Skip to content

Commit ba67a62

Browse files
authored
quota: skip usage records registering the period a volume has been attached (#13936)
1 parent 8b72a16 commit ba67a62

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.apache.cloudstack.quota.vo.QuotaTariffUsageVO;
5555
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
5656
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
57+
import org.apache.cloudstack.usage.UsageTypes;
5758
import org.apache.cloudstack.usage.UsageUnitTypes;
5859
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
5960
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
@@ -366,6 +367,11 @@ protected boolean shouldCalculateUsageRecord(AccountVO accountVO, UsageVO usageR
366367
usageRecord.toString(usageAggregationTimeZone), accountVO.reflectionToString());
367368
return false;
368369
}
370+
if (usageRecord.getUsageType() == UsageTypes.VOLUME && usageRecord.getVmInstanceId() != null) {
371+
logger.debug("Considering usage record [{}] as calculated and skipping it because it represents the period " +
372+
"a volume has remained attached to an instance, which Quota does not handle.", usageRecord.toString(usageAggregationTimeZone));
373+
return false;
374+
}
369375
return true;
370376
}
371377

framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,29 @@
2626
import java.util.List;
2727
import java.util.Map;
2828

29+
import org.apache.cloudstack.framework.config.ConfigKey;
30+
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
2931
import org.apache.cloudstack.quota.activationrule.presetvariables.Domain;
3032
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
3133
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
3234
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
3335
import org.apache.cloudstack.quota.activationrule.presetvariables.Tariff;
3436
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
37+
import org.apache.cloudstack.quota.constant.QuotaConfig;
3538
import org.apache.cloudstack.quota.constant.QuotaTypes;
3639
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
3740
import org.apache.cloudstack.quota.dao.QuotaTariffUsageDao;
3841
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
3942
import org.apache.cloudstack.quota.vo.QuotaTariffUsageVO;
4043
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
4144
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
45+
import org.apache.cloudstack.usage.UsageTypes;
4246
import org.apache.cloudstack.usage.UsageUnitTypes;
4347
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
4448
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
49+
import org.junit.After;
4550
import org.junit.Assert;
51+
import org.junit.Before;
4652
import org.junit.Test;
4753
import org.junit.runner.RunWith;
4854
import org.mockito.InjectMocks;
@@ -95,8 +101,21 @@ public class QuotaManagerImplTest {
95101
@Mock
96102
QuotaTariffUsageDao quotaTariffUsageDaoMock;
97103

104+
@Mock
105+
ConfigDepotImpl configDepotImplMock;
106+
98107
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
99108

109+
@Before
110+
public void setup() {
111+
ConfigKey.init(configDepotImplMock);
112+
}
113+
114+
@After
115+
public void tearDown() {
116+
ConfigKey.init(null);
117+
}
118+
100119
@Test
101120
public void isLockableTestValidateAccountTypes() {
102121
List<Account.Type> lockablesAccountTypes = Arrays.asList(Account.Type.NORMAL, Account.Type.DOMAIN_ADMIN);
@@ -113,6 +132,49 @@ public void isLockableTestValidateAccountTypes() {
113132
});
114133
}
115134

135+
@Test
136+
public void shouldCalculateUsageRecordTestQuotaIsDisabledForAccountReturnFalse() {
137+
Mockito.doReturn(1L).when(accountVoMock).getAccountId();
138+
Mockito.doReturn("false").when(configDepotImplMock).getConfigStringValue(Mockito.eq(QuotaConfig.QuotaAccountEnabled.key()), Mockito.eq(ConfigKey.Scope.Account),
139+
Mockito.eq(1L));
140+
141+
boolean result = quotaManagerImplSpy.shouldCalculateUsageRecord(accountVoMock, usageVoMock);
142+
143+
Assert.assertFalse(result);
144+
}
145+
146+
@Test
147+
public void shouldCalculateUsageRecordTestQuotaIsEnabledForAccountAndUsageRecordIsVolumeWithVmInstanceIdReturnFalse() {
148+
Mockito.doReturn(1L).when(accountVoMock).getAccountId();
149+
Mockito.doReturn(UsageTypes.VOLUME).when(usageVoMock).getUsageType();
150+
Mockito.doReturn(1L).when(usageVoMock).getVmInstanceId();
151+
152+
boolean result = quotaManagerImplSpy.shouldCalculateUsageRecord(accountVoMock, usageVoMock);
153+
154+
Assert.assertFalse(result);
155+
}
156+
157+
@Test
158+
public void shouldCalculateUsageRecordTestQuotaIsEnabledForAccountAndUsageRecordIsVolumeWithoutVmInstanceIdReturnTrue() {
159+
Mockito.doReturn(1L).when(accountVoMock).getAccountId();
160+
Mockito.doReturn(UsageTypes.VOLUME).when(usageVoMock).getUsageType();
161+
Mockito.doReturn(null).when(usageVoMock).getVmInstanceId();
162+
163+
boolean result = quotaManagerImplSpy.shouldCalculateUsageRecord(accountVoMock, usageVoMock);
164+
165+
Assert.assertTrue(result);
166+
}
167+
168+
@Test
169+
public void shouldCalculateUsageRecordTestQuotaIsEnabledForAccountAndUsageRecordIsNotVolumeReturnTrue() {
170+
Mockito.doReturn(1L).when(accountVoMock).getAccountId();
171+
Mockito.doReturn(UsageTypes.RUNNING_VM).when(usageVoMock).getUsageType();
172+
173+
boolean result = quotaManagerImplSpy.shouldCalculateUsageRecord(accountVoMock, usageVoMock);
174+
175+
Assert.assertTrue(result);
176+
}
177+
116178
@Test
117179
public void getPendingUsageRecordsForQuotaAggregationTestNullListReturnNull() {
118180
Mockito.doReturn(pairMock).when(usageDaoMock).listUsageRecordsPendingForQuotaAggregation(Mockito.anyLong(), Mockito.anyLong());

0 commit comments

Comments
 (0)