Quota tariff order (#8347)

This commit is contained in:
João Jandre 2024-07-14 11:05:15 -03:00 committed by GitHub
parent a87778be9a
commit b9c7275c25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 351 additions and 21 deletions

View File

@ -150,3 +150,7 @@ SET
WHERE
name IN ("quota.usage.smtp.useStartTLS", "quota.usage.smtp.useAuth", "alert.smtp.useAuth", "project.smtp.useAuth")
AND value NOT IN ("true", "y", "t", "1", "on", "yes");
-- Quota inject tariff result into subsequent ones
CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.quota_tariff', 'position', 'bigint(20) NOT NULL DEFAULT 1 COMMENT "Position in the execution sequence for tariffs of the same type"');

View File

@ -20,6 +20,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
@ -36,6 +37,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
import org.apache.cloudstack.quota.activationrule.presetvariables.Tariff;
import org.apache.cloudstack.quota.constant.QuotaConfig;
import org.apache.cloudstack.quota.constant.QuotaTypes;
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
@ -371,9 +373,22 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
PresetVariables presetVariables = getPresetVariables(hasAnyQuotaTariffWithActivationRule, usageRecord);
BigDecimal aggregatedQuotaTariffsValue = BigDecimal.ZERO;
quotaTariffs.sort(Comparator.comparing(QuotaTariffVO::getPosition));
List<Tariff> lastTariffs = new ArrayList<>();
for (QuotaTariffVO quotaTariff : quotaTariffs) {
if (isQuotaTariffInPeriodToBeApplied(usageRecord, quotaTariff, accountToString)) {
aggregatedQuotaTariffsValue = aggregatedQuotaTariffsValue.add(getQuotaTariffValueToBeApplied(quotaTariff, jsInterpreter, presetVariables));
BigDecimal tariffValue = getQuotaTariffValueToBeApplied(quotaTariff, jsInterpreter, presetVariables, lastTariffs);
aggregatedQuotaTariffsValue = aggregatedQuotaTariffsValue.add(tariffValue);
Tariff tariffPresetVariable = new Tariff();
tariffPresetVariable.setId(quotaTariff.getUuid());
tariffPresetVariable.setValue(tariffValue);
lastTariffs.add(tariffPresetVariable);
}
}
@ -401,7 +416,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
* <li>If the activation rule result in something else, returns {@link BigDecimal#ZERO}.</li>
* </ul>
*/
protected BigDecimal getQuotaTariffValueToBeApplied(QuotaTariffVO quotaTariff, JsInterpreter jsInterpreter, PresetVariables presetVariables) {
protected BigDecimal getQuotaTariffValueToBeApplied(QuotaTariffVO quotaTariff, JsInterpreter jsInterpreter, PresetVariables presetVariables, List<Tariff> lastAppliedTariffsList) {
String activationRule = quotaTariff.getActivationRule();
BigDecimal quotaTariffValue = quotaTariff.getCurrencyValue();
String quotaTariffToString = quotaTariff.toString(usageAggregationTimeZone);
@ -413,6 +428,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
injectPresetVariablesIntoJsInterpreter(jsInterpreter, presetVariables);
jsInterpreter.injectVariable("lastTariffs", lastAppliedTariffsList.toString());
String scriptResult = jsInterpreter.executeScript(activationRule).toString();

View File

@ -0,0 +1,33 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.quota.activationrule.presetvariables;
import java.math.BigDecimal;
public class Tariff extends GenericPresetVariable {
private BigDecimal value;
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
fieldNamesToIncludeInToString.add("value");
}
}

View File

@ -93,6 +93,10 @@ public class QuotaTariffVO implements QuotaTariff {
@Temporal(value = TemporalType.TIMESTAMP)
private Date endDate;
@Column(name = "position")
protected Integer position;
public QuotaTariffVO() {
}
@ -120,6 +124,7 @@ public class QuotaTariffVO implements QuotaTariff {
this.setDescription(that.getDescription());
this.setActivationRule(that.getActivationRule());
this.setEndDate(that.getEndDate());
this.setPosition(that.getPosition());
}
public void setId(Long id) {
@ -263,6 +268,15 @@ public class QuotaTariffVO implements QuotaTariff {
return true;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
@Override
public String toString() {
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "uuid", "name", "usageName");

View File

@ -29,6 +29,7 @@ import org.apache.cloudstack.quota.activationrule.presetvariables.Domain;
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
import org.apache.cloudstack.quota.activationrule.presetvariables.Tariff;
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
import org.apache.cloudstack.quota.constant.QuotaTypes;
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
@ -395,7 +396,7 @@ public class QuotaManagerImplTest {
Mockito.doReturn(null).when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(BigDecimal.ONE).when(quotaTariffVoMock).getCurrencyValue();
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null, null);
Assert.assertEquals(BigDecimal.ONE, result);
}
@ -405,7 +406,7 @@ public class QuotaManagerImplTest {
Mockito.doReturn("").when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, null, null, null);
Assert.assertEquals(BigDecimal.TEN, result);
}
@ -413,13 +414,15 @@ public class QuotaManagerImplTest {
@Test
public void getQuotaTariffValueToBeAppliedTestScriptResultIsNumberReturnIt() {
BigDecimal expected = new BigDecimal(50.1);
List<Tariff> lastTariffs = createLastAppliedTariffsPresetVariableList(0);
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
Mockito.doReturn(expected).when(jsInterpreterMock).executeScript(Mockito.anyString());
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock, lastTariffs);
Assert.assertEquals(expected, result);
}
@ -427,37 +430,42 @@ public class QuotaManagerImplTest {
@Test
public void getQuotaTariffValueToBeAppliedTestScriptResultIsTrueReturnTariffValue() {
BigDecimal expected = new BigDecimal(236.84);
List<Tariff> lastTariffs = createLastAppliedTariffsPresetVariableList(0);
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(expected).when(quotaTariffVoMock).getCurrencyValue();
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
Mockito.doReturn(true).when(jsInterpreterMock).executeScript(Mockito.anyString());
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock, lastTariffs);
Assert.assertEquals(expected, result);
}
@Test
public void getQuotaTariffValueToBeAppliedTestScriptResultIsFalseReturnZero() {
List<Tariff> lastTariffs = createLastAppliedTariffsPresetVariableList(0);
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
Mockito.doReturn(false).when(jsInterpreterMock).executeScript(Mockito.anyString());
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock, lastTariffs);
Assert.assertEquals(BigDecimal.ZERO, result);
}
@Test
public void getQuotaTariffValueToBeAppliedTestScriptResultIsNotBooleanNorNumericReturnZero() {
List<Tariff> lastTariffs = createLastAppliedTariffsPresetVariableList(0);
Mockito.doReturn(" ").when(quotaTariffVoMock).getActivationRule();
Mockito.doReturn(BigDecimal.TEN).when(quotaTariffVoMock).getCurrencyValue();
Mockito.doNothing().when(quotaManagerImplSpy).injectPresetVariablesIntoJsInterpreter(Mockito.any(), Mockito.any());
Mockito.doReturn("test").when(jsInterpreterMock).executeScript(Mockito.anyString());
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock);
BigDecimal result = quotaManagerImplSpy.getQuotaTariffValueToBeApplied(quotaTariffVoMock, jsInterpreterMock, presetVariablesMock, lastTariffs);
Assert.assertEquals(BigDecimal.ZERO, result);
}
@ -477,10 +485,7 @@ public class QuotaManagerImplTest {
@Test
public void aggregateQuotaTariffsValuesTestTariffsWereNotInPeriodToBeAppliedReturnZero() {
List<QuotaTariffVO> tariffs = new ArrayList<>();
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
List<QuotaTariffVO> tariffs = createTariffList();
Mockito.doReturn(false).when(quotaManagerImplSpy).isQuotaTariffInPeriodToBeApplied(Mockito.any(), Mockito.any(), Mockito.anyString());
BigDecimal result = quotaManagerImplSpy.aggregateQuotaTariffsValues(usageVoMock, tariffs, false, jsInterpreterMock, "");
@ -497,13 +502,10 @@ public class QuotaManagerImplTest {
@Test
public void aggregateQuotaTariffsValuesTestTariffsAreInPeriodToBeAppliedReturnAggregation() {
List<QuotaTariffVO> tariffs = new ArrayList<>();
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
List<QuotaTariffVO> tariffs = createTariffList();
Mockito.doReturn(true, false, true).when(quotaManagerImplSpy).isQuotaTariffInPeriodToBeApplied(Mockito.any(), Mockito.any(), Mockito.anyString());
Mockito.doReturn(BigDecimal.TEN).when(quotaManagerImplSpy).getQuotaTariffValueToBeApplied(Mockito.any(), Mockito.any(), Mockito.any());
Mockito.doReturn(BigDecimal.TEN).when(quotaManagerImplSpy).getQuotaTariffValueToBeApplied(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
BigDecimal result = quotaManagerImplSpy.aggregateQuotaTariffsValues(usageVoMock, tariffs, false, jsInterpreterMock, "");
Assert.assertEquals(BigDecimal.TEN.multiply(new BigDecimal(2)), result);
@ -528,4 +530,25 @@ public class QuotaManagerImplTest {
Assert.assertEquals(quotaUsageVoMock1, result.get(0));
Assert.assertEquals(quotaUsageVoMock2, result.get(1));
}
private static List<QuotaTariffVO> createTariffList() {
List<QuotaTariffVO> tariffs = new ArrayList<>();
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
tariffs.add(new QuotaTariffVO());
tariffs.forEach(quotaTariffVO -> quotaTariffVO.setPosition(1));
return tariffs;
}
private static List<Tariff> createLastAppliedTariffsPresetVariableList(int numberOfTariffs) {
List<Tariff> lastTariffs = new ArrayList<>();
for (int i = 0; i < numberOfTariffs; i++) {
Tariff tariff = new Tariff();
tariff.setId(String.valueOf(i));
tariff.setValue(BigDecimal.valueOf(i));
lastTariffs.add(tariff);
}
return lastTariffs;
}
}

View File

@ -68,6 +68,9 @@ public class QuotaTariffCreateCmd extends BaseCmd {
ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS)
private Date endDate;
@Parameter(name = ApiConstants.POSITION, type = CommandType.INTEGER, description = "Position in the execution sequence for tariffs of the same type", since = "4.20.0.0")
private Integer position;
@Override
public void execute() {
CallContext.current().setEventDetails(String.format("Tariff: %s, description: %s, value: %s", getName(), getDescription(), getValue()));
@ -139,4 +142,13 @@ public class QuotaTariffCreateCmd extends BaseCmd {
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.QuotaTariff;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
}

View File

@ -69,6 +69,9 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
"value will be applied. Inform empty to remove the activation rule.", length = 65535, since = "4.18.0.0")
private String activationRule;
@Parameter(name = ApiConstants.POSITION, type = CommandType.INTEGER, description = "Position in the execution sequence for tariffs of the same type", since = "4.20.0.0")
private Integer position;
public Integer getUsageType() {
return usageType;
}
@ -130,4 +133,13 @@ public class QuotaTariffUpdateCmd extends BaseCmd {
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.QuotaTariff;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
}

View File

@ -80,6 +80,7 @@ import org.apache.cloudstack.quota.vo.QuotaUsageVO;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.stereotype.Component;
@ -151,6 +152,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
response.setDescription(tariff.getDescription());
response.setId(tariff.getUuid());
response.setRemoved(tariff.getRemoved());
response.setPosition(tariff.getPosition());
return response;
}
@ -414,6 +416,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
String description = cmd.getDescription();
String activationRule = cmd.getActivationRule();
Date now = new Date();
Integer position = cmd.getPosition();
warnQuotaTariffUpdateDeprecatedFields(cmd);
@ -428,7 +431,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
currentQuotaTariff.setRemoved(now);
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(currentQuotaTariff, name, 0, currentQuotaTariffStartDate, cmd.getEntityOwnerId(), endDate, value, description,
activationRule);
activationRule, position);
_quotaTariffDao.updateQuotaTariff(currentQuotaTariff);
CallContext.current().setEventResourceId(newQuotaTariff.getId());
@ -449,7 +452,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
}
protected QuotaTariffVO persistNewQuotaTariff(QuotaTariffVO currentQuotaTariff, String name, int usageType, Date startDate, Long entityOwnerId, Date endDate, Double value,
String description, String activationRule) {
String description, String activationRule, Integer position) {
QuotaTariffVO newQuotaTariff = getNewQuotaTariffObject(currentQuotaTariff, name, usageType);
@ -461,6 +464,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
validateValueOnCreatingNewQuotaTariff(newQuotaTariff, value);
validateStringsOnCreatingNewQuotaTariff(newQuotaTariff::setDescription, description);
validateStringsOnCreatingNewQuotaTariff(newQuotaTariff::setActivationRule, activationRule);
validatePositionOnCreatingNewQuotaTariff(newQuotaTariff, position);
_quotaTariffDao.addQuotaTariff(newQuotaTariff);
return newQuotaTariff;
@ -481,6 +485,13 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
return newQuotaTariff;
}
protected void validatePositionOnCreatingNewQuotaTariff(QuotaTariffVO newQuotaTariff, Integer position) {
if (position != null) {
newQuotaTariff.setPosition(position);
}
}
protected void validateStringsOnCreatingNewQuotaTariff(Consumer<String> method, String value){
if (value != null) {
method.accept(value.isBlank() ? null : value);
@ -663,6 +674,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
Double value = cmd.getValue();
String description = cmd.getDescription();
String activationRule = cmd.getActivationRule();
Integer position = ObjectUtils.defaultIfNull(cmd.getPosition(), 1);
QuotaTariffVO currentQuotaTariff = _quotaTariffDao.findByName(name);
@ -675,7 +687,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
"Please, inform a date in the future or do not pass the parameter to use the current date and time.", startDate));
}
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule);
QuotaTariffVO newQuotaTariff = persistNewQuotaTariff(null, name, usageType, startDate, cmd.getEntityOwnerId(), endDate, value, description, activationRule, position);
CallContext.current().setEventResourceId(newQuotaTariff.getId());

View File

@ -83,6 +83,11 @@ public class QuotaTariffResponse extends BaseResponse {
@Param(description = "when the quota tariff was removed")
private Date removed;
@SerializedName("position")
@Param(description = "position in the execution sequence for tariffs of the same type")
private Integer position;
public QuotaTariffResponse() {
super();
this.setObjectName("quotatariff");
@ -172,4 +177,12 @@ public class QuotaTariffResponse extends BaseResponse {
this.removed = removed;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
}

View File

@ -372,8 +372,10 @@ public class QuotaResponseBuilderImplTest extends TestCase {
Mockito.doNothing().when(quotaResponseBuilderSpy).validateValueOnCreatingNewQuotaTariff(Mockito.any(QuotaTariffVO.class), Mockito.anyDouble());
Mockito.doNothing().when(quotaResponseBuilderSpy).validateStringsOnCreatingNewQuotaTariff(Mockito.any(Consumer.class), Mockito.anyString());
Mockito.doReturn(quotaTariffVoMock).when(quotaTariffDaoMock).addQuotaTariff(Mockito.any(QuotaTariffVO.class));
Mockito.doNothing().when(quotaResponseBuilderSpy).validatePositionOnCreatingNewQuotaTariff(Mockito.any(QuotaTariffVO.class), Mockito.anyInt());
quotaResponseBuilderSpy.persistNewQuotaTariff(quotaTariffVoMock, "", 1, date, 1l, date, 1.0, "", "");
quotaResponseBuilderSpy.persistNewQuotaTariff(quotaTariffVoMock, "", 1, date, 1l, date, 1.0, "", "", 2);
Mockito.verify(quotaTariffDaoMock).addQuotaTariff(Mockito.any(QuotaTariffVO.class));
}
@ -553,4 +555,18 @@ public class QuotaResponseBuilderImplTest extends TestCase {
assertEquals(2, result.getEmailTemplateId());
assertFalse(result.isEnabled());
}
@Test
public void validatePositionOnCreatingNewQuotaTariffTestNullValueDoNothing() {
quotaResponseBuilderSpy.validatePositionOnCreatingNewQuotaTariff(quotaTariffVoMock, null);
Mockito.verify(quotaTariffVoMock, Mockito.never()).setPosition(Mockito.any());
}
@Test
public void validatePositionOnCreatingNewQuotaTariffTestAnyValueIsSet() {
Integer position = 1;
quotaResponseBuilderSpy.validatePositionOnCreatingNewQuotaTariff(quotaTariffVoMock, position);
Mockito.verify(quotaTariffVoMock).setPosition(position);
}
}

View File

@ -0,0 +1,175 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
""" Test cases for checking quota API
"""
# Import Local Modules
import tools.marvin.marvin
from tools.marvin.marvin.cloudstackTestCase import *
from tools.marvin.marvin.cloudstackAPI import *
from tools.marvin.marvin.lib.utils import *
from tools.marvin.marvin.lib.base import *
from tools.marvin.marvin.lib.common import *
from nose.plugins.attrib import attr
# Import System modules
import time
class TestQuotaTariffOrder(cloudstackTestCase):
@classmethod
def setUpClass(cls):
testClient = super(TestQuotaTariffOrder, cls).getClsTestClient()
cls.api_client = testClient.getApiClient()
cls.services = testClient.getParsedTestDataConfig()
# Get Zone, Domain and templates
cls.domain = get_domain(cls.api_client)
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
cls._cleanup = []
# Create Account
cls.account = Account.create(
cls.api_client,
cls.services["account"],
domainid=cls.domain.id
)
cls._cleanup.append(cls.account)
cls.services["account"] = cls.account.name
return
@classmethod
def tearDownClass(cls):
super(TestQuotaTariffOrder, cls).tearDownClass()
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.cleanup = []
self.tariffs = []
return
def tearDown(self):
self.delete_tariffs()
super(TestQuotaTariffOrder, self).tearDown()
def delete_tariffs(self):
for tariff in self.tariffs:
cmd = quotaTariffDelete.quotaTariffDeleteCmd()
cmd.id = tariff.uuid
self.api_client.quotaTariffDelete(cmd)
@attr(
tags=[
"advanced",
"smoke"],
required_hardware="false")
def test_01_quota_tariff_order(self):
"""Test Quota Tariff Order
"""
cmd = quotaTariffCreate.quotaTariffCreateCmd()
cmd.name = 'tf1'
cmd.value = '1'
cmd.activationrule = '10'
cmd.usagetype = '22'
cmd.position = '2'
self.tariffs.append(self.api_client.quotaTariffCreate(cmd))
cmd = quotaTariffCreate.quotaTariffCreateCmd()
cmd.name = 'tf2'
cmd.value = '1'
cmd.activationrule = 'lastTariffs[lastTariffs.length -1].value + 7'
cmd.usagetype = '22'
cmd.position = '3'
self.tariffs.append(self.api_client.quotaTariffCreate(cmd))
cmd = quotaTariffCreate.quotaTariffCreateCmd()
cmd.name = 'tf3'
cmd.value = '1'
cmd.activationrule = 'lastTariffs[lastTariffs.length -2].value + lastTariffs[lastTariffs.length -1].value'
cmd.usagetype = '22'
cmd.position = '4'
self.tariffs.append(self.api_client.quotaTariffCreate(cmd))
cmd = quotaCredits.quotaCreditsCmd()
cmd.account = self.account.name
cmd.domainid = self.domain.id
cmd.value = 54
self.api_client.quotaCredits(cmd)
# Fetch account ID from account_uuid
self.debug("select id from account where uuid = '%s';"
% self.account.id)
qresultset = self.dbclient.execute(
"select id from account where uuid = '%s';"
% self.account.id
)
account_id = qresultset[0][0]
self.debug("SELECT id from `domain` d WHERE uuid = '%s';"
% self.domain.id)
qresultset = self.dbclient.execute(
"SELECT id from `domain` d WHERE uuid = '%s';"
% self.domain.id
)
domain_id = qresultset[0][0]
self.debug("SELECT id from data_center dc where dc.uuid = '%s';"
% self.zone.id)
qresultset = self.dbclient.execute(
"SELECT id from data_center dc where dc.uuid = '%s';"
% self.zone.id
)
zone_id = qresultset[0][0]
start = datetime.datetime.now() + datetime.timedelta(seconds=1)
end = datetime.datetime.now() + datetime.timedelta(hours=1)
query = "INSERT INTO cloud_usage.cloud_usage (zone_id,account_id,domain_id,description,usage_display,"
"usage_type,raw_usage,vm_instance_id,vm_name,offering_id,template_id,usage_id,`type`,`size`,"
"network_id,start_date,end_date,virtual_size,cpu_speed,cpu_cores,memory,quota_calculated,"
"is_hidden,state) VALUES ('{}','{}','{}','Test','1 Hrs',22,1,NULL,NULL,NULL,NULL,NULL,"
"'VirtualMachine',NULL,NULL,'{}','{}',NULL,NULL,NULL,NULL,0,0,NULL);".format(zone_id, account_id, domain_id, start, end)
self.debug(query)
self.dbclient.execute(
query)
cmd = quotaUpdate.quotaUpdateCmd()
self.api_client.quotaUpdate(cmd)
cmd = quotaBalance.quotaBalanceCmd()
cmd.domainid = self.account.domainid
cmd.account = self.account.name
response = self.apiclient.quotaBalance(cmd)
self.debug(f"Quota Balance: {response.balance}")
self.assertEqual(response.balance.startquota, 0, f"startQuota is supposed to be 0 but was {response.balance.startquota}")
return