Merge "Revert "Use ddt.named_data decorator to avoid random test names""
diff --git a/manila_tempest_tests/tests/rbac/test_quotas.py b/manila_tempest_tests/tests/rbac/test_quotas.py
new file mode 100644
index 0000000..604e488
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_quotas.py
@@ -0,0 +1,219 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed 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.
+
+import abc
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+CONF = config.CONF
+
+
+class ShareRbacQuotasTests(rbac_base.ShareRbacBaseTests,
+ metaclass=abc.ABCMeta):
+
+ @classmethod
+ def setup_clients(cls):
+ super(ShareRbacQuotasTests, cls).setup_clients()
+ cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+ cls.client = cls.persona.share_v2.SharesV2Client()
+ cls.alt_project_share_v2_client = (
+ cls.os_project_alt_member.share_v2.SharesV2Client())
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareRbacQuotasTests, cls).resource_setup()
+ cls.quotas = cls.client.show_quotas(cls.client.tenant_id)['quota_set']
+ cls.alt_quotas = cls.alt_project_share_v2_client.show_quotas(
+ cls.alt_project_share_v2_client.tenant_id)['quota_set']
+
+ @abc.abstractmethod
+ def test_default_quotas(self):
+ pass
+
+ @abc.abstractmethod
+ def test_show_quotas(self):
+ pass
+
+ @abc.abstractmethod
+ def test_show_quotas_detail(self):
+ pass
+
+ @abc.abstractmethod
+ def test_update_tenant_quota_shares(self):
+ pass
+
+ @abc.abstractmethod
+ def test_delete_quotas(self):
+ pass
+
+
+class TestProjectAdminTests(ShareRbacQuotasTests, base.BaseSharesTest):
+
+ credentials = ['project_admin', 'project_alt_member']
+
+ @decorators.idempotent_id('e102292f-93f9-4918-96b2-bb270e29e43e')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_default_quotas(self):
+ self.do_request(
+ 'default_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'default_quotas', expected_status=200,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('77c14ee8-9dbc-47dc-a86e-3a26f33beda5')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_show_quotas(self):
+ self.do_request(
+ 'show_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'show_quotas', expected_status=200,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('0bce045c-5575-4301-b526-032812a2e71f')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_show_quotas_detail(self):
+ self.do_request(
+ 'detail_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'detail_quotas', expected_status=200,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('b055f9ea-6176-45f9-a918-d9120912fcf6')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_tenant_quota_shares(self):
+ self.do_request(
+ 'update_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id,
+ shares=int(self.quotas['shares']) + 2)
+
+ self.do_request(
+ 'update_quotas', expected_status=200,
+ tenant_id=self.alt_project_share_v2_client.tenant_id,
+ shares=int(self.alt_quotas['shares']) + 2)
+
+ @decorators.idempotent_id('fe9ce5ab-4e93-4bdf-bd2d-d1b35a8b19f8')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_quotas(self):
+ self.do_request(
+ 'reset_quotas', expected_status=202,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'reset_quotas', expected_status=202,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+
+class TestProjectMemberTests(ShareRbacQuotasTests, base.BaseSharesTest):
+
+ credentials = ['project_member', 'project_alt_member']
+
+ @decorators.idempotent_id('a81d40fc-04b2-4535-ad44-c989a51e49b9')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_default_quotas(self):
+ self.do_request(
+ 'default_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'default_quotas', expected_status=200,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('52194358-6268-446c-ada4-74fb7e23dbe9')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_show_quotas(self):
+ self.do_request(
+ 'show_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'show_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('68b3d3e7-8ebd-4b20-bf56-7b4e4c365eda')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_show_quotas_detail(self):
+ self.do_request(
+ 'detail_quotas', expected_status=200,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'detail_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+ @decorators.idempotent_id('5a86d62d-5fdf-448e-bd6b-43e26e39201f')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_tenant_quota_shares(self):
+ self.do_request(
+ 'update_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.client.tenant_id,
+ shares=int(self.quotas['shares']) + 2)
+
+ self.do_request(
+ 'update_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.alt_project_share_v2_client.tenant_id,
+ shares=int(self.alt_quotas['shares']) + 2)
+
+ @decorators.idempotent_id('1928eea7-ca78-4004-8e5f-6d58a446503c')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_quotas(self):
+ self.do_request(
+ 'reset_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.client.tenant_id)
+
+ self.do_request(
+ 'reset_quotas', expected_status=lib_exc.Forbidden,
+ tenant_id=self.alt_project_share_v2_client.tenant_id)
+
+
+class TestProjectReaderTests(TestProjectMemberTests):
+
+ credentials = ['project_reader', 'project_alt_member']
+
+ @decorators.idempotent_id('51ec3c23-8c3b-45ff-9e41-38141ac82145')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_default_quotas(self):
+ super(TestProjectReaderTests, self).test_default_quotas()
+
+ @decorators.idempotent_id('48ca6e6b-6ad1-43b6-bdb7-848fe6a4d0fb')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_show_quotas(self):
+ super(TestProjectReaderTests, self).test_show_quotas()
+
+ @decorators.idempotent_id('0648bf5f-d8c8-4fd4-9713-27e9b5a1cda8')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_default_quotas_detail(self):
+ super(TestProjectReaderTests, self).test_show_quotas_detail()
+
+ @decorators.idempotent_id('4051f57d-3d79-4007-8b90-b5abf744b4b3')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_tenant_quota_shares(self):
+ super(TestProjectReaderTests, self).test_update_tenant_quota_shares()
+
+ @decorators.idempotent_id('8185210d-edf4-40e7-840a-484ab21bf7bd')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_quotas(self):
+ super(TestProjectReaderTests, self).test_delete_quotas()
diff --git a/manila_tempest_tests/tests/rbac/test_rules.py b/manila_tempest_tests/tests/rbac/test_rules.py
new file mode 100644
index 0000000..aa033f7
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_rules.py
@@ -0,0 +1,492 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed 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.
+
+import abc
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.common import waiters
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+from manila_tempest_tests import utils
+
+CONF = config.CONF
+
+
+class ShareRbacRulesTests(rbac_base.ShareRbacBaseTests, metaclass=abc.ABCMeta):
+
+ @classmethod
+ def skip_checks(cls):
+ super(ShareRbacRulesTests, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_protocols:
+ message = "%s tests are disabled" % cls.protocol
+ raise cls.skipException(message)
+
+ @classmethod
+ def setup_clients(cls):
+ super(ShareRbacRulesTests, cls).setup_clients()
+ cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+ cls.client = cls.persona.share_v2.SharesV2Client()
+ cls.alt_project_share_v2_client = (
+ cls.os_project_alt_member.share_v2.SharesV2Client())
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareRbacRulesTests, cls).resource_setup()
+ cls.metadata = {u'key': u'value'}
+ cls.access_type, cls.access_to = (
+ utils.get_access_rule_data_from_config(cls.protocol))
+
+ def access(self, share_id, access_level='rw'):
+ access = {}
+ access['share_id'] = share_id
+ access['access_type'] = self.access_type
+ access['access_to'] = self.access_to
+ access['access_level'] = access_level
+ return access
+
+ def allow_access(self, client, share_id, access_type, access_to,
+ access_level='rw', metadata=None, status='active',
+ cleanup=True):
+
+ kwargs = {
+ 'access_type': access_type,
+ 'access_to': access_to,
+ 'access_level': access_level,
+ 'metadata': metadata
+ }
+
+ rule = client.create_access_rule(share_id, **kwargs)['access']
+ waiters.wait_for_resource_status(
+ client, share_id, status, resource_name='access_rule',
+ rule_id=rule['id'])
+ if cleanup:
+ self.addCleanup(
+ client.wait_for_resource_deletion, rule_id=rule['id'],
+ share_id=share_id)
+ self.addCleanup(client.delete_access_rule, share_id, rule['id'])
+
+ return rule
+
+ @abc.abstractmethod
+ def test_grant_access_rule(self):
+ pass
+
+ @abc.abstractmethod
+ def test_get_access(self):
+ pass
+
+ @abc.abstractmethod
+ def test_list_access(self):
+ pass
+
+ @abc.abstractmethod
+ def test_delete_access(self):
+ pass
+
+ @abc.abstractmethod
+ def test_update_access_rule_metadata(self):
+ pass
+
+ @abc.abstractmethod
+ def test_delete_access_rule_metadata(self):
+ pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacRulesTests, base.BaseSharesTest):
+ credentials = ['project_admin', 'project_alt_member']
+ protocol = 'nfs'
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestProjectAdminTestsNFS, cls).setup_clients()
+ project_member = cls.setup_user_client(
+ cls.persona, project_id=cls.persona.credentials.project_id)
+ cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+ @classmethod
+ def resource_setup(cls):
+ super(TestProjectAdminTestsNFS, cls).resource_setup()
+ share_type = cls.get_share_type()
+ cls.share = cls.create_share(cls.client, share_type['id'])
+ cls.alt_share = cls.create_share(
+ cls.alt_project_share_v2_client, share_type['id'])
+
+ @decorators.idempotent_id('5b6897d1-4b2a-490c-990e-941ea4893f47')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_get_access(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'get_access_rule', expected_status=200, access_id=access['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'get_access_rule', expected_status=200, access_id=alt_access['id'])
+
+ @decorators.idempotent_id('f8e9a2bb-ccff-4fc5-8d61-2930f87406cd')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_list_access(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ access_list = self.do_request(
+ 'list_access_rules', expected_status=200,
+ share_id=self.share['id'])['access_list'][0]['id']
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ alt_access_list = self.do_request(
+ 'list_access_rules', expected_status=200,
+ share_id=self.share['id'])['access_list'][0]['id']
+
+ self.assertIn(access['id'], access_list)
+ self.assertNotIn(alt_access['id'], alt_access_list)
+
+ @decorators.idempotent_id('b4d7a91c-a75e-4ad9-93cb-8e5234fea97a')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_grant_access_rule(self):
+ access = self.do_request(
+ 'create_access_rule', expected_status=200,
+ **self.access(self.share['id']))['access']
+ self.addCleanup(
+ self.client.wait_for_resource_deletion, rule_id=access['id'],
+ share_id=self.share['id'])
+ self.addCleanup(
+ self.client.delete_access_rule, self.share['id'], access['id'])
+
+ alt_access = self.do_request(
+ 'create_access_rule', expected_status=200,
+ **self.access(self.alt_share['id']))['access']
+ self.addCleanup(
+ self.client.wait_for_resource_deletion, rule_id=alt_access['id'],
+ share_id=self.alt_share['id'])
+ self.addCleanup(
+ self.client.delete_access_rule, self.alt_share['id'],
+ alt_access['id'])
+
+ @decorators.idempotent_id('e24d7018-cb49-4306-9947-716b4e4250c5')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type,
+ access_to=self.access_to, cleanup=False)
+ self.do_request(
+ 'delete_access_rule', expected_status=202,
+ share_id=self.share['id'], rule_id=access['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ cleanup=False)
+ self.do_request(
+ 'delete_access_rule', expected_status=202,
+ share_id=self.alt_share['id'], rule_id=alt_access['id'])
+
+ @decorators.idempotent_id('ffc07445-d0d1-4bf9-9fbc-4f409d48bccd')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access_rule_metadata(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=200,
+ access_id=access['id'], metadata=self.metadata)
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=200,
+ access_id=alt_access['id'], metadata=self.metadata)
+
+ @decorators.idempotent_id('fd580d91-1d8d-4dd0-8484-01c412ddb768')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access_rule_metadata(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=200,
+ access_id=access['id'], key='key')
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=200,
+ access_id=alt_access['id'], key='key')
+
+
+class TestProjectMemberTestsNFS(ShareRbacRulesTests, base.BaseSharesTest):
+ credentials = ['project_member', 'project_alt_member']
+ protocol = 'nfs'
+
+ @classmethod
+ def resource_setup(cls):
+ super(TestProjectMemberTestsNFS, cls).resource_setup()
+ share_type = cls.get_share_type()
+ share_client = getattr(cls, 'share_member_client', cls.client)
+ cls.share = cls.create_share(share_client, share_type['id'])
+ cls.alt_share = cls.create_share(
+ cls.alt_project_share_v2_client, share_type['id'])
+
+ @decorators.idempotent_id('de643909-88a2-470b-8a14-0417696ec451')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_get_access(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(
+ share_client, self.share['id'], access_type=self.access_type,
+ access_to=self.access_to)
+ self.do_request(
+ 'get_access_rule', expected_status=200, access_id=access['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'get_access_rule', expected_status=lib_exc.NotFound,
+ access_id=alt_access['id'])
+
+ @decorators.idempotent_id('7c6c4262-5095-4cd7-9d9c-8064009a9055')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_list_access(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(
+ share_client, self.share['id'], access_type=self.access_type,
+ access_to=self.access_to)
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+
+ access_list = self.do_request(
+ 'list_access_rules', expected_status=200,
+ share_id=self.share['id'])['access_list']
+ access_id_list = [
+ s['id'] for s in access_list
+ ]
+
+ self.assertIn(access['id'], access_id_list)
+ self.assertNotIn(alt_access['id'], access_id_list)
+
+ @decorators.idempotent_id('61cf6f6c-5d7c-48d7-9d5a-e6ea288afdbc')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_grant_access_rule(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.do_request(
+ 'create_access_rule', client=share_client, expected_status=200,
+ **self.access(self.share['id']))['access']
+ self.addCleanup(
+ self.client.wait_for_resource_deletion, rule_id=access['id'],
+ share_id=self.share['id'])
+ self.addCleanup(
+ self.client.delete_access_rule, self.share['id'], access['id'])
+
+ self.do_request(
+ 'create_access_rule', client=share_client,
+ expected_status=lib_exc.NotFound,
+ **self.access(self.alt_share['id']))
+
+ @decorators.idempotent_id('8665d1b1-de4c-42d4-93ff-8dc6d2b73a2d')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(
+ share_client, self.share['id'], access_type=self.access_type,
+ access_to=self.access_to, cleanup=False)
+ self.do_request(
+ 'delete_access_rule', expected_status=202,
+ share_id=self.share['id'], rule_id=access['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'delete_access_rule', expected_status=lib_exc.NotFound,
+ share_id=self.alt_share['id'], rule_id=alt_access['id'])
+
+ @decorators.idempotent_id('c5e84362-6075-425b-bfa3-898abfd9d5a0')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access_rule_metadata(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(
+ share_client, self.share['id'], access_type=self.access_type,
+ access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=200,
+ access_id=access['id'], metadata=self.metadata)
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=lib_exc.NotFound,
+ access_id=alt_access['id'], metadata=self.metadata)
+
+ @decorators.idempotent_id('abb17315-6510-4b6e-ae6c-dd99a6088954')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access_rule_metadata(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(
+ share_client, self.share['id'], access_type=self.access_type,
+ access_to=self.access_to, metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=200,
+ access_id=access['id'], key='key')
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=lib_exc.NotFound,
+ access_id=alt_access['id'], key='key')
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+ """Test suite for basic share access rule operations by reader user
+
+ In order to test certain share operations we must create a share
+ resource for this. Since reader user is limited in resources creation, we
+ are forced to use admin credentials, so we can test other share
+ operations. In this class we use admin user to create a member user within
+ reader project. That way we can perform a reader actions on this resource.
+ """
+
+ credentials = ['project_reader', 'project_admin', 'project_alt_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestProjectReaderTestsNFS, cls).setup_clients()
+ project_member = cls.setup_user_client(
+ cls.os_project_admin,
+ project_id=cls.persona.credentials.project_id)
+ cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+ @classmethod
+ def resource_setup(cls):
+ super(TestProjectReaderTestsNFS, cls).resource_setup()
+ share_type = cls.get_share_type()
+ cls.share = cls.create_share(cls.share_member_client, share_type['id'])
+ cls.alt_share = cls.create_share(
+ cls.alt_project_share_v2_client, share_type['id'])
+
+ @decorators.idempotent_id('0eec0f05-f2f3-4500-9d9e-1b77ebc476c2')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_get_access(self):
+ super(TestProjectReaderTestsNFS, self).test_get_access()
+
+ @decorators.idempotent_id('9ddc26b6-f8bf-45d9-a2c6-a9eec9bfb8d2')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_list_access(self):
+ super(TestProjectReaderTestsNFS, self).test_list_access()
+
+ @decorators.idempotent_id('ace870f9-af91-4259-8760-dc7d7107b7ff')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_grant_access_rule(self):
+ self.do_request(
+ 'create_access_rule', expected_status=lib_exc.Forbidden,
+ **self.access(self.share['id']))
+
+ self.do_request(
+ 'create_access_rule', expected_status=lib_exc.Forbidden,
+ **self.access(self.alt_share['id']))
+
+ @decorators.idempotent_id('7a702c74-8d31-49e3-859a-cc8a78d7915e')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'delete_access_rule', expected_status=lib_exc.Forbidden,
+ share_id=self.share['id'], rule_id=access['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'delete_access_rule', expected_status=lib_exc.Forbidden,
+ share_id=self.alt_share['id'], rule_id=alt_access['id'])
+
+ @decorators.idempotent_id('a61d7f06-6f0e-4da3-b11d-1c3a0b5bd416')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access_rule_metadata(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=lib_exc.Forbidden,
+ access_id=access['id'], metadata=self.metadata)
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to)
+ self.do_request(
+ 'update_access_metadata', expected_status=lib_exc.Forbidden,
+ access_id=alt_access['id'], metadata=self.metadata)
+
+ @decorators.idempotent_id('5faf0e0b-b246-4392-901d-9e7d628f0d6e')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_delete_access_rule_metadata(self):
+ access = self.allow_access(
+ self.share_member_client, self.share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=lib_exc.Forbidden,
+ access_id=access['id'], key='key')
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ access_type=self.access_type, access_to=self.access_to,
+ metadata=self.metadata)
+ self.do_request(
+ 'delete_access_metadata', expected_status=lib_exc.Forbidden,
+ access_id=alt_access['id'], key='key')
+
+
+class TestProjectAdminTestsCEPHFS(TestProjectAdminTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectMemberTestsCEPHFS(TestProjectMemberTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectReaderTestsCEPHFS(TestProjectReaderTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectAdminTestsCIFS(TestProjectAdminTestsNFS):
+ protocol = 'cifs'
+
+
+class TestProjectMemberTestsCIFS(TestProjectMemberTestsNFS):
+ protocol = 'cifs'
+
+
+class TestProjectReaderTestsCIFS(TestProjectReaderTestsNFS):
+ protocol = 'cifs'
diff --git a/manila_tempest_tests/tests/rbac/test_share_manage.py b/manila_tempest_tests/tests/rbac/test_share_manage.py
new file mode 100644
index 0000000..272ec66
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_manage.py
@@ -0,0 +1,241 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed 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.
+
+import abc
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.common import constants
+from manila_tempest_tests.common import waiters
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+CONF = config.CONF
+
+
+class ShareRbacManageShareTests(rbac_base.ShareRbacBaseTests,
+ metaclass=abc.ABCMeta):
+
+ @classmethod
+ def skip_checks(cls):
+ super(ShareRbacManageShareTests, cls).skip_checks()
+ if not CONF.share.run_manage_unmanage_tests:
+ raise cls.skipException('Manage/unmanage tests are disabled.')
+ if cls.protocol not in CONF.share.enable_protocols:
+ message = "%s tests are disabled" % cls.protocol
+ raise cls.skipException(message)
+
+ @classmethod
+ def setup_clients(cls):
+ super(ShareRbacManageShareTests, cls).setup_clients()
+ cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+ cls.client = cls.persona.share_v2.SharesV2Client()
+ cls.admin_shares_v2_client = (
+ cls.os_project_admin.share_v2.SharesV2Client())
+ cls.alt_project_share_v2_client = (
+ cls.os_project_alt_member.share_v2.SharesV2Client())
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareRbacManageShareTests, cls).resource_setup()
+ cls.share_type = cls.get_share_type()
+
+ def share_manage_preparations(self, share_id, unmanage=True):
+ share_info = self.admin_shares_v2_client.get_share(share_id)['share']
+ export_path = self.admin_shares_v2_client.list_share_export_locations(
+ share_id)['export_locations'][0]
+ protocol = share_info['share_proto']
+ service_host = share_info['host']
+
+ if unmanage:
+ self.admin_shares_v2_client.unmanage_share(share_id)
+ self.admin_shares_v2_client.wait_for_resource_deletion(
+ share_id=share_id)
+ return {
+ 'export_path': export_path,
+ 'protocol': protocol,
+ 'service_host': service_host
+ }
+
+ @abc.abstractmethod
+ def test_manage_share(self):
+ pass
+
+ @abc.abstractmethod
+ def test_unmanage_share(self):
+ pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacManageShareTests, base.BaseSharesTest):
+
+ credentials = ['project_admin', 'project_alt_member']
+ protocol = 'nfs'
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestProjectAdminTestsNFS, cls).setup_clients()
+ project_member = cls.setup_user_client(
+ cls.persona, project_id=cls.persona.credentials.project_id)
+ cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+ @decorators.idempotent_id('8a21f805-2d45-4b0c-8ec5-3f45337bbf66')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_manage_share(self):
+ share = self.create_share(
+ self.share_member_client, self.share_type['id'])
+ share_data = self.share_manage_preparations(share['id'])
+ self.do_request(
+ 'manage_share', expected_status=200,
+ share_type_id=self.share_type['id'], **share_data)
+
+ alt_share = self.create_share(
+ self.alt_project_share_v2_client, self.share_type['id'])
+ alt_share_data = self.share_manage_preparations(alt_share['id'])
+ self.do_request(
+ 'manage_share', expected_status=200,
+ share_type_id=self.share_type['id'], **alt_share_data)
+
+ @decorators.idempotent_id('be5b836d-d6cc-40a5-acf4-e5f249035383')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_unmanage_share(self):
+ share = self.create_share(
+ self.share_member_client, self.share_type['id'])
+ share_data = self.share_manage_preparations(
+ share['id'], unmanage=False)
+ self.do_request(
+ 'unmanage_share', expected_status=202, share_id=share['id'])
+ self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
+
+ # Unmanaged share operation removes the share from the management of
+ # the shared file systems service without deleting the share.
+ # In order to be able to delete the share we need to manage it again,
+ # otherwise, it would leave some allocated space.
+ managed_share = self.client.manage_share(
+ share_type_id=self.share_type['id'], **share_data)['share']
+ waiters.wait_for_resource_status(
+ self.client, managed_share['id'], constants.STATUS_AVAILABLE)
+
+ alt_share = self.create_share(
+ self.alt_project_share_v2_client, self.share_type['id'])
+ share_data = self.share_manage_preparations(
+ alt_share['id'], unmanage=False)
+ self.do_request(
+ 'unmanage_share', expected_status=202, share_id=alt_share['id'])
+ self.shares_v2_client.wait_for_resource_deletion(
+ share_id=alt_share['id'])
+
+ alt_managed_share = self.client.manage_share(
+ share_type_id=self.share_type['id'], **share_data)['share']
+ waiters.wait_for_resource_status(
+ self.client, alt_managed_share['id'], constants.STATUS_AVAILABLE)
+
+
+class TestProjectMemberTestsNFS(ShareRbacManageShareTests,
+ base.BaseSharesTest):
+
+ credentials = ['project_member', 'project_admin', 'project_alt_member']
+ protocol = 'nfs'
+
+ @decorators.idempotent_id('46f884b2-531d-41c0-8455-8874629b3ea3')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_manage_share(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ share = self.create_share(share_client, self.share_type['id'])
+ share_data = self.share_manage_preparations(
+ share['id'], unmanage=False)
+ self.do_request(
+ 'manage_share', expected_status=lib_exc.Forbidden,
+ share_type_id=self.share_type['id'], **share_data)
+
+ alt_share = self.create_share(
+ self.alt_project_share_v2_client, self.share_type['id'])
+ alt_share_data = self.share_manage_preparations(
+ alt_share['id'], unmanage=False)
+ self.do_request(
+ 'manage_share', expected_status=lib_exc.Forbidden,
+ share_type_id=self.share_type['id'], **alt_share_data)
+
+ @decorators.idempotent_id('9dc2b1a5-8195-46b8-a28a-9710be352f18')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_unmanage_share(self):
+ share_client = getattr(self, 'share_member_client', self.client)
+ share = self.create_share(share_client, self.share_type['id'])
+ self.do_request(
+ 'unmanage_share', expected_status=lib_exc.Forbidden,
+ share_id=share['id'])
+
+ alt_share = self.create_share(
+ self.alt_project_share_v2_client, self.share_type['id'])
+ self.do_request(
+ 'unmanage_share', expected_status=lib_exc.Forbidden,
+ share_id=alt_share['id'])
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+ """Test suite for basic share operations by reader user
+
+ In order to test certain share operations we must create a share resource
+ for this. Since reader user is limited in resources creation, we are forced
+ to use admin credentials, so we can test other share operations.
+ In this class we use admin user to create a member user within reader
+ project. That way we can perform a reader actions on this resource.
+ """
+
+ credentials = ['project_reader', 'project_admin', 'project_alt_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestProjectReaderTestsNFS, cls).setup_clients()
+ project_member = cls.setup_user_client(
+ cls.os_project_admin,
+ project_id=cls.persona.credentials.project_id)
+ cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+ @decorators.idempotent_id('cec85349-b7e3-440e-bbbc-3bb5999b119a')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_manage_share(self):
+ super(TestProjectReaderTestsNFS, self).test_manage_share()
+
+ @decorators.idempotent_id('a524620c-90b6-496c-8418-c469e711a607')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_unmanage_share(self):
+ super(TestProjectReaderTestsNFS, self).test_unmanage_share()
+
+
+class TestProjectAdminTestsCEPHFS(TestProjectAdminTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectMemberTestsCEPHFS(TestProjectMemberTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectReaderTestsCEPHFS(TestProjectReaderTestsNFS):
+ protocol = 'cephfs'
+
+
+class TestProjectAdminTestsCIFS(TestProjectAdminTestsNFS):
+ protocol = 'cifs'
+
+
+class TestProjectMemberTestsCIFS(TestProjectMemberTestsNFS):
+ protocol = 'cifs'
+
+
+class TestProjectReaderTestsCIFS(TestProjectReaderTestsNFS):
+ protocol = 'cifs'
diff --git a/zuul.d/manila-tempest-stable-jobs.yaml b/zuul.d/manila-tempest-stable-jobs.yaml
index d5adfce..28db229 100644
--- a/zuul.d/manila-tempest-stable-jobs.yaml
+++ b/zuul.d/manila-tempest-stable-jobs.yaml
@@ -1,4 +1,4 @@
-# Stable wallaby / xena / yoga branch jobs to test the trunk version of
+# Stable xena / yoga / zed branch jobs to test the trunk version of
# manila-tempest-plugin against those released stable branches of manila
- job:
@@ -7,7 +7,7 @@
Test the scenario test cases on the generic driver multibackend
(DHSS=True) with NFS and CIFS
parent: manila-tempest-plugin-generic-scenario-base
- branches: &manila_tempest_image_pinned_branches ^(stable/(yoga|xena|wallaby)).*$
+ branches: &manila_tempest_image_pinned_branches ^(stable/(zed|yoga|xena)).*$
vars: &manila_tempest_image_pinned_vars
devstack_localrc:
# NOTE(carloss): Pinning manila service image to a Focal version,
@@ -68,7 +68,7 @@
- job:
name: manila-tempest-plugin-lvm-fips-stable
parent: manila-tempest-plugin-lvm-fips-base
- branches: ^(stable/(yoga|xena|wallaby)).*$
+ branches: ^(stable/(yoga|xena)).*$
vars: *manila_tempest_image_pinned_vars
- job:
@@ -85,13 +85,6 @@
override-checkout: stable/xena
vars: *manila_tempest_image_pinned_vars
-- job:
- name: manila-tempest-plugin-lvm-wallaby
- parent: manila-tempest-plugin-lvm-base
- nodeset: openstack-single-node-focal
- override-checkout: stable/wallaby
- vars: *manila_tempest_image_pinned_vars
-
- project-template:
name: manila-tempest-plugin-jobs-using-service-image-stable
description: |
diff --git a/zuul.d/manila-tempest-wallaby-jobs.yaml b/zuul.d/manila-tempest-wallaby-jobs.yaml
new file mode 100644
index 0000000..57fe515
--- /dev/null
+++ b/zuul.d/manila-tempest-wallaby-jobs.yaml
@@ -0,0 +1,131 @@
+# Stable wallaby branch jobs run with a pinned version of manila-tempest-plugin
+
+- job:
+ name: manila-tempest-plugin-generic-scenario-wallaby
+ description: |
+ Test the scenario test cases on the generic driver multibackend
+ (DHSS=True) with NFS and CIFS in the stable/wallaby branch
+ parent: manila-tempest-plugin-generic-scenario-base
+ vars: &manila_tempest_image_pinned_vars
+ devstack_localrc:
+ # NOTE(carloss): Pinning manila service image to a Focal version,
+ # since on Zed we moved to Ubuntu Jammy (22), and it requires more
+ # VM resources.
+ MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-1.3.0-76-ga216835.qcow2
+ MANILA_SERVICE_IMAGE_NAME: manila-service-image-1.3.0-76-ga216835
+ required-projects: &manila-tempest-plugin-pinned-version
+ - name: openstack/manila-tempest-plugin
+ override-checkout: 1.8.0
+
+- job:
+ name: manila-tempest-plugin-generic-wallaby
+ description: |
+ Test the generic driver multibackend (DHSS=True) with NFS and CIFS in
+ stable wallaby
+ parent: manila-tempest-plugin-generic-base
+ vars: *manila_tempest_image_pinned_vars
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-lvm-wallaby
+ description: |
+ Test LVM multibackend (DHSS=False) in a 4+6 (dual-stack) devstack
+ environment with IPv6 control plane endpoints on the stable/wallaby
+ branch
+ parent: manila-tempest-plugin-lvm-base
+ vars: *manila_tempest_image_pinned_vars
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-cephfs-native-wallaby
+ description: Test CephFS Native (DHSS=False) in stable/wallaby
+ parent: manila-tempest-plugin-cephfs-native-base
+ vars:
+ devstack_localrc:
+ # NOTE(gouthamr): The following need to use the latest images, however, there's a bug
+ # with cephfs on Ubuntu 20.04 LTS: https://tracker.ceph.com/issues/47236
+ # the latest image is built as https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-master.qcow2
+ MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-1.3.0-58-g2859569.qcow2
+ MANILA_SERVICE_IMAGE_NAME: manila-service-image-cephfs-1.3.0-58-g2859569
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-cephfs-nfs-wallaby
+ description: Test CephFS NFS (DHSS=False) in stable/wallaby
+ parent: manila-tempest-plugin-cephfs-nfs-base
+ vars: *manila_tempest_image_pinned_vars
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-zfsonlinux-wallaby
+ description: |
+ Test ZFSOnLinux multibackend (DHSS=False) with postgresql db in
+ stable wallaby
+ parent: manila-tempest-plugin-zfsonlinux-base
+ vars: *manila_tempest_image_pinned_vars
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-dummy-no-dhss-wallaby
+ description: Test the Dummy driver with DHSS=False in stable wallaby
+ parent: manila-tempest-plugin-dummy-no-dhss
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-dummy-dhss-wallaby
+ description: Test the Dummy driver with DHSS=True in stable wallaby
+ parent: manila-tempest-plugin-dummy-dhss
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-container-wallaby
+ description: |
+ Test the container driver multibackend (DHSS=True) with CIFS
+ and postgresql db. API only, in a minimal devstack in stable wallaby
+ parent: manila-tempest-plugin-container
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-glusterfs-native-wallaby
+ description: |
+ Test the GlusterFS driver (DHSS=False) with the native GlusterFS
+ protocol in stable wallaby
+ parent: manila-tempest-plugin-glusterfs-native
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-glusterfs-nfs-wallaby
+ description: |
+ Test the GlusterFS driver (DHSS=False) with the native NFS protocol in
+ stable wallaby
+ parent: manila-tempest-plugin-glusterfs-nfs
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+ name: manila-tempest-plugin-lvm-fips-wallaby
+ description: |
+ Test the LVM driver (DHSS=False) in a FIPS-enabled environment
+ parent: manila-tempest-plugin-lvm-fips-base
+ required-projects: *manila-tempest-plugin-pinned-version
+
+- project-template:
+ name: manila-tempest-plugin-jobs-using-service-image-wallaby
+ description: |
+ Runs jobs that will also perform scenario tests in the stable/wallaby
+ branches.
+ check:
+ jobs:
+ - manila-tempest-plugin-lvm-wallaby
+ - manila-tempest-plugin-generic-scenario-wallaby:
+ voting: false
+ - manila-tempest-plugin-generic-wallaby:
+ voting: false
+ - manila-tempest-plugin-cephfs-native-wallaby:
+ voting: false
+ - manila-tempest-plugin-cephfs-nfs-wallaby:
+ voting: false
+ - manila-tempest-plugin-zfsonlinux-wallaby:
+ voting: false
+ gate:
+ jobs:
+ - manila-tempest-plugin-lvm-wallaby
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index af9767c..48d3d4c 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -10,7 +10,6 @@
- manila-tempest-plugin-dummy-dhss
- manila-tempest-plugin-lvm-yoga
- manila-tempest-plugin-lvm-xena
- - manila-tempest-plugin-lvm-wallaby
- manila-tempest-plugin-dummy-no-dhss-rbac
- manila-tempest-plugin-container:
voting: false