From 2de67360fe34e5fdf80bd4884eaf6298d66491c7 Mon Sep 17 00:00:00 2001 From: Valeriy Ponomaryov Date: Fri, 9 Jun 2017 20:03:06 +0300 Subject: [PATCH] Add share groups and share group snapshots quotas "Quota" APIs now will return two new following keys: - 'share_groups' - 'share_group_snapshots' For user and project, but not share type. Default values can be configured using following config options: - 'quota_share_groups' - 'quota_share_group_snapshots' APIImpact DocImpact Implements BluePrint add-share-groups-quota Change-Id: I397a8e886226cb22fa50abdf2a4a938bb04c655d --- manila_tempest_tests/config.py | 2 +- .../services/share/v2/json/shares_client.py | 8 +- .../tests/api/admin/test_quotas.py | 248 ++++++++++++++++-- .../tests/api/admin/test_quotas_negative.py | 115 +++++--- 4 files changed, 305 insertions(+), 68 deletions(-) diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py index 8b27700d..9e4a1688 100644 --- a/manila_tempest_tests/config.py +++ b/manila_tempest_tests/config.py @@ -30,7 +30,7 @@ ShareGroup = [ help="The minimum api microversion is configured to be the " "value of the minimum microversion supported by Manila."), cfg.StrOpt("max_api_microversion", - default="2.39", + default="2.40", help="The maximum api microversion is configured to be the " "value of the latest microversion supported by Manila."), cfg.StrOpt("region", diff --git a/manila_tempest_tests/services/share/v2/json/shares_client.py b/manila_tempest_tests/services/share/v2/json/shares_client.py index 3631c68b..94e1ac60 100644 --- a/manila_tempest_tests/services/share/v2/json/shares_client.py +++ b/manila_tempest_tests/services/share/v2/json/shares_client.py @@ -909,7 +909,9 @@ class SharesV2Client(shares_client.SharesClient): def update_quotas(self, tenant_id, user_id=None, shares=None, snapshots=None, gigabytes=None, snapshot_gigabytes=None, - share_networks=None, force=True, share_type=None, + share_networks=None, + share_groups=None, share_group_snapshots=None, + force=True, share_type=None, url=None, version=LATEST_MICROVERSION): if url is None: url = self._get_quotas_url(version) @@ -929,6 +931,10 @@ class SharesV2Client(shares_client.SharesClient): put_body["snapshot_gigabytes"] = snapshot_gigabytes if share_networks is not None: put_body["share_networks"] = share_networks + if share_groups is not None: + put_body["share_groups"] = share_groups + if share_group_snapshots is not None: + put_body["share_group_snapshots"] = share_group_snapshots put_body = json.dumps({"quota_set": put_body}) resp, body = self.put(url, put_body, version=version) diff --git a/manila_tempest_tests/tests/api/admin/test_quotas.py b/manila_tempest_tests/tests/api/admin/test_quotas.py index 741a2bfb..02d0a62d 100644 --- a/manila_tempest_tests/tests/api/admin/test_quotas.py +++ b/manila_tempest_tests/tests/api/admin/test_quotas.py @@ -17,11 +17,15 @@ import ddt from tempest import config from tempest.lib.common.utils import data_utils from tempest.lib import exceptions as lib_exc +import testtools from testtools import testcase as tc from manila_tempest_tests.tests.api import base +from manila_tempest_tests import utils CONF = config.CONF +PRE_SHARE_GROUPS_MICROVERSION = "2.39" +SHARE_GROUPS_MICROVERSION = "2.40" @ddt.ddt @@ -44,6 +48,9 @@ class SharesAdminQuotasTest(base.BaseSharesAdminTest): self.assertGreater(int(quotas["shares"]), -2) self.assertGreater(int(quotas["snapshots"]), -2) self.assertGreater(int(quotas["share_networks"]), -2) + if utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION): + self.assertGreater(int(quotas["share_groups"]), -2) + self.assertGreater(int(quotas["share_group_snapshots"]), -2) @tc.attr(base.TAG_POSITIVE, base.TAG_API) def test_show_quotas(self): @@ -53,6 +60,9 @@ class SharesAdminQuotasTest(base.BaseSharesAdminTest): self.assertGreater(int(quotas["shares"]), -2) self.assertGreater(int(quotas["snapshots"]), -2) self.assertGreater(int(quotas["share_networks"]), -2) + if utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION): + self.assertGreater(int(quotas["share_groups"]), -2) + self.assertGreater(int(quotas["share_group_snapshots"]), -2) @tc.attr(base.TAG_POSITIVE, base.TAG_API) def test_show_quotas_for_user(self): @@ -63,6 +73,28 @@ class SharesAdminQuotasTest(base.BaseSharesAdminTest): self.assertGreater(int(quotas["shares"]), -2) self.assertGreater(int(quotas["snapshots"]), -2) self.assertGreater(int(quotas["share_networks"]), -2) + if utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION): + self.assertGreater(int(quotas["share_groups"]), -2) + self.assertGreater(int(quotas["share_group_snapshots"]), -2) + + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION) + def test_show_sg_quotas_using_too_old_microversion(self): + quotas = self.shares_v2_client.show_quotas( + self.tenant_id, version=PRE_SHARE_GROUPS_MICROVERSION) + + for key in ('share_groups', 'share_group_snapshots'): + self.assertNotIn(key, quotas) + + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION) + def test_show_sg_quotas_for_user_using_too_old_microversion(self): + quotas = self.shares_v2_client.show_quotas( + self.tenant_id, self.user_id, + version=PRE_SHARE_GROUPS_MICROVERSION) + + for key in ('share_groups', 'share_group_snapshots'): + self.assertNotIn(key, quotas) @ddt.data( ('id', True), @@ -93,12 +125,16 @@ class SharesAdminQuotasTest(base.BaseSharesAdminTest): for key in ('shares', 'gigabytes', 'snapshots', 'snapshot_gigabytes'): self.assertEqual(st_quotas[key], p_quotas[key]) + # Verify that we do not have share groups related quotas + # for share types. + for key in ('share_groups', 'share_group_snapshots'): + self.assertNotIn(key, st_quotas) + @ddt.ddt class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): force_tenant_isolation = True - client_version = '2' @classmethod def resource_setup(cls): @@ -109,8 +145,7 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): def setUp(self): super(self.__class__, self).setUp() - self.client = self.get_client_with_isolated_creds( - client_version=self.client_version) + self.client = self.get_client_with_isolated_creds(client_version='2') self.tenant_id = self.client.tenant_id self.user_id = self.client.user_id @@ -124,6 +159,24 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): updated = self.client.update_quotas(self.tenant_id, shares=new_quota) self.assertEqual(new_quota, int(updated["shares"])) + @ddt.data( + "share_groups", + "share_group_snapshots", + ) + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_update_tenant_quota_share_groups(self, quota_key): + # Get current quotas + quotas = self.client.show_quotas(self.tenant_id) + new_quota = int(quotas[quota_key]) + 2 + + # Set new quota + updated = self.client.update_quotas( + self.tenant_id, **{quota_key: new_quota}) + self.assertEqual(new_quota, int(updated[quota_key])) + @tc.attr(base.TAG_POSITIVE, base.TAG_API) def test_update_user_quota_shares(self): # get current quotas @@ -135,6 +188,24 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): self.tenant_id, self.user_id, shares=new_quota) self.assertEqual(new_quota, int(updated["shares"])) + @ddt.data( + "share_groups", + "share_group_snapshots", + ) + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_update_user_quota_share_groups(self, quota_key): + # Get current quotas + quotas = self.client.show_quotas(self.tenant_id, self.user_id) + new_quota = int(quotas[quota_key]) - 1 + + # Set new quota + updated = self.client.update_quotas( + self.tenant_id, self.user_id, **{quota_key: new_quota}) + self.assertEqual(new_quota, int(updated[quota_key])) + def _create_share_type(self): share_type = self.create_share_type( data_utils.rand_name("tempest-manila"), @@ -280,44 +351,63 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): @tc.attr(base.TAG_POSITIVE, base.TAG_API) def test_reset_tenant_quotas(self): - # get default_quotas + # Get default_quotas default = self.client.default_quotas(self.tenant_id) - # get current quotas + # Get current quotas custom = self.client.show_quotas(self.tenant_id) - # make quotas for update - shares = int(custom["shares"]) + 2 - snapshots = int(custom["snapshots"]) + 2 - gigabytes = int(custom["gigabytes"]) + 2 - snapshot_gigabytes = int(custom["snapshot_gigabytes"]) + 2 - share_networks = int(custom["share_networks"]) + 2 + # Make quotas for update + data = { + "shares": int(custom["shares"]) + 2, + "snapshots": int(custom["snapshots"]) + 2, + "gigabytes": int(custom["gigabytes"]) + 2, + "snapshot_gigabytes": int(custom["snapshot_gigabytes"]) + 2, + "share_networks": int(custom["share_networks"]) + 2, + } + if (utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION) and + CONF.share.run_share_group_tests): + data["share_groups"] = int(custom["share_groups"]) + 2 + data["share_group_snapshots"] = ( + int(custom["share_group_snapshots"]) + 2) # set new quota - updated = self.client.update_quotas( - self.tenant_id, - shares=shares, - snapshots=snapshots, - gigabytes=gigabytes, - snapshot_gigabytes=snapshot_gigabytes, - share_networks=share_networks) - self.assertEqual(shares, int(updated["shares"])) - self.assertEqual(snapshots, int(updated["snapshots"])) - self.assertEqual(gigabytes, int(updated["gigabytes"])) - self.assertEqual(snapshot_gigabytes, - int(updated["snapshot_gigabytes"])) - self.assertEqual(share_networks, int(updated["share_networks"])) + updated = self.client.update_quotas(self.tenant_id, **data) + self.assertEqual(data["shares"], int(updated["shares"])) + self.assertEqual(data["snapshots"], int(updated["snapshots"])) + self.assertEqual(data["gigabytes"], int(updated["gigabytes"])) + self.assertEqual( + data["snapshot_gigabytes"], int(updated["snapshot_gigabytes"])) + self.assertEqual( + data["share_networks"], int(updated["share_networks"])) + if (utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION) and + CONF.share.run_share_group_tests): + self.assertEqual( + data["share_groups"], int(updated["share_groups"])) + self.assertEqual( + data["share_group_snapshots"], + int(updated["share_group_snapshots"])) - # reset customized quotas + # Reset customized quotas self.client.reset_quotas(self.tenant_id) - # verify quotas + # Verify quotas reseted = self.client.show_quotas(self.tenant_id) self.assertEqual(int(default["shares"]), int(reseted["shares"])) self.assertEqual(int(default["snapshots"]), int(reseted["snapshots"])) self.assertEqual(int(default["gigabytes"]), int(reseted["gigabytes"])) - self.assertEqual(int(default["share_networks"]), - int(reseted["share_networks"])) + self.assertEqual( + int(default["snapshot_gigabytes"]), + int(reseted["snapshot_gigabytes"])) + self.assertEqual( + int(default["share_networks"]), int(reseted["share_networks"])) + if (utils.is_microversion_supported(SHARE_GROUPS_MICROVERSION) and + CONF.share.run_share_group_tests): + self.assertEqual( + int(default["share_groups"]), int(reseted["share_groups"])) + self.assertEqual( + int(default["share_group_snapshots"]), + int(reseted["share_group_snapshots"])) @ddt.data( ('id', True), @@ -450,6 +540,29 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): self.assertEqual(-1, quotas.get('share_networks')) + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_unlimited_quota_for_share_groups(self): + self.client.update_quotas(self.tenant_id, share_groups=-1) + + quotas = self.client.show_quotas(self.tenant_id) + + self.assertEqual(-1, quotas.get('share_groups')) + + @tc.attr(base.TAG_POSITIVE, base.TAG_API) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_unlimited_user_quota_for_share_group_snapshots(self): + self.client.update_quotas( + self.tenant_id, self.user_id, share_group_snapshots=-1) + + quotas = self.client.show_quotas(self.tenant_id, self.user_id) + + self.assertEqual(-1, quotas.get('share_group_snapshots')) + @ddt.data(11, -1) @tc.attr(base.TAG_NEGATIVE, base.TAG_API) def test_update_user_quotas_bigger_than_project_quota(self, user_quota): @@ -541,3 +654,82 @@ class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest): for key in ('shares', 'gigabytes'): self.assertEqual(0, quotas[key]['reserved']) self.assertEqual(0, quotas[key]['in_use']) + + def _check_sg_usages(self, quotas, in_use, limit): + """Helper method for 'test_share_group_quotas_usages' test.""" + self.assertEqual(0, int(quotas['share_groups']['reserved'])) + self.assertEqual(in_use, int(quotas['share_groups']['in_use'])) + self.assertEqual(limit, int(quotas['share_groups']['limit'])) + + def _check_sgs_usages(self, quotas, in_use): + """Helper method for 'test_share_group_quotas_usages' test.""" + self.assertEqual(0, int(quotas['share_group_snapshots']['reserved'])) + self.assertEqual( + in_use, int(quotas['share_group_snapshots']['in_use'])) + self.assertEqual(1, int(quotas['share_group_snapshots']['limit'])) + + def _check_usages(self, sg_in_use, sgs_in_use): + """Helper method for 'test_share_group_quotas_usages' test.""" + p_quotas = self.client.detail_quotas(tenant_id=self.tenant_id) + u_quotas = self.client.detail_quotas( + tenant_id=self.tenant_id, user_id=self.user_id) + self._check_sg_usages(p_quotas, sg_in_use, 3) + self._check_sg_usages(u_quotas, sg_in_use, 2) + self._check_sgs_usages(p_quotas, sgs_in_use) + self._check_sgs_usages(u_quotas, sgs_in_use) + + @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @base.skip_if_microversion_lt(SHARE_GROUPS_MICROVERSION) + def test_share_group_quotas_usages(self): + # Set quotas for project (3 SG, 1 SGS) and user (2 SG, 1 SGS) + self.client.update_quotas( + self.tenant_id, share_groups=3, share_group_snapshots=1) + self.client.update_quotas( + self.tenant_id, user_id=self.user_id, + share_groups=2, share_group_snapshots=1) + + # Check usages, they should be 0s + self._check_usages(0, 0) + + # Create SG1 and check usages + share_group1 = self.create_share_group( + cleanup_in_class=False, client=self.client) + self._check_usages(1, 0) + + # Create SGS1 and check usages + sg_snapshot = self.create_share_group_snapshot_wait_for_active( + share_group1['id'], cleanup_in_class=False, client=self.client) + self._check_usages(1, 1) + + # Create SG2 from SGS1 and check usages + share_group2 = self.create_share_group( + cleanup_in_class=False, client=self.client, + source_share_group_snapshot_id=sg_snapshot['id']) + self._check_usages(2, 1) + + # Try create SGS2, fail, then check usages + self.assertRaises( + lib_exc.OverLimit, + self.create_share_group, + client=self.client, cleanup_in_class=False) + self._check_usages(2, 1) + + # Delete SG2 and check usages + self.client.delete_share_group(share_group2['id']) + self.client.wait_for_resource_deletion( + share_group_id=share_group2['id']) + self._check_usages(1, 1) + + # Delete SGS1 and check usages + self.client.delete_share_group_snapshot(sg_snapshot['id']) + self.client.wait_for_resource_deletion( + share_group_snapshot_id=sg_snapshot['id']) + self._check_usages(1, 0) + + # Delete SG1 and check usages + self.client.delete_share_group(share_group1['id']) + self.client.wait_for_resource_deletion( + share_group_id=share_group1['id']) + self._check_usages(0, 0) diff --git a/manila_tempest_tests/tests/api/admin/test_quotas_negative.py b/manila_tempest_tests/tests/api/admin/test_quotas_negative.py index fe4f5624..91b2507e 100644 --- a/manila_tempest_tests/tests/api/admin/test_quotas_negative.py +++ b/manila_tempest_tests/tests/api/admin/test_quotas_negative.py @@ -17,11 +17,15 @@ import ddt from tempest import config from tempest.lib.common.utils import data_utils from tempest.lib import exceptions as lib_exc +import testtools from testtools import testcase as tc from manila_tempest_tests.tests.api import base +from manila_tempest_tests import utils CONF = config.CONF +PRE_SHARE_GROUPS_MICROVERSION = "2.39" +SHARE_GROUPS_MICROVERSION = "2.40" @ddt.ddt @@ -49,50 +53,35 @@ class SharesAdminQuotasNegativeTest(base.BaseSharesAdminTest): self.assertRaises(lib_exc.NotFound, client.reset_quotas, "") + @ddt.data( + {"shares": -2}, + {"snapshots": -2}, + {"gigabytes": -2}, + {"snapshot_gigabytes": -2}, + {"share_networks": -2}, + ) @tc.attr(base.TAG_NEGATIVE, base.TAG_API) - def test_update_shares_quota_with_wrong_data(self): + def test_update_quota_with_wrong_data(self, kwargs): # -1 is acceptable value as unlimited client = self.get_client_with_isolated_creds() - self.assertRaises(lib_exc.BadRequest, - client.update_quotas, - client.tenant_id, - shares=-2) + self.assertRaises( + lib_exc.BadRequest, + client.update_quotas, client.tenant_id, **kwargs) + @ddt.data( + {"share_groups": -2}, + {"share_group_snapshots": -2}, + ) @tc.attr(base.TAG_NEGATIVE, base.TAG_API) - def test_update_snapshots_quota_with_wrong_data(self): + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_update_sg_quota_with_wrong_data(self, kwargs): # -1 is acceptable value as unlimited - client = self.get_client_with_isolated_creds() - self.assertRaises(lib_exc.BadRequest, - client.update_quotas, - client.tenant_id, - snapshots=-2) - - @tc.attr(base.TAG_NEGATIVE, base.TAG_API) - def test_update_gigabytes_quota_with_wrong_data(self): - # -1 is acceptable value as unlimited - client = self.get_client_with_isolated_creds() - self.assertRaises(lib_exc.BadRequest, - client.update_quotas, - client.tenant_id, - gigabytes=-2) - - @tc.attr(base.TAG_NEGATIVE, base.TAG_API) - def test_update_snapshot_gigabytes_quota_with_wrong_data(self): - # -1 is acceptable value as unlimited - client = self.get_client_with_isolated_creds() - self.assertRaises(lib_exc.BadRequest, - client.update_quotas, - client.tenant_id, - snapshot_gigabytes=-2) - - @tc.attr(base.TAG_NEGATIVE, base.TAG_API) - def test_update_share_networks_quota_with_wrong_data(self): - # -1 is acceptable value as unlimited - client = self.get_client_with_isolated_creds() - self.assertRaises(lib_exc.BadRequest, - client.update_quotas, - client.tenant_id, - share_networks=-2) + client = self.get_client_with_isolated_creds(client_version='2') + self.assertRaises( + lib_exc.BadRequest, + client.update_quotas, client.tenant_id, **kwargs) @tc.attr(base.TAG_NEGATIVE, base.TAG_API) def test_create_share_with_size_bigger_than_quota(self): @@ -105,6 +94,21 @@ class SharesAdminQuotasNegativeTest(base.BaseSharesAdminTest): self.create_share, size=overquota) + @tc.attr(base.TAG_NEGATIVE, base.TAG_API) + @testtools.skipUnless( + CONF.share.run_share_group_tests, 'Share Group tests disabled.') + @utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_create_share_group_with_exceeding_quota_limit(self): + client = self.get_client_with_isolated_creds(client_version='2') + client.update_quotas(client.tenant_id, share_groups=0) + + # Try schedule share group creation + self.assertRaises( + lib_exc.OverLimit, + self.create_share_group, + client=client, + cleanup_in_class=False) + @tc.attr(base.TAG_NEGATIVE, base.TAG_API) def test_try_set_user_quota_shares_bigger_than_tenant_quota(self): client = self.get_client_with_isolated_creds() @@ -267,6 +271,41 @@ class SharesAdminQuotasNegativeTest(base.BaseSharesAdminTest): share_networks=int(tenant_quotas["share_networks"]), ) + @ddt.data('share_groups', 'share_group_snapshots') + @tc.attr(base.TAG_NEGATIVE, base.TAG_API) + @base.skip_if_microversion_lt(SHARE_GROUPS_MICROVERSION) + def test_try_update_share_type_quota_for_share_groups(self, quota_name): + client = self.get_client_with_isolated_creds(client_version='2') + share_type = self._create_share_type() + tenant_quotas = client.show_quotas(client.tenant_id) + + self.assertRaises( + lib_exc.BadRequest, + client.update_quotas, + client.tenant_id, + share_type=share_type["name"], + **{quota_name: int(tenant_quotas[quota_name])} + ) + + @ddt.data('share_groups', 'share_group_snapshots') + @tc.attr(base.TAG_NEGATIVE, base.TAG_API) + @base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION) + @base.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION) + def test_share_group_quotas_using_too_old_microversion(self, quota_key): + client = self.get_client_with_isolated_creds(client_version='2') + tenant_quotas = client.show_quotas( + client.tenant_id, version=SHARE_GROUPS_MICROVERSION) + kwargs = { + "version": PRE_SHARE_GROUPS_MICROVERSION, + quota_key: tenant_quotas[quota_key], + } + + self.assertRaises( + lib_exc.BadRequest, + client.update_quotas, + client.tenant_id, + **kwargs) + @ddt.data('show', 'reset', 'update') @tc.attr(base.TAG_NEGATIVE, base.TAG_API) @base.skip_if_microversion_lt("2.38")