Merge "Prepare the stable/wallaby jobs with pinned manila-tempest-plugin"
diff --git a/manila_tempest_tests/common/constants.py b/manila_tempest_tests/common/constants.py
index 2750760..3488bc5 100644
--- a/manila_tempest_tests/common/constants.py
+++ b/manila_tempest_tests/common/constants.py
@@ -42,6 +42,7 @@
 REPLICATION_STATE_OUT_OF_SYNC = 'out_of_sync'
 MIN_SHARE_REPLICATION_VERSION = '2.11'
 SHARE_REPLICA_GRADUATION_VERSION = '2.56'
+SHARE_REPLICA_SHARE_NET_PARAM_VERSION = '2.72'
 
 # Access Rules
 RULE_STATE_ACTIVE = 'active'
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 6ea0b92..648b282 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -1563,8 +1563,8 @@
         return rest_client.ResponseBody(resp, body)
 
     def create_share_replica(self, share_id, availability_zone=None,
-                             version=LATEST_MICROVERSION,
-                             scheduler_hints=None):
+                             scheduler_hints=None, share_network_id=None,
+                             version=LATEST_MICROVERSION):
         """Add a share replica of an existing share."""
         uri = "share-replicas"
         post_body = {
@@ -1574,6 +1574,9 @@
 
         if scheduler_hints:
             post_body["scheduler_hints"] = scheduler_hints
+        if share_network_id:
+            post_body['share_network_id'] = share_network_id
+
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_REPLICA_GRADUATION_VERSION)
         body = json.dumps({'share_replica': post_body})
diff --git a/manila_tempest_tests/tests/api/admin/test_replication.py b/manila_tempest_tests/tests/api/admin/test_replication.py
index 242e786..3458023 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication.py
@@ -105,9 +105,13 @@
 
         # NOTE(Yogi1): Cleanup needs to be disabled for replica that is
         # being promoted since it will become the 'primary'/'active' replica.
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
         replica = self.create_share_replica(
-            share["id"], self.replica_zone, cleanup=False,
-            client=self.admin_client, version=version)
+            share["id"], self.replica_zone, share_network_id=share_net_id,
+            cleanup=False, client=self.admin_client, version=version)
         # Wait for replica state to update after creation
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
@@ -156,11 +160,15 @@
     def test_force_delete_share_replica(self, version):
         """Test force deleting a replica that is in 'error_deleting' status."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False,
+            client=self.admin_client, version=version)
         self.admin_client.reset_share_replica_status(
             replica['id'], constants.STATUS_ERROR_DELETING, version=version)
         waiters.wait_for_resource_status(
@@ -179,11 +187,15 @@
     def test_reset_share_replica_status(self, version):
         """Test resetting a replica's 'status' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_status(replica['id'],
                                                      constants.STATUS_ERROR,
                                                      version=version)
@@ -200,11 +212,15 @@
     def test_reset_share_replica_state(self, version):
         """Test resetting a replica's 'replica_state' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_state(replica['id'],
                                                     constants.STATUS_ERROR,
                                                     version=version)
@@ -222,11 +238,12 @@
     def test_resync_share_replica(self, version):
         """Test resyncing a replica."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], share_network_id=share_net_id, version=version)
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
             constants.REPLICATION_STATE_IN_SYNC, resource_name='share_replica',
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index 6372034..226e767 100755
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -676,14 +676,17 @@
 
     @classmethod
     def create_share_replica(cls, share_id, availability_zone=None,
+                             scheduler_hints=None,
+                             share_network_id=None,
                              client=None, cleanup_in_class=False,
                              cleanup=True,
-                             version=CONF.share.max_api_microversion,
-                             scheduler_hints=None):
+                             version=CONF.share.max_api_microversion):
         client = client or cls.shares_v2_client
         replica = client.create_share_replica(
             share_id, availability_zone=availability_zone,
-            version=version, scheduler_hints=scheduler_hints)['share_replica']
+            scheduler_hints=scheduler_hints,
+            share_network_id=share_network_id,
+            version=version)['share_replica']
         resource = {
             "type": "share_replica",
             "id": replica["id"],
diff --git a/manila_tempest_tests/tests/api/test_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 14c4d45..5865e69 100644
--- a/manila_tempest_tests/tests/api/test_replication.py
+++ b/manila_tempest_tests/tests/api/test_replication.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import ddt
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
@@ -26,12 +27,14 @@
 from manila_tempest_tests import utils
 
 CONF = config.CONF
+LATEST_MICROVERSION = CONF.share.max_api_microversion
 _MIN_SUPPORTED_MICROVERSION = '2.11'
 SUMMARY_KEYS = ['share_id', 'id', 'replica_state', 'status']
 DETAIL_KEYS = SUMMARY_KEYS + ['availability_zone', 'updated_at',
                               'share_network_id', 'created_at']
 
 
+@ddt.ddt
 class ReplicationTest(base.BaseSharesMixedTest):
 
     @classmethod
@@ -96,11 +99,15 @@
             share["id"])['share_instances']
         return share_instances[0]["id"]
 
-    def _verify_create_replica(self):
+    def _verify_create_replica(self, version=LATEST_MICROVERSION):
         # Create the replica
-        share_replica = self.create_share_replica(self.shares[0]["id"],
-                                                  self.replica_zone,
-                                                  cleanup_in_class=False)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        share_replica = self.create_share_replica(
+            self.shares[0]["id"], self.replica_zone,
+            share_network_id=share_net_id, cleanup_in_class=False)
         share_replicas = self.shares_v2_client.list_share_replicas(
             share_id=self.shares[0]["id"])['share_replicas']
         # Ensure replica is created successfully.
@@ -155,6 +162,18 @@
             raise self.skipException(
                 msg % ','.join(constants.REPLICATION_PROMOTION_CHOICES))
 
+    @decorators.idempotent_id('c59e3198-062b-4284-8a3b-189a62213573')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+    @testtools.skipUnless(
+        CONF.share.multitenancy_enabled, "Only for multitenancy.")
+    @ddt.data(
+        *utils.deduplicate([constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION,
+                            LATEST_MICROVERSION]))
+    def test_create_share_replica_with_provided_network(self, version):
+        utils.check_skip_if_microversion_not_supported(version)
+        share_replica = self._verify_create_replica(version)
+        self.assertIsNotNone(share_replica)
+
     @decorators.idempotent_id('8858617f-292d-4e5c-9e15-794b7f1b2e3c')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
     def test_add_delete_share_replica(self):
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_share_manage.py b/manila_tempest_tests/tests/rbac/test_share_manage.py
new file mode 100644
index 0000000..6127755
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_manage.py
@@ -0,0 +1,239 @@
+# 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 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'