Repository: cloudstack Updated Branches: refs/heads/master ee2bc828a -> 06fe7844d
CLOUDSTACK-9161: fix the quota marvin test 1. Create a dummy user, as existing user may already have stale quota data 2. fix the tests to use the dummy user 3. a boundary condition was revealed and fixed for a new user where quota service has never run and created bootstrap entries Quota Marvin: If the quota plugin is not enabled skip tests Quota Service: Enable quota plugin in zone setup configuration Quota: Moving test_quota.py the test to test/integration/plugins In most automated environment this test case will not run as it requires a mangement server restart to enable the plugin. Due to this requirement moving it to plugin folder. This condition is already documented in the test case. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ccd0f220 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ccd0f220 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ccd0f220 Branch: refs/heads/master Commit: ccd0f22061fe72f97c1a6352d8d004e809c04dde Parents: 94a1448 Author: Abhinandan Prateek <abhinandan.prat...@shapeblue.com> Authored: Mon Dec 14 12:10:48 2015 +0530 Committer: Abhinandan Prateek <abhinandan.prat...@shapeblue.com> Committed: Wed Dec 16 16:22:31 2015 +0530 ---------------------------------------------------------------------- .../cloudstack/quota/QuotaManagerImpl.java | 4 +- .../cloudstack/quota/vo/QuotaBalanceVO.java | 10 +- .../api/response/QuotaResponseBuilderImpl.java | 2 +- test/integration/plugins/test_quota.py | 267 +++++++++++++++++++ test/integration/smoke/test_quota.py | 204 -------------- tools/marvin/marvin/config/setup.cfg | 4 + 6 files changed, 282 insertions(+), 209 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/framework/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java ---------------------------------------------------------------------- diff --git a/framework/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java b/framework/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java index b039e26..ac14718 100644 --- a/framework/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java +++ b/framework/quota/src/org/apache/cloudstack/quota/QuotaManagerImpl.java @@ -220,7 +220,9 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager { _quotaBalanceDao.saveQuotaBalance(firstBalance); } else { QuotaBalanceVO lastRealBalanceEntry = _quotaBalanceDao.findLastBalanceEntry(account.getAccountId(), account.getDomainId(), endDate); - aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance()); + if (lastRealBalanceEntry != null){ + aggrUsage = aggrUsage.add(lastRealBalanceEntry.getCreditBalance()); + } if (s_logger.isDebugEnabled()) { s_logger.debug("Last balance entry " + lastRealBalanceEntry + " AggrUsage=" + aggrUsage); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java ---------------------------------------------------------------------- diff --git a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java index b454a14..509702a 100644 --- a/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java +++ b/framework/quota/src/org/apache/cloudstack/quota/vo/QuotaBalanceVO.java @@ -62,7 +62,7 @@ public class QuotaBalanceVO implements InternalIdentity { this.accountId = credit.getAccountId(); this.domainId = credit.getDomainId(); this.creditBalance = credit.getCredit(); - this.updatedOn = credit.getUpdatedOn() == null ? null : new Date(credit.getUpdatedOn().getTime()); + this.updatedOn = credit.getUpdatedOn() == null ? null : new Date(credit.getUpdatedOn().getTime()); this.creditsId = credit.getId(); } @@ -72,7 +72,7 @@ public class QuotaBalanceVO implements InternalIdentity { this.domainId = domainId; this.creditBalance = creditBalance; this.creditsId = 0L; - this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime()); + this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime()); } @Override @@ -108,6 +108,10 @@ public class QuotaBalanceVO implements InternalIdentity { this.creditsId = creditsId; } + public boolean isBalanceEntry(){ + return creditsId==0; + } + public BigDecimal getCreditBalance() { return creditBalance; } @@ -121,7 +125,7 @@ public class QuotaBalanceVO implements InternalIdentity { } public void setUpdatedOn(Date updatedOn) { - this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime()); + this.updatedOn = updatedOn == null ? null : new Date(updatedOn.getTime()); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java ---------------------------------------------------------------------- diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java index 1b6f400..51a654c 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java @@ -186,7 +186,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { //check that there is at least one balance entry for (Iterator<QuotaBalanceVO> it = quotaBalance.iterator(); it.hasNext();) { QuotaBalanceVO entry = it.next(); - if (entry.getCreditsId() > 0) { + if (entry.isBalanceEntry()) { have_balance_entries = true; break; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/test/integration/plugins/test_quota.py ---------------------------------------------------------------------- diff --git a/test/integration/plugins/test_quota.py b/test/integration/plugins/test_quota.py new file mode 100644 index 0000000..1ae6790 --- /dev/null +++ b/test/integration/plugins/test_quota.py @@ -0,0 +1,267 @@ +# 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 marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.lib.utils import (random_gen) +from nose.plugins.attrib import attr + +#Import System modules +import time + +class TestQuota(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + # Create Account + testClient = super(TestQuota, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + + # Create Account + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.account, + ] + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + self.dbclient = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + #Check quotaTariffList API returning 22 items + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_01_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaTariffList.quotaTariffListCmd() + response = self.apiclient.quotaTariffList(cmd) + + self.debug("Number of quota usage types: %s" % len(response)) + self.assertEqual( + len(response), 22 + ) + for quota in response: + self.debug("Usage Name: %s" % quota.usageName) + self.assertEqual( + hasattr(quota, 'usageName'), + True, + "Check whether usgaeName field is there" + ) + + return + + #Check quota tariff on a particualr day + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_02_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaTariffList.quotaTariffListCmd() + cmd.startdate='2015-07-06' + response = self.apiclient.quotaTariffList(cmd) + + self.debug("Number of quota usage types: %s" % len(response)) + self.assertEqual( + len(response), 22 + ) + + return + + #check quota tariff of a particular item + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_03_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaTariffList.quotaTariffListCmd() + cmd.startdate='2015-07-06' + cmd.usagetype='10' + response = self.apiclient.quotaTariffList(cmd) + + self.debug("Number of quota usage types: %s" % len(response)) + self.assertEqual( + len(response), 1 + ) + return + + + #check quota tariff + #Change it + #Check on affective date the new tariff should be applicable + #check the old tariff it should be same + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_04_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaTariffList.quotaTariffListCmd() + cmd.startdate='2015-07-06' + cmd.usagetype='10' + response = self.apiclient.quotaTariffList(cmd) + + self.debug("Number of quota usage types: %s" % len(response)) + self.assertEqual( + len(response), 1 + ) + quota = response[0] + self.debug("Tariff Value for 10: %s" % quota.tariffValue) + + cmd = quotaTariffUpdate.quotaTariffUpdateCmd() + tomorrow = datetime.date.today() + datetime.timedelta(days=1) + cmd.startdate=tomorrow + cmd.usagetype='10' + cmd.value='2.9' + response = self.apiclient.quotaTariffUpdate(cmd) + + cmd = quotaTariffList.quotaTariffListCmd() + cmd.startdate=tomorrow + cmd.usagetype='10' + response = self.apiclient.quotaTariffList(cmd) + self.assertEqual( + len(response), 1 + ) + quota = response[0] + self.debug("Tariff Value for 10: %s" % quota.tariffValue) + + self.assertEqual( quota.tariffValue, 2.9) + + + cmd = quotaTariffList.quotaTariffListCmd() + cmd.startdate='2015-07-07' + cmd.usagetype='10' + response = self.apiclient.quotaTariffList(cmd) + self.assertEqual( + len(response), 1 + ) + quota = response[0] + self.debug("Tariff Value for 10: %s" % quota.tariffValue) + + self.assertEqual( quota.tariffValue, 0) + + return + + + #Make credit deposit + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_05_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaCredits.quotaCreditsCmd() + cmd.domainid = self.account.domainid + cmd.account = self.account.name + cmd.value = '10' + cmd.quota_enforce = '1' + cmd.min_balance = '9' + response = self.apiclient.quotaCredits(cmd) + + self.debug("Credit response update on: %s" % response.updated_on) + + return + + + #Make credit deposit and check today balance + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_06_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaBalance.quotaBalanceCmd() + today = datetime.date.today() + cmd.domainid = self.account.domainid + cmd.account = self.account.name + cmd.startdate = today + response = self.apiclient.quotaBalance(cmd) + + self.debug("Quota Balance on: %s" % response.startdate) + self.debug("is: %s" % response.startquota) + + self.assertEqual( response.startquota, 10) + return + + #make credit deposit and check start and end date balances + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_07_quota(self): + if not is_config_suitable( + apiclient=self.apiclient, + name='quota.enable.service', + value='true'): + self.skipTest('quota.enable.service should be true. skipping') + + cmd = quotaBalance.quotaBalanceCmd() + today = datetime.date.today() + cmd.domainid = self.account.domainid + cmd.account = self.account.name + cmd.startdate = today - datetime.timedelta(days=2) + cmd.enddate = today + response = self.apiclient.quotaBalance(cmd) + + self.debug("Quota Balance on: %s" % response.startdate) + self.debug("is: %s" % response.startquota) + + self.assertEqual( response.startquota, 0) + self.assertEqual( response.endquota, 10) + return http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/test/integration/smoke/test_quota.py ---------------------------------------------------------------------- diff --git a/test/integration/smoke/test_quota.py b/test/integration/smoke/test_quota.py deleted file mode 100644 index d4e4323..0000000 --- a/test/integration/smoke/test_quota.py +++ /dev/null @@ -1,204 +0,0 @@ -# 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 marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.lib.utils import * -from marvin.lib.base import * -from marvin.lib.common import * -from marvin.lib.utils import (random_gen) -from nose.plugins.attrib import attr - -#Import System modules -import time - -#ENABLE THE QUOTA PLUGIN AND RESTART THE MANAGEMENT SERVER TO RUN QUOTA TESTS - -class TestQuota(cloudstackTestCase): - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.hypervisor = self.testClient.getHypervisorInfo() - self.dbclient = self.testClient.getDbConnection() - self.services = self.testClient.getParsedTestDataConfig() - self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) - self.pod = get_pod(self.apiclient, self.zone.id) - self.cleanup = [] - return - - def tearDown(self): - try: - #Clean up, terminate the created templates - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return - - #Check quotaTariffList API returning 22 items - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_01_quota(self): - cmd = quotaTariffList.quotaTariffListCmd() - response = self.apiclient.quotaTariffList(cmd) - - self.debug("Number of quota usage types: %s" % len(response)) - self.assertEqual( - len(response), 22 - ) - for quota in response: - self.debug("Usage Name: %s" % quota.usageName) - self.assertEqual( - hasattr(quota, 'usageName'), - True, - "Check whether usgaeName field is there" - ) - - return - - #Check quota tariff on a particualr day - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_02_quota(self): - cmd = quotaTariffList.quotaTariffListCmd() - cmd.startdate='2015-07-06' - response = self.apiclient.quotaTariffList(cmd) - - self.debug("Number of quota usage types: %s" % len(response)) - self.assertEqual( - len(response), 22 - ) - - return - - #check quota tariff of a particular item - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_03_quota(self): - cmd = quotaTariffList.quotaTariffListCmd() - cmd.startdate='2015-07-06' - cmd.usagetype='10' - response = self.apiclient.quotaTariffList(cmd) - - self.debug("Number of quota usage types: %s" % len(response)) - self.assertEqual( - len(response), 1 - ) - return - - - #check quota tariff - #Change it - #Check on affective date the new tariff should be applicable - #check the old tariff it should be same - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_04_quota(self): - cmd = quotaTariffList.quotaTariffListCmd() - cmd.startdate='2015-07-06' - cmd.usagetype='10' - response = self.apiclient.quotaTariffList(cmd) - - self.debug("Number of quota usage types: %s" % len(response)) - self.assertEqual( - len(response), 1 - ) - quota = response[0] - self.debug("Tariff Value for 10: %s" % quota.tariffValue) - - cmd = quotaTariffUpdate.quotaTariffUpdateCmd() - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - cmd.startdate=tomorrow - cmd.usagetype='10' - cmd.value='2.9' - response = self.apiclient.quotaTariffUpdate(cmd) - - cmd = quotaTariffList.quotaTariffListCmd() - cmd.startdate=tomorrow - cmd.usagetype='10' - response = self.apiclient.quotaTariffList(cmd) - self.assertEqual( - len(response), 1 - ) - quota = response[0] - self.debug("Tariff Value for 10: %s" % quota.tariffValue) - - self.assertEqual( quota.tariffValue, 2.9) - - - cmd = quotaTariffList.quotaTariffListCmd() - cmd.startdate='2015-07-07' - cmd.usagetype='10' - response = self.apiclient.quotaTariffList(cmd) - self.assertEqual( - len(response), 1 - ) - quota = response[0] - self.debug("Tariff Value for 10: %s" % quota.tariffValue) - - self.assertEqual( quota.tariffValue, 0) - - return - - - #Make credit deposit - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_05_quota(self): - cmd = quotaCredits.quotaCreditsCmd() - cmd.domainid = '1' - cmd.account = 'admin' - cmd.value = '10' - cmd.quota_enforce = '1' - cmd.min_balance = '9' - response = self.apiclient.quotaCredits(cmd) - - self.debug("Credit response update on: %s" % response.updated_on) - - return - - - #Make credit deposit and check today balance - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_06_quota(self): - cmd = quotaBalance.quotaBalanceCmd() - today = datetime.date.today() - cmd.domainid = '1' - cmd.account = 'admin' - cmd.startdate = today - response = self.apiclient.quotaBalance(cmd) - - self.debug("Quota Balance on: %s" % response.startdate) - self.debug("is: %s" % response.startquota) - - self.assertGreater( response.startquota, 9) - return - - #make credit deposit and check start and end date balances - @attr(tags=["smoke", "advanced"], required_hardware="false") - def test_07_quota(self): - cmd = quotaBalance.quotaBalanceCmd() - today = datetime.date.today() - cmd.domainid = '1' - cmd.account = 'admin' - cmd.startdate = today - datetime.timedelta(days=2) - cmd.enddate = today - response = self.apiclient.quotaBalance(cmd) - - self.debug("Quota Balance on: %s" % response.startdate) - self.debug("is: %s" % response.startquota) - - self.assertGreater( response.endquota, 9) - return http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ccd0f220/tools/marvin/marvin/config/setup.cfg ---------------------------------------------------------------------- diff --git a/tools/marvin/marvin/config/setup.cfg b/tools/marvin/marvin/config/setup.cfg index 23981f0..f694bba 100644 --- a/tools/marvin/marvin/config/setup.cfg +++ b/tools/marvin/marvin/config/setup.cfg @@ -143,6 +143,10 @@ }, "globalConfig": [ { + "name": "quota.enable.service", + "value": "true" + }, + { "name": "network.gc.wait", "value": "60" },