Merge "Change test manage share server with invalid id"
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/config.py b/manila_tempest_tests/config.py
index b62c409..0cd07d3 100644
--- a/manila_tempest_tests/config.py
+++ b/manila_tempest_tests/config.py
@@ -40,7 +40,7 @@
                     "This value is only used to validate the versions "
                     "response from Manila."),
     cfg.StrOpt("max_api_microversion",
-               default="2.71",
+               default="2.81",
                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 a87648c..fe3e31c 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -515,7 +515,8 @@
 ###############
 
     def create_snapshot(self, share_id, name=None, description=None,
-                        force=False, version=LATEST_MICROVERSION):
+                        force=False, metadata=None,
+                        version=LATEST_MICROVERSION):
         if name is None:
             name = data_utils.rand_name("tempest-created-share-snap")
         if description is None:
@@ -529,6 +530,9 @@
                 "share_id": share_id,
             }
         }
+        if utils.is_microversion_ge(version, "2.73") and metadata:
+            post_body["snapshot"]["metadata"] = metadata
+
         body = json.dumps(post_body)
         resp, body = self.post("snapshots", body, version=version)
         self.expected_success(202, resp.status)
@@ -1155,8 +1159,8 @@
         headers, _junk = utils.get_extra_headers(
             version, constants.SHARE_GROUPS_GRADUATION_VERSION)
         return self.reset_state(
-            share_group_id, status=status, s_type='groups', headers=headers,
-            version=version)
+            share_group_id, status=status, s_type='share-groups',
+            headers=headers, version=version)
 
     def share_group_force_delete(self, share_group_id,
                                  version=LATEST_MICROVERSION):
@@ -1295,7 +1299,7 @@
 
     def get_share_group_type_spec(self, share_group_type_id, group_spec_key,
                                   version=LATEST_MICROVERSION):
-        uri = "group-types/%s/group_specs/%s" % (
+        uri = "share-group-types/%s/group-specs/%s" % (
             share_group_type_id, group_spec_key)
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_GROUPS_GRADUATION_VERSION)
@@ -1305,9 +1309,9 @@
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def list_share_group_type_specs(self, share_group_type_id, params=None,
-                                    version=LATEST_MICROVERSION):
-        uri = "share-group-types/%s/group_specs" % share_group_type_id
+    def get_share_group_type_specs(self, share_group_type_id, params=None,
+                                   version=LATEST_MICROVERSION):
+        uri = "share-group-types/%s/group-specs" % share_group_type_id
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_GROUPS_GRADUATION_VERSION)
         if params is not None:
@@ -1339,10 +1343,10 @@
         return self.create_share_group_type_specs(
             share_group_type_id, group_specs_dict, version=version)
 
-    def delete_share_group_type_spec(self, share_type_id, group_spec_key,
+    def delete_share_group_type_spec(self, share_group_type_id, group_spec_key,
                                      version=LATEST_MICROVERSION):
         uri = "share-group-types/%s/group-specs/%s" % (
-            share_type_id, group_spec_key)
+            share_group_type_id, group_spec_key)
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_GROUPS_GRADUATION_VERSION)
         resp, body = self.delete(uri, headers=headers,
@@ -1559,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 = {
@@ -1570,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})
@@ -2071,3 +2078,139 @@
 
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
+
+#################
+
+    def _update_metadata(self, resource, resource_id, metadata=None,
+                         method="post", parent_resource=None, parent_id=None):
+        if parent_resource is None:
+            uri = f'{resource}s/{resource_id}/metadata'
+        else:
+            uri = (f'{parent_resource}/{parent_id}'
+                   f'/{resource}s/{resource_id}/metadata')
+        if metadata is None:
+            metadata = {}
+        post_body = {"metadata": metadata}
+        body = json.dumps(post_body)
+        if method == "post":
+            resp, body = self.post(uri, body)
+        if method == "put":
+            resp, body = self.put(uri, body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def set_metadata(self, resource_id, metadata=None, resource='share',
+                     parent_resource=None, parent_id=None):
+        return self._update_metadata(resource, resource_id, metadata,
+                                     method="post",
+                                     parent_resource=parent_resource,
+                                     parent_id=parent_id)
+
+    def update_all_metadata(self, resource_id, metadata=None,
+                            resource='share', parent_resource=None,
+                            parent_id=None):
+        return self._update_metadata(resource, resource_id, metadata,
+                                     method="put",
+                                     parent_resource=parent_resource,
+                                     parent_id=parent_id)
+
+    def delete_metadata(self, resource_id, key, resource='share',
+                        parent_resource=None, parent_id=None):
+        if parent_resource is None:
+            uri = f'{resource}s/{resource_id}/metadata/{key}'
+        else:
+            uri = (f'{parent_resource}/{parent_id}'
+                   f'/{resource}s/{resource_id}/metadata/{key}')
+        resp, body = self.delete(uri)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def get_metadata(self, resource_id, resource='share',
+                     parent_resource=None, parent_id=None):
+        if parent_resource is None:
+            uri = f'{resource}s/{resource_id}/metadata'
+        else:
+            uri = (f'{parent_resource}/{parent_id}'
+                   f'/{resource}s/{resource_id}/metadata')
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def get_metadata_item(self, resource_id, key, resource='share',
+                          parent_resource=None, parent_id=None):
+        if parent_resource is None:
+            uri = f'{resource}s/{resource_id}/metadata/{key}'
+        else:
+            uri = (f'{parent_resource}/{parent_id}'
+                   f'/{resource}s/{resource_id}/metadata/{key}')
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+#################
+
+    def create_resource_lock(self, resource_id, resource_type,
+                             resource_action='delete', lock_reason=None,
+                             version=LATEST_MICROVERSION):
+        body = {
+            "resource_lock": {
+                'resource_id': resource_id,
+                'resource_type': resource_type,
+                'resource_action': resource_action,
+                'lock_reason': lock_reason,
+            },
+        }
+        body = json.dumps(body)
+        resp, body = self.post("resource-locks", body, version=version)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def get_resource_lock(self, lock_id, version=LATEST_MICROVERSION):
+        resp, body = self.get("resource-locks/%s" % lock_id, version=version)
+
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_resource_locks(self, filters=None, version=LATEST_MICROVERSION):
+        uri = (
+            "resource-locks?%s" % parse.urlencode(filters)
+            if filters else "resource-locks"
+        )
+
+        resp, body = self.get(uri, version=version)
+
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_resource_lock(self,
+                             lock_id,
+                             resource_action=None,
+                             lock_reason=None,
+                             version=LATEST_MICROVERSION):
+        uri = 'resource-locks/%s' % lock_id
+        post_body = {}
+        if resource_action:
+            post_body['resource_action'] = resource_action
+        if lock_reason:
+            post_body['lock_reason'] = lock_reason
+        body = json.dumps({'resource_lock': post_body})
+
+        resp, body = self.put(uri, body, version=version)
+
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_resource_lock(self, lock_id, version=LATEST_MICROVERSION):
+        uri = "resource-locks/%s" % lock_id
+
+        resp, body = self.delete(uri, version=version)
+
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/manila_tempest_tests/tests/api/admin/test_quotas.py b/manila_tempest_tests/tests/api/admin/test_quotas.py
index 7ef3a96..e8377e1 100644
--- a/manila_tempest_tests/tests/api/admin/test_quotas.py
+++ b/manila_tempest_tests/tests/api/admin/test_quotas.py
@@ -35,10 +35,14 @@
 class SharesAdminQuotasTest(base.BaseSharesAdminTest):
 
     @classmethod
-    def resource_setup(cls):
+    def skip_checks(cls):
+        super(SharesAdminQuotasTest, cls).skip_checks()
         if not CONF.share.run_quota_tests:
             msg = "Quota tests are disabled."
             raise cls.skipException(msg)
+
+    @classmethod
+    def resource_setup(cls):
         super(SharesAdminQuotasTest, cls).resource_setup()
         cls.client = cls.shares_v2_client
         cls.user_id = cls.client.user_id
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/admin/test_share_group_types.py b/manila_tempest_tests/tests/api/admin/test_share_group_types.py
index 1bc522a..771be4f 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_group_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_group_types.py
@@ -142,6 +142,42 @@
 
         self.assertDictMatch(group_specs, sg_type['group_specs'])
 
+    @decorators.idempotent_id('dd620bfd-197b-4675-ace6-e26f809bb26e')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_one_share_group_type_extra_spec(self):
+        name = data_utils.rand_name('share-group-type')
+        group_specs = {'key1': 'value1', 'key2': 'value2'}
+
+        sg_type = self.create_share_group_type(
+            name=name,
+            share_types=self.share_type['id'],
+            group_specs=group_specs,
+            cleanup_in_class=False,
+            version=constants.MIN_SHARE_GROUP_MICROVERSION)
+
+        extra_spec = self.shares_v2_client.get_share_group_type_spec(
+            sg_type['id'], 'key1')
+
+        self.assertEqual({'key1': group_specs['key1']}, extra_spec)
+
+    @decorators.idempotent_id('eef69171-9757-423c-8cd4-487cbd84ca24')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_all_share_group_type_extra_specs(self):
+        name = data_utils.rand_name('share-group-type')
+        group_specs = {'key': 'value'}
+
+        sg_type = self.create_share_group_type(
+            name=name,
+            share_types=self.share_type['id'],
+            group_specs=group_specs,
+            cleanup_in_class=False,
+            version=constants.MIN_SHARE_GROUP_MICROVERSION)
+
+        extra_specs = self.shares_v2_client.get_share_group_type_specs(
+            sg_type['id'])
+
+        self.assertDictMatch(group_specs, extra_specs['group_specs'])
+
     @decorators.idempotent_id('15b44580-a34d-4e0d-a77b-0e76b45d6199')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     @ddt.data(
diff --git a/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py b/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
index 391a6b4..778d7a7 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
@@ -44,6 +44,7 @@
         cls.share_group_type = cls.create_share_group_type(
             data_utils.rand_name("unique_sgt_name"),
             share_types=[cls.share_type['id']],
+            group_specs={"key": "value"},
             client=cls.admin_shares_v2_client)
 
     @decorators.idempotent_id('1f8e3f98-4df7-4383-94d6-4ad058ef79c1')
@@ -163,3 +164,27 @@
             self.admin_shares_v2_client.remove_access_from_share_group_type,
             data_utils.rand_name("fake"),
             self.admin_shares_v2_client.tenant_id)
+
+    @decorators.idempotent_id('3e763f5b-6663-4620-9471-ed3050da6201')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_try_get_share_group_type_extra_specs_with_user(self):
+        self.assertRaises(
+            lib_exc.Forbidden,
+            self.shares_v2_client.get_share_group_type_specs,
+            self.share_group_type['id'])
+
+    @decorators.idempotent_id('2264f7eb-3ff0-47e9-8ab0-54694113db3d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_try_get_extra_specs_from_nonexistent_share_group_type(self):
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.admin_shares_v2_client.get_share_group_type_specs,
+            data_utils.rand_name('fake'))
+
+    @decorators.idempotent_id('2be79455-0ce7-4ca6-818f-40651ba79c6e')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_try_get_extra_spec_with_nonexistent_key(self):
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.admin_shares_v2_client.get_share_group_type_spec,
+            self.share_group_type['id'], 'fake_key')
diff --git a/manila_tempest_tests/tests/api/admin/test_share_networks.py b/manila_tempest_tests/tests/api/admin/test_share_networks.py
index 82d8a8a..3eedb4e 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_networks.py
@@ -18,6 +18,7 @@
 
 from manila_tempest_tests.tests.api import base
 from manila_tempest_tests.tests.api import test_share_networks
+from manila_tempest_tests import utils
 
 
 class ShareNetworkAdminTest(base.BaseSharesMixedTest,
@@ -26,7 +27,7 @@
     @classmethod
     def resource_setup(cls):
         super(ShareNetworkAdminTest, cls).resource_setup()
-        ss_data = cls.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         cls.ss_ldap = cls.create_security_service(**ss_data)
 
         cls.data_sn_with_ldap_ss = {
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types.py b/manila_tempest_tests/tests/api/admin/test_share_types.py
index abdb4ba..3d46c9e 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types.py
@@ -113,26 +113,22 @@
     @utils.skip_if_microversion_not_supported("2.50")
     @decorators.idempotent_id('a9af19e1-e789-4c4f-a39b-dd8df6ed00b1')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
-    @ddt.named_data(
-        ('2.50_name_description_public', '2.50',
-         data_utils.rand_name("type_updated"), 'description_updated', True),
-        ('2.50_name', '2.50', data_utils.rand_name("type_updated"), None,
-         None),
-        ('2.50_description_public', '2.50', None, 'description_updated',
-         None),
-        ('2.50_public', '2.50', None, None, True),
-        ('2.50', '2.50', None, None, False),
-        (f'{LATEST_MICROVERSION}_name_description_public',
-         LATEST_MICROVERSION, data_utils.rand_name("type_updated"),
+    @ddt.data(
+        ('2.50', data_utils.rand_name("type_updated"),
          'description_updated', True),
-        (f'{LATEST_MICROVERSION}_name', LATEST_MICROVERSION,
-         data_utils.rand_name("type_updated"), None, None),
-        (f'{LATEST_MICROVERSION}_description', LATEST_MICROVERSION, None,
-         'description_updated', None),
-        (f'{LATEST_MICROVERSION}_public', LATEST_MICROVERSION, None, None,
-         True),
-        (LATEST_MICROVERSION, LATEST_MICROVERSION, None, None, False),
+        ('2.50', data_utils.rand_name("type_updated"), None, None),
+        ('2.50', None, 'description_updated', None),
+        ('2.50', None, None, True),
+        ('2.50', None, None, False),
+        (LATEST_MICROVERSION, data_utils.rand_name("type_updated"),
+         'description_updated', True),
+        (LATEST_MICROVERSION, data_utils.rand_name("type_updated"),
+         None, None),
+        (LATEST_MICROVERSION, None, 'description_updated', None),
+        (LATEST_MICROVERSION, None, None, True),
+        (LATEST_MICROVERSION, None, None, False),
     )
+    @ddt.unpack
     def test_share_type_create_update(self, version, st_name,
                                       st_description, st_is_public):
         name = data_utils.rand_name("tempest-manila")
diff --git a/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py b/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
index 7e2f9f1..79e80e6 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
@@ -112,6 +112,8 @@
                          "provider_location"]
         if utils.is_microversion_ge(version, '2.17'):
             expected_keys.extend(["user_id", "project_id"])
+        if utils.is_microversion_ge(version, '2.73'):
+            expected_keys.extend(["metadata"])
 
         actual_keys = snapshot.keys()
 
@@ -135,7 +137,8 @@
 
     @decorators.idempotent_id('5fb65a19-fb73-4b5a-9210-010f93e0304f')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
-    @ddt.data('2.12', '2.16', CONF.share.max_api_microversion)
+    @ddt.data(*utils.deduplicate(['2.12', '2.16', '2.73',
+                                  CONF.share.max_api_microversion]))
     def test_manage_different_versions(self, version):
         """Run snapshot manage test for multiple versions.
 
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index 34f8e41..18562e5 100755
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -562,13 +562,14 @@
     @classmethod
     def create_snapshot_wait_for_active(cls, share_id, name=None,
                                         description=None, force=False,
-                                        client=None, cleanup_in_class=True):
+                                        metadata=None, client=None,
+                                        cleanup_in_class=True):
         if client is None:
             client = cls.shares_v2_client
         if description is None:
             description = "Tempest's snapshot"
         snapshot = client.create_snapshot(
-            share_id, name, description, force)['snapshot']
+            share_id, name, description, force, metadata)['snapshot']
         resource = {
             "type": "snapshot",
             "id": snapshot["id"],
@@ -675,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"],
@@ -722,35 +726,6 @@
         return replica
 
     @classmethod
-    def _get_access_rule_data_from_config(cls):
-        """Get the first available access type/to combination from config.
-
-        This method opportunistically picks the first configured protocol
-        to create the share. Do not use this method in tests where you need
-        to test depth and breadth in the access types and access recipients.
-        """
-        protocol = cls.shares_v2_client.share_protocol
-
-        if protocol in CONF.share.enable_ip_rules_for_protocols:
-            access_type = "ip"
-            access_to = utils.rand_ip()
-        elif protocol in CONF.share.enable_user_rules_for_protocols:
-            access_type = "user"
-            access_to = CONF.share.username_for_user_rules
-        elif protocol in CONF.share.enable_cert_rules_for_protocols:
-            access_type = "cert"
-            access_to = "client3.com"
-        elif protocol in CONF.share.enable_cephx_rules_for_protocols:
-            access_type = "cephx"
-            access_to = data_utils.rand_name(
-                cls.__class__.__name__ + '-cephx-id')
-        else:
-            message = "Unrecognized protocol and access rules configuration."
-            raise cls.skipException(message)
-
-        return access_type, access_to
-
-    @classmethod
     def create_share_network(cls, client=None,
                              cleanup_in_class=False,
                              add_security_services=True, **kwargs):
@@ -785,7 +760,7 @@
         share_network_subnet = client.create_subnet(
             **kwargs)['share_network_subnet']
         resource = {
-            "type": "share-network-subnet",
+            "type": "share_network_subnet",
             "id": share_network_subnet["id"],
             "extra_params": {
                 "share_network_id": share_network_subnet["share_network_id"]
@@ -817,6 +792,30 @@
         return security_service
 
     @classmethod
+    def create_resource_lock(cls, resource_id, resource_type='share',
+                             resource_action='delete', lock_reason=None,
+                             client=None, version=LATEST_MICROVERSION,
+                             cleanup_in_class=True):
+        lock_reason = lock_reason or "locked by tempest tests"
+        client = client or cls.shares_v2_client
+
+        lock = client.create_resource_lock(resource_id,
+                                           resource_type,
+                                           resource_action=resource_action,
+                                           lock_reason=lock_reason,
+                                           version=version)['resource_lock']
+        resource = {
+            "type": "resource_lock",
+            "id": lock["id"],
+            "client": client,
+        }
+        if cleanup_in_class:
+            cls.class_resources.insert(0, resource)
+        else:
+            cls.method_resources.insert(0, resource)
+        return lock
+
+    @classmethod
     def update_share_type(cls, share_type_id, name=None,
                           is_public=None, description=None,
                           client=None):
@@ -929,45 +928,13 @@
                     elif res["type"] == "quotas":
                         user_id = res.get('user_id')
                         client.reset_quotas(res_id, user_id=user_id)
+                    elif res["type"] == "resource_lock":
+                        client.delete_resource_lock(res_id)
                     else:
                         LOG.warning("Provided unsupported resource type for "
                                     "cleanup '%s'. Skipping.", res["type"])
                 res["deleted"] = True
 
-    @classmethod
-    def generate_share_network_data(self):
-        data = {
-            "name": data_utils.rand_name("sn-name"),
-            "description": data_utils.rand_name("sn-desc"),
-            "neutron_net_id": data_utils.rand_name("net-id"),
-            "neutron_subnet_id": data_utils.rand_name("subnet-id"),
-        }
-        return data
-
-    @classmethod
-    def generate_subnet_data(self):
-        data = {
-            "neutron_net_id": data_utils.rand_name("net-id"),
-            "neutron_subnet_id": data_utils.rand_name("subnet-id"),
-        }
-        return data
-
-    @classmethod
-    def generate_security_service_data(self, set_ou=False):
-        data = {
-            "name": data_utils.rand_name("ss-name"),
-            "description": data_utils.rand_name("ss-desc"),
-            "dns_ip": utils.rand_ip(),
-            "server": utils.rand_ip(),
-            "domain": data_utils.rand_name("ss-domain"),
-            "user": data_utils.rand_name("ss-user"),
-            "password": data_utils.rand_name("ss-password"),
-        }
-        if set_ou:
-            data["ou"] = data_utils.rand_name("ss-ou")
-
-        return data
-
     # Useful assertions
     def assertDictMatch(self, d1, d2, approx_equal=False, tolerance=0.001):
         """Assert two dicts are equivalent.
@@ -1053,7 +1020,8 @@
                      raise_rule_in_error_state=True, cleanup=True):
 
         client = client or self.shares_v2_client
-        a_type, a_to = self._get_access_rule_data_from_config()
+        a_type, a_to = utils.get_access_rule_data_from_config(
+            client.share_protocol)
         access_type = access_type or a_type
         access_to = access_to or a_to
 
diff --git a/manila_tempest_tests/tests/api/test_access_rules_metadata.py b/manila_tempest_tests/tests/api/test_access_rules_metadata.py
index ee541ac..6b0aa2d 100644
--- a/manila_tempest_tests/tests/api/test_access_rules_metadata.py
+++ b/manila_tempest_tests/tests/api/test_access_rules_metadata.py
@@ -55,8 +55,8 @@
     @classmethod
     def resource_setup(cls):
         super(AccessRulesMetadataTest, cls).resource_setup()
-        cls.protocol = cls.shares_v2_client.share_protocol
-        cls.access_type, __ = cls._get_access_rule_data_from_config()
+        cls.access_type, __ = utils.get_access_rule_data_from_config(
+            cls.shares_v2_client.share_protocol)
         int_range = range(20, 50)
         cls.access_to = {
             # list of unique values is required for ability to create lots
diff --git a/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py b/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
index c848ed3..98a1361 100644
--- a/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
+++ b/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
@@ -55,9 +55,9 @@
     @classmethod
     def resource_setup(cls):
         super(AccessesMetadataNegativeTest, cls).resource_setup()
-        cls.protocol = cls.shares_v2_client.share_protocol
         cls.access_type, cls.access_to = (
-            cls._get_access_rule_data_from_config()
+            utils.get_access_rule_data_from_config(
+                cls.shares_v2_client.share_protocol)
         )
         # create share type
         cls.share_type = cls.create_share_type()
diff --git a/manila_tempest_tests/tests/api/test_metadata.py b/manila_tempest_tests/tests/api/test_metadata.py
index d2ae326..bd73963 100644
--- a/manila_tempest_tests/tests/api/test_metadata.py
+++ b/manila_tempest_tests/tests/api/test_metadata.py
@@ -41,8 +41,8 @@
 
         # verify metadata items
         for key in md:
-            get_value = self.shares_v2_client.get_metadata_item(share["id"],
-                                                                key)
+            get_value = self.shares_v2_client.get_metadata_item(
+                share["id"], key)['meta']
             self.assertEqual(md[key], get_value[key])
 
     @decorators.idempotent_id('9070249f-6e94-4a38-a036-08debee547c3')
diff --git a/manila_tempest_tests/tests/api/test_metadata_negative.py b/manila_tempest_tests/tests/api/test_metadata_negative.py
index caa34ac..5caca5e 100644
--- a/manila_tempest_tests/tests/api/test_metadata_negative.py
+++ b/manila_tempest_tests/tests/api/test_metadata_negative.py
@@ -66,7 +66,7 @@
 
     @decorators.idempotent_id('759ca34d-1c87-43f3-8da2-8e1d373049ac')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
-    def test_try_upd_metadata_with_empty_key(self):
+    def test_try_update_metadata_with_empty_key(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.shares_v2_client.update_all_metadata,
                           self.share["id"], {"": "value"})
@@ -82,7 +82,7 @@
 
     @decorators.idempotent_id('33ef3047-6ca3-4547-a681-b52314382dcb')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
-    def test_try_upd_metadata_with_too_big_key(self):
+    def test_try_update_metadata_with_too_big_key(self):
         too_big_key = "x" * 256
         md = {too_big_key: "value"}
         self.assertRaises(lib_exc.BadRequest,
@@ -100,7 +100,7 @@
 
     @decorators.idempotent_id('c2eddcf0-cf81-4f9f-b06d-c9165ab8553e')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
-    def test_try_upd_metadata_with_too_big_value(self):
+    def test_try_update_metadata_with_too_big_value(self):
         too_big_value = "x" * 1024
         md = {"key": too_big_value}
         self.assertRaises(lib_exc.BadRequest,
diff --git a/manila_tempest_tests/tests/api/test_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 7873926..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):
@@ -330,7 +349,8 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
     def test_add_access_rule_create_replica_delete_rule(self):
         # Add access rule to the share
-        access_type, access_to = self._get_access_rule_data_from_config()
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.shares_v2_client.share_protocol)
         self.allow_access(
             self.shares[0]["id"], access_type=access_type, access_to=access_to,
             access_level='ro')
@@ -346,7 +366,8 @@
     @decorators.idempotent_id('3af3f19a-1195-464e-870b-1a3918914f1b')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
     def test_create_replica_add_access_rule_delete_replica(self):
-        access_type, access_to = self._get_access_rule_data_from_config()
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.shares_v2_client.share_protocol)
         # Create the replica
         share_replica = self._verify_create_replica()
 
@@ -358,6 +379,30 @@
         # Delete the replica
         self.delete_share_replica(share_replica["id"])
 
+    @decorators.idempotent_id('600a13d2-5cf0-482e-97af-9f598b55a406')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.74")
+    def test_add_access_rule_share_replica_error_status(self):
+        '''From 2.74, we can add rules even if replicas are in error state.'''
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.shares_v2_client.share_protocol)
+        # Create the replica
+        share_replica = self._verify_create_replica()
+
+        # Reset the replica status to error
+        self.admin_client.reset_share_replica_status(
+            share_replica['id'], constants.STATUS_ERROR)
+
+        # Verify access rule will be added in error state
+        self.shares_v2_client.create_access_rule(
+            self.shares[0]["id"], access_type=access_type, access_to=access_to,
+            access_level='ro')
+
+        # Verify access_rules_status transitions to 'active' state.
+        waiters.wait_for_resource_status(
+            self.shares_v2_client, self.shares[0]["id"],
+            constants.RULE_STATE_ACTIVE, status_attr='access_rules_status')
+
     @decorators.idempotent_id('a542c179-ea41-4bc0-bd80-e06eaddf5253')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
     @testtools.skipUnless(CONF.share.run_multiple_share_replicas_tests,
@@ -408,7 +453,8 @@
 
         share = self.create_shares([self.creation_data])[0]
         # Add access rule
-        access_type, access_to = self._get_access_rule_data_from_config()
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.shares_v2_client.share_protocol)
         self.allow_access(
             share["id"], access_type=access_type, access_to=access_to,
             access_level='ro')
diff --git a/manila_tempest_tests/tests/api/test_replication_negative.py b/manila_tempest_tests/tests/api/test_replication_negative.py
index e7d0e7d..9424a08 100644
--- a/manila_tempest_tests/tests/api/test_replication_negative.py
+++ b/manila_tempest_tests/tests/api/test_replication_negative.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
@@ -83,6 +84,7 @@
         return share, instance_id
 
 
+@ddt.ddt
 class ReplicationNegativeTest(ReplicationNegativeBase):
 
     def _is_replication_type_promotable(self):
@@ -189,8 +191,12 @@
 
     @decorators.idempotent_id('600a13d2-5cf0-482e-97af-9f598b55a407')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
-    def test_add_access_rule_share_replica_error_status(self):
-        access_type, access_to = self._get_access_rule_data_from_config()
+    @ddt.data('2.11', '2.73')
+    def test_add_access_rule_share_replica_error_status(self, version):
+        """From 2.74, we can add rules even if replicas are in error state."""
+        utils.check_skip_if_microversion_not_supported(version)
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.shares_v2_client.share_protocol)
         # Create the replica
         share_replica = self.create_share_replica(self.share1["id"],
                                                   self.replica_zone,
@@ -199,10 +205,12 @@
         self.admin_client.reset_share_replica_status(
             share_replica['id'], constants.STATUS_ERROR)
 
-        # Verify access rule cannot be added
-        self.assertRaises(lib_exc.BadRequest,
-                          self.admin_client.create_access_rule,
-                          self.share1["id"], access_type, access_to, 'ro')
+        if utils.is_microversion_lt(version, '2.74'):
+            # Verify access rule cannot be added
+            self.assertRaises(lib_exc.BadRequest,
+                              self.shares_v2_client.create_access_rule,
+                              self.share1["id"], access_type, access_to, 'ro',
+                              version)
 
     @decorators.idempotent_id('91b93b71-4048-412b-bb42-0fe88edfb987')
     @testtools.skipUnless(CONF.share.run_host_assisted_migration_tests or
@@ -248,7 +256,7 @@
     @utils.skip_if_microversion_not_supported("2.51")
     def test_try_add_replica_nonexistent_subnet(self):
         # Create a new share network only for a specific az
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
         subnet = utils.share_network_get_default_subnet(self.share_network)
         data['neutron_net_id'] = subnet['neutron_net_id']
         data['neutron_subnet_id'] = subnet['neutron_subnet_id']
diff --git a/manila_tempest_tests/tests/api/test_resource_locks.py b/manila_tempest_tests/tests/api/test_resource_locks.py
new file mode 100644
index 0000000..4f88d72
--- /dev/null
+++ b/manila_tempest_tests/tests/api/test_resource_locks.py
@@ -0,0 +1,291 @@
+# 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 datetime
+
+from oslo_utils import timeutils
+from oslo_utils import uuidutils
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
+
+CONF = config.CONF
+
+LOCKS_MIN_API_VERSION = '2.81'
+
+RESOURCE_LOCK_FIELDS = {
+    'id',
+    'resource_id',
+    'resource_action',
+    'resource_type',
+    'user_id',
+    'project_id',
+    'lock_context',
+    'created_at',
+    'updated_at',
+    'lock_reason',
+    'links',
+}
+
+
+class ResourceLockCRUTest(base.BaseSharesMixedTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ResourceLockCRUTest, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported(LOCKS_MIN_API_VERSION)
+
+    @classmethod
+    def resource_setup(cls):
+        super(ResourceLockCRUTest, cls).resource_setup()
+        # create share type
+        share_type = cls.create_share_type()
+        cls.share_type_id = share_type['id']
+
+        # create share and place a "delete" lock on it
+        cls.share = cls.create_share(share_type_id=cls.share_type_id)
+        cls.lock = cls.create_resource_lock(cls.share['id'])
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('f3d162a6-2ab4-433b-b8e7-6bf4f0bb6b0e')
+    def test_list_resource_locks(self):
+        locks = self.shares_v2_client.list_resource_locks()['resource_locks']
+        self.assertIsInstance(locks, list)
+        self.assertIn(self.lock['id'], [x['id'] for x in locks])
+        lock = locks[0]
+        self.assertEqual(RESOURCE_LOCK_FIELDS, set(lock.keys()))
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('72cc0d43-f676-4dd8-8a93-faa71608de98')
+    def test_list_resource_locks_sorted_and_paginated(self):
+        lock_2 = self.create_resource_lock(self.share['id'],
+                                           cleanup_in_class=False)
+        lock_3 = self.create_resource_lock(self.share['id'],
+                                           cleanup_in_class=False)
+
+        expected_order = [self.lock['id'], lock_2['id']]
+
+        filters = {'sort_key': 'created_at', 'sort_dir': 'asc', 'limit': 2}
+        body = self.shares_v2_client.list_resource_locks(filters=filters)
+        # tempest/lib/common/rest_client.py's _parse_resp checks
+        # for number of keys in response's dict, if there is only single
+        # key, it returns directly this key, otherwise it returns
+        # parsed body. If limit param is used, then API returns
+        # multiple keys in response ('resource_locks' and
+        # 'resource_lock_links')
+        locks = body['resource_locks']
+        self.assertIsInstance(locks, list)
+        actual_order = [x['id'] for x in locks]
+        self.assertEqual(2, len(actual_order))
+        self.assertNotIn(lock_3['id'], actual_order)
+        self.assertEqual(expected_order, actual_order)
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('22831edc-9d99-432d-a0b6-85af8853db98')
+    def test_list_resource_locks_filtered(self):
+        # Filter by resource_id, resource_action, lock_reason_like,
+        # created_since, created_before
+        share_2 = self.create_share(share_type_id=self.share_type_id)
+        share_1_lock_2 = self.create_resource_lock(
+            self.share['id'],
+            lock_reason="clemson tigers rule",
+            cleanup_in_class=False)
+        share_2_lock = self.create_resource_lock(share_2['id'],
+                                                 cleanup_in_class=False)
+
+        # filter by resource_type
+        expected_locks = sorted([
+            self.lock['id'],
+            share_1_lock_2['id'],
+            share_2_lock['id']
+        ])
+        actual_locks = self.shares_v2_client.list_resource_locks(
+            filters={'resource_type': 'share'})['resource_locks']
+        self.assertEqual(expected_locks,
+                         sorted([lock['id'] for lock in actual_locks]))
+
+        # filter by resource_id
+        expected_locks = sorted([self.lock['id'], share_1_lock_2['id']])
+        actual_locks = self.shares_v2_client.list_resource_locks(
+            filters={'resource_id': self.share['id']})['resource_locks']
+        self.assertEqual(expected_locks,
+                         sorted([lock['id'] for lock in actual_locks]))
+
+        # filter by inexact lock reason
+        actual_locks = self.shares_v2_client.list_resource_locks(
+            filters={'lock_reason~': "clemson"})['resource_locks']
+        self.assertEqual([share_1_lock_2['id']],
+                         [lock['id'] for lock in actual_locks])
+
+        # timestamp filters
+        created_at_1 = timeutils.parse_strtime(self.lock['created_at'])
+        created_at_2 = timeutils.parse_strtime(share_2_lock['created_at'])
+        time_1 = created_at_1 - datetime.timedelta(seconds=1)
+        time_2 = created_at_2 - datetime.timedelta(microseconds=1)
+        filters_1 = {'created_since': str(time_1)}
+
+        # should return all resource locks created by this test including
+        # self.lock
+        actual_locks = self.shares_v2_client.list_resource_locks(
+            filters=filters_1)['resource_locks']
+        actual_lock_ids = [lock['id'] for lock in actual_locks]
+        self.assertGreaterEqual(len(actual_lock_ids), 3)
+        self.assertIn(self.lock['id'], actual_lock_ids)
+        self.assertIn(share_1_lock_2['id'], actual_lock_ids)
+
+        for lock in actual_locks:
+            time_diff_with_created_since = timeutils.delta_seconds(
+                time_1, timeutils.parse_strtime(lock['created_at']))
+            self.assertGreaterEqual(time_diff_with_created_since, 0)
+
+        filters_2 = {
+            'created_since': str(time_1),
+            'created_before': str(time_2),
+        }
+
+        actual_locks = self.shares_v2_client.list_resource_locks(
+            filters=filters_2)['resource_locks']
+        self.assertIsInstance(actual_locks, list)
+        actual_lock_ids = [lock['id'] for lock in actual_locks]
+        self.assertGreaterEqual(len(actual_lock_ids), 2)
+        self.assertIn(self.lock['id'], actual_lock_ids)
+        self.assertIn(share_1_lock_2['id'], actual_lock_ids)
+        self.assertNotIn(share_2_lock['id'], actual_lock_ids)
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('8cbf7331-f3a1-4c7b-ab1e-f8b938bf135e')
+    def test_get_resource_lock(self):
+        lock = self.shares_v2_client.get_resource_lock(
+            self.lock['id'])['resource_lock']
+
+        self.assertEqual(set(RESOURCE_LOCK_FIELDS), set(lock.keys()))
+        self.assertTrue(uuidutils.is_uuid_like(lock['id']))
+        self.assertEqual('share', lock['resource_type'])
+        self.assertEqual(self.share['id'], lock['resource_id'])
+        self.assertEqual('delete', lock['resource_action'])
+        self.assertEqual('user', lock['lock_context'])
+        self.assertEqual(self.shares_v2_client.user_id, lock['user_id'])
+        self.assertEqual(self.shares_v2_client.project_id, lock['project_id'])
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('a7f0fb6a-05ac-4afa-b8d9-04d20549bbd1')
+    def test_create_resource_lock(self):
+        # testing lock creation by a different user in the same project
+        project = self.os_admin.projects_client.show_project(
+            self.shares_v2_client.project_id)['project']
+        new_user_client = self.create_user_and_get_client(project)
+
+        lock = self.create_resource_lock(
+            self.share['id'],
+            client=new_user_client.shares_v2_client,
+            cleanup_in_class=False)
+
+        self.assertEqual(set(RESOURCE_LOCK_FIELDS), set(lock.keys()))
+        self.assertTrue(uuidutils.is_uuid_like(lock['id']))
+        self.assertEqual('share', lock['resource_type'])
+        self.assertEqual(self.share['id'], lock['resource_id'])
+        self.assertEqual('delete', lock['resource_action'])
+        self.assertEqual('user', lock['lock_context'])
+        self.assertEqual(new_user_client.shares_v2_client.user_id,
+                         lock['user_id'])
+        self.assertEqual(self.shares_v2_client.project_id, lock['project_id'])
+
+        # testing lock creation by admin
+        lock = self.create_resource_lock(
+            self.share['id'],
+            client=self.admin_shares_v2_client,
+            cleanup_in_class=False)
+        self.assertEqual('admin', lock['lock_context'])
+
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('d7b51cde-ff4f-45ce-a237-401e8be5b4e5')
+    def test_update_resource_lock(self):
+        lock = self.shares_v2_client.update_resource_lock(
+            self.lock['id'], lock_reason="new lock reason")['resource_lock']
+
+        # update is synchronous
+        self.assertEqual("new lock reason", lock['lock_reason'])
+
+        # verify get
+        lock = self.shares_v2_client.get_resource_lock(lock['id'])
+        self.assertEqual("new lock reason",
+                         lock['resource_lock']['lock_reason'])
+
+
+class ResourceLockDeleteTest(base.BaseSharesMixedTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ResourceLockDeleteTest, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported(LOCKS_MIN_API_VERSION)
+
+    @classmethod
+    def resource_setup(cls):
+        super(ResourceLockDeleteTest, cls).resource_setup()
+        cls.share_type_id = cls.create_share_type()['id']
+
+    @decorators.idempotent_id('835fd617-4600-40a0-9ba1-40e5e0097b01')
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    def test_delete_lock(self):
+        share = self.create_share(share_type_id=self.share_type_id)
+        lock_1 = self.create_resource_lock(share['id'], cleanup_in_class=False)
+        lock_2 = self.create_resource_lock(share['id'], cleanup_in_class=False)
+
+        locks = self.shares_v2_client.list_resource_locks(
+            filters={'resource_id': share['id']})['resource_locks']
+        self.assertEqual(sorted([lock_1['id'], lock_2['id']]),
+                         sorted([lock['id'] for lock in locks]))
+
+        self.shares_v2_client.delete_resource_lock(lock_1['id'])
+        locks = self.shares_v2_client.list_resource_locks(
+            filters={'resource_id': share['id']})['resource_locks']
+        self.assertEqual(1, len(locks))
+        self.assertIn(lock_2['id'], [lock['id'] for lock in locks])
+
+    @decorators.idempotent_id('a96e70c7-0afe-4335-9abc-4b45ef778bd7')
+    @decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND])
+    def test_delete_locked_resource(self):
+        share = self.create_share(share_type_id=self.share_type_id)
+        lock_1 = self.create_resource_lock(share['id'], cleanup_in_class=False)
+        lock_2 = self.create_resource_lock(share['id'], cleanup_in_class=False)
+
+        # share can't be deleted when a lock exists
+        self.assertRaises(lib_exc.Forbidden,
+                          self.shares_v2_client.delete_share,
+                          share['id'])
+
+        # admin can't do this either
+        self.assertRaises(lib_exc.Forbidden,
+                          self.admin_shares_v2_client.delete_share,
+                          share['id'])
+        # "the force" shouldn't work either
+        self.assertRaises(lib_exc.Forbidden,
+                          self.admin_shares_v2_client.delete_share,
+                          share['id'],
+                          params={'force': True})
+
+        self.shares_v2_client.delete_resource_lock(lock_1['id'])
+
+        # there's at least one lock, share deletion should still fail
+        self.assertRaises(lib_exc.Forbidden,
+                          self.shares_v2_client.delete_share,
+                          share['id'])
+
+        self.shares_v2_client.delete_resource_lock(lock_2['id'])
+
+        # locks are gone, share deletion should be possible
+        self.shares_v2_client.delete_share(share['id'])
+        self.shares_v2_client.wait_for_resource_deletion(
+            share_id=share["id"])
diff --git a/manila_tempest_tests/tests/api/test_resource_locks_negative.py b/manila_tempest_tests/tests/api/test_resource_locks_negative.py
new file mode 100644
index 0000000..9501d6c
--- /dev/null
+++ b/manila_tempest_tests/tests/api/test_resource_locks_negative.py
@@ -0,0 +1,127 @@
+#    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.
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
+
+CONF = config.CONF
+
+LOCKS_MIN_API_VERSION = '2.81'
+
+
+class ResourceLockNegativeTestAPIOnly(base.BaseSharesMixedTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ResourceLockNegativeTestAPIOnly, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported(LOCKS_MIN_API_VERSION)
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+    @decorators.idempotent_id('dd978cf7-1622-49e8-a6c8-3da4ac6c6f86')
+    def test_create_resource_lock_invalid_resource(self):
+        self.assertRaises(
+            lib_exc.BadRequest,
+            self.shares_v2_client.create_resource_lock,
+            'invalid-share-id',
+            'share'
+        )
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+    @decorators.idempotent_id('d5600bdc-72c8-43fd-9900-c112aa6c87fa')
+    def test_delete_resource_lock_invalid(self):
+        self.assertRaises(
+            lib_exc.NotFound,
+            self.shares_v2_client.delete_resource_lock,
+            'invalid-lock-id'
+        )
+
+
+class ResourceLockNegativeTestWithShares(base.BaseSharesMixedTest):
+    @classmethod
+    def skip_checks(cls):
+        super(ResourceLockNegativeTestWithShares, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported(LOCKS_MIN_API_VERSION)
+
+    @classmethod
+    def resource_setup(cls):
+        super(ResourceLockNegativeTestWithShares, cls).resource_setup()
+        share_type = cls.create_share_type()
+        cls.share = cls.create_share(share_type_id=share_type['id'])
+        cls.user_project = cls.os_admin.projects_client.show_project(
+            cls.shares_v2_client.project_id)['project']
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('658297a8-d675-471d-8a19-3d9e9af3a352')
+    def test_create_resource_lock_invalid_resource_action(self):
+        self.assertRaises(
+            lib_exc.BadRequest,
+            self.shares_v2_client.create_resource_lock,
+            self.share['id'],
+            'share',
+            resource_action='invalid-action'
+        )
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('0057b3e7-c250-492d-805b-e355dff954ed')
+    def test_create_resource_lock_invalid_lock_reason_too_long(self):
+        self.assertRaises(
+            lib_exc.BadRequest,
+            self.shares_v2_client.create_resource_lock,
+            self.share['id'],
+            'share',
+            resource_action='delete',
+            lock_reason='invalid' * 150,
+        )
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('a2db3d29-b42f-4c0b-b484-afd32f91f747')
+    def test_update_resource_lock_invalid_param(self):
+        lock = self.create_resource_lock(self.share['id'])
+        self.assertRaises(
+            lib_exc.BadRequest,
+            self.shares_v2_client.update_resource_lock,
+            lock['id'],
+            resource_action='invalid-action'
+        )
+        self.assertRaises(
+            lib_exc.BadRequest,
+            self.shares_v2_client.update_resource_lock,
+            lock['id'],
+            lock_reason='invalid' * 150,
+        )
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('45b12120-0fc3-461f-8776-fdb92e599394')
+    def test_update_resource_lock_created_by_different_user(self):
+        lock = self.create_resource_lock(self.share['id'])
+        new_user = self.create_user_and_get_client(project=self.user_project)
+        self.assertRaises(
+            lib_exc.Forbidden,
+            new_user.shares_v2_client.update_resource_lock,
+            lock['id'],
+            lock_reason="I shouldn't be able to do this",
+        )
+
+    @decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND])
+    @decorators.idempotent_id('00a8ef2b-8769-4aad-aefc-43fc579492f7')
+    def test_delete_resource_lock_created_by_different_user(self):
+        lock = self.create_resource_lock(self.share['id'])
+        new_user = self.create_user_and_get_client(project=self.user_project)
+        self.assertRaises(
+            lib_exc.Forbidden,
+            new_user.shares_v2_client.delete_resource_lock,
+            lock['id'],
+        )
diff --git a/manila_tempest_tests/tests/api/test_revert_to_snapshot.py b/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
index 7609e69..dca394a 100644
--- a/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
+++ b/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
@@ -122,6 +122,9 @@
         waiters.wait_for_resource_status(
             self.shares_v2_client, self.share['id'],
             constants.STATUS_AVAILABLE)
+        waiters.wait_for_resource_status(
+            self.shares_v2_client, snapshot['id'], constants.STATUS_AVAILABLE,
+            resource_name='snapshot')
 
     @decorators.idempotent_id('09bd9942-7ef9-4d24-b2dd-f83bdda27b50')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@@ -145,6 +148,9 @@
         waiters.wait_for_resource_status(
             self.shares_v2_client, self.share['id'],
             constants.STATUS_AVAILABLE)
+        waiters.wait_for_resource_status(
+            self.shares_v2_client, snapshot1['id'], constants.STATUS_AVAILABLE,
+            resource_name='snapshot')
 
     @decorators.idempotent_id('146de138-d351-49dc-a13a-5cdbed40b9ac')
     @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@@ -181,3 +187,6 @@
             self.shares_v2_client, share_replica['id'],
             constants.REPLICATION_STATE_IN_SYNC, resource_name='share_replica',
             status_attr='replica_state')
+        waiters.wait_for_resource_status(
+            self.shares_v2_client, snapshot['id'], constants.STATUS_AVAILABLE,
+            resource_name='snapshot')
diff --git a/manila_tempest_tests/tests/api/test_rules.py b/manila_tempest_tests/tests/api/test_rules.py
index 979bf06..925b725 100644
--- a/manila_tempest_tests/tests/api/test_rules.py
+++ b/manila_tempest_tests/tests/api/test_rules.py
@@ -437,9 +437,9 @@
     @classmethod
     def resource_setup(cls):
         super(ShareRulesTest, cls).resource_setup()
-        cls.protocol = cls.shares_v2_client.share_protocol
         cls.access_type, cls.access_to = (
-            cls._get_access_rule_data_from_config()
+            utils.get_access_rule_data_from_config(
+                cls.shares_v2_client.share_protocol)
         )
         cls.share_type = cls.create_share_type()
         cls.share_type_id = cls.share_type['id']
diff --git a/manila_tempest_tests/tests/api/test_rules_negative.py b/manila_tempest_tests/tests/api/test_rules_negative.py
index 1eb858d..a4b53f5 100644
--- a/manila_tempest_tests/tests/api/test_rules_negative.py
+++ b/manila_tempest_tests/tests/api/test_rules_negative.py
@@ -153,7 +153,8 @@
     @decorators.idempotent_id('d2856c7d-9417-416d-8d08-e68376ee5b2e')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
     def test_add_access_rule_on_share_with_no_host(self):
-        access_type, access_to = self._get_access_rule_data_from_config()
+        access_type, access_to = utils.get_access_rule_data_from_config(
+            self.protocol)
         extra_specs = self.add_extra_specs_to_dict(
             {"share_backend_name": 'invalid_backend'})
         share_type = self.create_share_type('invalid_backend',
diff --git a/manila_tempest_tests/tests/api/test_security_services.py b/manila_tempest_tests/tests/api/test_security_services.py
index f938a91..85ed5fb 100644
--- a/manila_tempest_tests/tests/api/test_security_services.py
+++ b/manila_tempest_tests/tests/api/test_security_services.py
@@ -162,7 +162,7 @@
     @decorators.idempotent_id('70927e29-4a6a-431a-bbc1-76bc419e0579')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_delete_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         self.service_names = ["ldap", "kerberos", "active_directory"]
         for ss_name in self.service_names:
             ss = self.create_security_service(ss_name, **data)
@@ -176,7 +176,7 @@
     def test_get_security_service(self, version):
         utils.check_skip_if_microversion_not_supported(version)
         with_ou = True if utils.is_microversion_ge(version, '2.44') else False
-        data = self.generate_security_service_data(set_ou=with_ou)
+        data = utils.generate_security_service_data(set_ou=with_ou)
 
         if utils.is_microversion_ge(version, '2.0'):
             ss = self.create_security_service(
@@ -196,11 +196,11 @@
     @decorators.idempotent_id('84d47747-13c8-4ab9-9fc4-a43fbb29ad18')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_update_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         ss = self.create_security_service(**data)
         self.assertDictContainsSubset(data, ss)
 
-        upd_data = self.generate_security_service_data()
+        upd_data = utils.generate_security_service_data()
         updated = self.shares_client.update_security_service(
             ss["id"], **upd_data)['security_service']
 
@@ -211,7 +211,7 @@
 
         if utils.is_microversion_ge(CONF.share.max_api_microversion, '2.44'):
             # update again with ou
-            upd_data_ou = self.generate_security_service_data(set_ou=True)
+            upd_data_ou = utils.generate_security_service_data(set_ou=True)
             updated_ou = self.shares_v2_client.update_security_service(
                 ss["id"], **upd_data_ou)['security_service']
 
@@ -225,7 +225,7 @@
     @testtools.skipIf(
         not CONF.share.multitenancy_enabled, "Only for multitenancy.")
     def test_try_update_valid_keys_sh_server_exists(self):
-        ss_data = self.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         ss = self.create_security_service(**ss_data)
 
         sn = self.shares_client.get_share_network(
@@ -274,7 +274,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_try_list_security_services_all_tenants_ignored(self):
         alt_security_service = self.create_security_service(
-            **self.generate_security_service_data(),
+            **utils.generate_security_service_data(),
             client=self.alt_shares_v2_client)
         alt_security_service_id = alt_security_service['id']
         sec_service_list = self.shares_client.list_security_services(
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping.py b/manila_tempest_tests/tests/api/test_security_services_mapping.py
index 2e7531d..6ce9a0a 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping.py
@@ -17,6 +17,7 @@
 from testtools import testcase as tc
 
 from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
 
 
 class SecurityServicesMappingTest(base.BaseSharesTest):
@@ -30,7 +31,7 @@
         super(SecurityServicesMappingTest, self).setUp()
 
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         self.sn = self.create_share_network(client=self.cl,
                                             add_security_services=False,
@@ -38,7 +39,7 @@
         self.assertDictContainsSubset(data, self.sn)
 
         # create security service
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
 
         self.ss = self.create_security_service(client=self.cl, **data)
         self.assertDictContainsSubset(data, self.ss)
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
index d0bb321..96506ce 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
@@ -146,7 +146,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_map_two_ss_with_same_type_to_sn(self):
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         sn = self.create_share_network(client=self.cl,
                                        add_security_services=False, **data)
@@ -155,7 +155,7 @@
         # create security services with same type
         security_services = []
         for i in range(2):
-            data = self.generate_security_service_data()
+            data = utils.generate_security_service_data()
             ss = self.create_security_service(client=self.cl, **data)
             self.assertDictContainsSubset(data, ss)
             security_services.insert(i, ss)
@@ -173,14 +173,14 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_delete_ss_that_assigned_to_sn(self):
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         sn = self.create_share_network(client=self.cl,
                                        add_security_services=False, **data)
         self.assertDictContainsSubset(data, sn)
 
         # create security service
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
 
         ss = self.create_security_service(client=self.cl, **data)
         self.assertDictContainsSubset(data, ss)
diff --git a/manila_tempest_tests/tests/api/test_security_services_negative.py b/manila_tempest_tests/tests/api/test_security_services_negative.py
index 08e3c7b..23c7cc1 100644
--- a/manila_tempest_tests/tests/api/test_security_services_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_negative.py
@@ -21,6 +21,7 @@
 from testtools import testcase as tc
 
 from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
 
 CONF = config.CONF
 LOG = log.getLogger(__name__)
@@ -93,7 +94,7 @@
     @testtools.skipIf(
         not CONF.share.multitenancy_enabled, "Only for multitenancy.")
     def test_try_update_invalid_keys_sh_server_exists(self):
-        ss_data = self.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         ss = self.create_security_service(**ss_data)
 
         sn = self.shares_client.get_share_network(
@@ -129,7 +130,7 @@
     @decorators.idempotent_id('288dbf42-ee22-4445-8363-7ebb1c3d89c9')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_get_deleted_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         ss = self.create_security_service(**data)
         self.assertDictContainsSubset(data, ss)
 
diff --git a/manila_tempest_tests/tests/api/test_share_groups.py b/manila_tempest_tests/tests/api/test_share_groups.py
index b203481..ab6b9d1 100644
--- a/manila_tempest_tests/tests/api/test_share_groups.py
+++ b/manila_tempest_tests/tests/api/test_share_groups.py
@@ -45,7 +45,7 @@
     @classmethod
     def resource_setup(cls):
         super(ShareGroupsTest, cls).resource_setup()
-        # create share type
+        # create share  type
         extra_specs = {}
         if CONF.share.capability_snapshot_support:
             extra_specs.update({'snapshot_support': True})
@@ -208,6 +208,16 @@
             new_share_group['share_network_id'],
             msg)
 
+        # Delete the share group snapshot and wait
+        self.shares_v2_client.delete_share_group_snapshot(
+            sg_snapshot["id"], version=constants.MIN_SHARE_GROUP_MICROVERSION)
+        self.shares_v2_client.wait_for_resource_deletion(
+            share_group_snapshot_id=sg_snapshot["id"])
+
+        # Delete share group, so share network subnet deletion does not fail
+        self.shares_v2_client.delete_share_group(
+            share_group['id'], version=constants.MIN_SHARE_GROUP_MICROVERSION)
+
     @utils.skip_if_microversion_not_supported("2.34")
     @decorators.idempotent_id('14fd6d88-87ff-4af2-ad17-f95dbd8dcd61')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -387,6 +397,11 @@
             params=params,
             version=constants.MIN_SHARE_GROUP_MICROVERSION)
         self.shares_client.wait_for_resource_deletion(share_id=share['id'])
+
+        # Delete share group
+        self.shares_v2_client.delete_share_group(
+            share_group['id'], version=constants.MIN_SHARE_GROUP_MICROVERSION)
+
         # Delete subnet
         self.shares_v2_client.delete_subnet(
             new_share_network_id, subnet1['id'])
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets.py b/manila_tempest_tests/tests/api/test_share_network_subnets.py
index cdf2162..1ae5351 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets.py
@@ -61,7 +61,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
@@ -75,6 +75,8 @@
             "updated_at", "segmentation_id", "availability_zone", "gateway",
             "share_network_id", "mtu"
         ]
+        if utils.is_microversion_ge(CONF.share.max_api_microversion, '2.78'):
+            keys.extend(['metadata'])
 
         # Default subnet was created during share network creation
         self.assertIsNone(default_subnet['availability_zone'])
@@ -95,7 +97,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
index 7b0ca55..52b297e 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
@@ -55,7 +55,7 @@
     @decorators.idempotent_id('d20b6105-22d1-4fc0-8468-45dd019240c0')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_add_share_network_subnet_share_network_not_found(self):
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         self.assertRaises(lib_exc.NotFound,
                           self.shares_v2_client.create_subnet,
                           'fake_inexistent_id',
@@ -94,7 +94,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_add_share_network_subnet_missing_parameters(self):
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['availability_zone'] = self.az_name
 
         data.pop('neutron_net_id')
@@ -122,7 +122,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_get_deleted_subnet(self):
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = self.share_network_id
         az = self.shares_v2_client.list_availability_zones(
             )['availability_zones'][0]
diff --git a/manila_tempest_tests/tests/api/test_share_networks.py b/manila_tempest_tests/tests/api/test_share_networks.py
index e3d5a78..f990566 100644
--- a/manila_tempest_tests/tests/api/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/test_share_networks.py
@@ -165,7 +165,7 @@
         cls.share_type = cls.create_share_type()
         cls.share_type_id = cls.share_type['id']
 
-        ss_data = cls.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         cls.ss_ldap = cls.create_security_service(**ss_data)
 
         cls.data_sn_with_ldap_ss = {
@@ -219,7 +219,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_delete_share_network(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create share network
         created = self.shares_client.create_share_network(
@@ -242,7 +242,7 @@
     @decorators.idempotent_id('1837fdd3-8068-4e88-bc50-9224498f84c0')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_update_share_network(self):
-        update_data = self.generate_share_network_data()
+        update_data = utils.generate_share_network_data()
         updated = self.shares_client.update_share_network(
             self.sn_with_ldap_ss["id"],
             **update_data)['share_network']
@@ -268,7 +268,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_recreate_share_network(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create share network
         sn1 = self.shares_client.create_share_network(**data)['share_network']
@@ -288,7 +288,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_two_share_networks_with_same_net_and_subnet(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create first share network
         sn1 = self.create_share_network(**data)
diff --git a/manila_tempest_tests/tests/api/test_share_networks_negative.py b/manila_tempest_tests/tests/api/test_share_networks_negative.py
index 3306068..94fa7b8 100644
--- a/manila_tempest_tests/tests/api/test_share_networks_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_networks_negative.py
@@ -88,7 +88,7 @@
     @decorators.idempotent_id('9166b81c-d6ab-4592-bcf7-9410250e30dd')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_get_deleted_share_network(self):
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
         sn = self.create_share_network(**data)
         self.assertDictContainsSubset(data, sn)
 
@@ -166,7 +166,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
@@ -200,7 +200,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     @decorators.idempotent_id('f6f47c64-6821-4d4a-aa7d-3b0244158197')
     def test_check_add_share_network_subnet_share_network_not_found(self):
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         self.assertRaises(lib_exc.NotFound,
                           self.shares_v2_client.subnet_create_check,
                           'fake_inexistent_id',
diff --git a/manila_tempest_tests/tests/api/test_share_servers_multiple_subnet_negative.py b/manila_tempest_tests/tests/api/test_share_servers_multiple_subnet_negative.py
index 522f34e..a230163 100644
--- a/manila_tempest_tests/tests/api/test_share_servers_multiple_subnet_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_servers_multiple_subnet_negative.py
@@ -32,13 +32,17 @@
         super(ShareServerMultipleSubNegativeTest, cls).skip_checks()
         if not CONF.share.multitenancy_enabled:
             raise cls.skipException('Multitenancy tests are disabled.')
+        if not CONF.share.run_share_server_multiple_subnet_tests:
+            raise cls.skipException(
+                'Share server multiple subnets and network allocation '
+                'update tests are disabled.')
         utils.check_skip_if_microversion_not_supported("2.70")
 
     @classmethod
     def resource_setup(cls):
         super(ShareServerMultipleSubNegativeTest, cls).resource_setup()
-        cls.share_network = cls.alt_shares_v2_client.get_share_network(
-            cls.alt_shares_v2_client.share_network_id)['share_network']
+        cls.share_network = cls.shares_v2_client.get_share_network(
+            cls.shares_v2_client.share_network_id)['share_network']
 
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
     @decorators.idempotent_id('1e2a9415-b02f-4c02-812d-bedc361f92ce')
@@ -53,9 +57,9 @@
         zones = self.get_availability_zones_matching_share_type(
             share_type)
         if not pools or not zones:
-            raise self.skipException("At least one backend that supports "
-                                     "adding multiple subnets into a share "
-                                     "network is needed for this test.")
+            raise self.skipException("At least one backend that does not "
+                                     "support adding multiple subnets into a "
+                                     "share network is needed for this test.")
         extra_specs = {'pool_name': pools[0]['pool'],
                        'availability_zone': zones[0]}
         self.admin_shares_v2_client.update_share_type_extra_specs(
diff --git a/manila_tempest_tests/tests/api/test_share_types_negative.py b/manila_tempest_tests/tests/api/test_share_types_negative.py
index 3b930f9..046af45 100644
--- a/manila_tempest_tests/tests/api/test_share_types_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_types_negative.py
@@ -83,17 +83,15 @@
     @utils.skip_if_microversion_not_supported("2.50")
     @decorators.idempotent_id('4a22945c-8988-43a1-88c9-eb86e6abcd8e')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
-    @ddt.named_data(
-        ('2.50', '2.50', '', None, None),
-        (LATEST_MICROVERSION, LATEST_MICROVERSION, '', None, None),
-        ('2.50_bad_public', '2.50', None, None, 'not_bool'),
-        (f'{LATEST_MICROVERSION}_bad_public', LATEST_MICROVERSION, None, None,
-         'not_bool'),
-        ('2.50_description', '2.50', None, generate_long_description(256),
-         None),
-        (f'{LATEST_MICROVERSION}_description', LATEST_MICROVERSION, None,
-         generate_long_description(256), None),
+    @ddt.data(
+        ('2.50', '', None, None),
+        (LATEST_MICROVERSION, '', None, None),
+        ('2.50', None, None, 'not_bool'),
+        (LATEST_MICROVERSION, None, None, 'not_bool'),
+        ('2.50', None, generate_long_description(256), None),
+        (LATEST_MICROVERSION, None, generate_long_description(256), None),
     )
+    @ddt.unpack
     def test_share_type_update_bad_request(
             self, version, st_name, st_description, st_is_public):
         st_id = self.st['id']
diff --git a/manila_tempest_tests/tests/api/test_shares.py b/manila_tempest_tests/tests/api/test_shares.py
index 3ff87b2..11b6963 100644
--- a/manila_tempest_tests/tests/api/test_shares.py
+++ b/manila_tempest_tests/tests/api/test_shares.py
@@ -157,6 +157,13 @@
             self.assertNotIn('user_id', detailed_elements)
             self.assertNotIn('project_id', detailed_elements)
 
+        # In v2.73 and beyond, we expect metadata key
+        if utils.is_microversion_supported('2.73'):
+            detailed_elements.update({'metadata'})
+            self.assertTrue(detailed_elements.issubset(snap.keys()), msg)
+        else:
+            self.assertNotIn('metadata', detailed_elements)
+
         # delete snapshot
         self.shares_client.delete_snapshot(snap["id"])
         self.shares_client.wait_for_resource_deletion(snapshot_id=snap["id"])
diff --git a/manila_tempest_tests/tests/api/test_shares_actions.py b/manila_tempest_tests/tests/api/test_shares_actions.py
index 779bfb6..1b987ae 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions.py
@@ -469,6 +469,8 @@
                          "description", "id", "share_size", "size"]
         if version and utils.is_microversion_ge(version, '2.17'):
             expected_keys.extend(["user_id", "project_id"])
+        if version and utils.is_microversion_ge(version, '2.73'):
+            expected_keys.extend(["metadata"])
         actual_keys = snapshot.keys()
 
         # strict key check
@@ -547,6 +549,11 @@
                          "share_size", "size"]
         if version and utils.is_microversion_ge(version, '2.17'):
             expected_keys.extend(["user_id", "project_id"])
+        if version and utils.is_microversion_ge(version, '2.73'):
+            expected_keys.append("metadata")
+
+        if version and utils.is_microversion_ge(version, '2.73'):
+            expected_keys.extend(["metadata"])
 
         # strict key check
         [self.assertEqual(set(expected_keys), set(s.keys())) for s in snaps]
diff --git a/manila_tempest_tests/tests/api/test_snapshot_metadata.py b/manila_tempest_tests/tests/api/test_snapshot_metadata.py
new file mode 100644
index 0000000..0596213
--- /dev/null
+++ b/manila_tempest_tests/tests/api/test_snapshot_metadata.py
@@ -0,0 +1,317 @@
+# 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.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from testtools import testcase as tc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
+
+CONF = config.CONF
+LATEST_MICROVERSION = CONF.share.max_api_microversion
+
+
+class ShareSnapshotMetadataTest(base.BaseSharesMixedTest):
+    @classmethod
+    def skip_checks(cls):
+        super(ShareSnapshotMetadataTest, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported("2.73")
+        if not CONF.share.run_snapshot_tests:
+            raise cls.skipException('Snapshot tests are disabled.')
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareSnapshotMetadataTest, cls).resource_setup()
+        # create share_type
+        extra_specs = {}
+        if CONF.share.capability_snapshot_support:
+            extra_specs.update({'snapshot_support': True})
+        if CONF.share.capability_create_share_from_snapshot_support:
+            extra_specs.update({'create_share_from_snapshot_support': True})
+        cls.share_type = cls.create_share_type(extra_specs=extra_specs)
+        cls.share_type_id = cls.share_type['id']
+
+        # create share
+        cls.share_name = data_utils.rand_name("tempest-share-name")
+        cls.share_desc = data_utils.rand_name("tempest-share-description")
+        cls.share = cls.create_share(
+            name=cls.share_name,
+            description=cls.share_desc,
+            share_type_id=cls.share_type_id,
+        )
+        cls.share_id = cls.share["id"]
+
+        # create snapshot
+        cls.snap_name = data_utils.rand_name("tempest-snapshot-name")
+        cls.snap_desc = data_utils.rand_name(
+            "tempest-snapshot-description")
+        cls.snap = cls.create_snapshot_wait_for_active(
+            cls.share_id, cls.snap_name, cls.snap_desc)
+        cls.snap_id = cls.snap['id']
+
+    def _verify_snapshot_metadata(self, snapshot, md):
+
+        # get metadata of snapshot
+        metadata = self.shares_v2_client.get_metadata(
+            snapshot['id'], resource="snapshot")['metadata']
+
+        # verify metadata
+        self.assertEqual(md, metadata)
+
+        # verify metadata items
+        for key in md:
+            get_value = self.shares_v2_client.get_metadata_item(
+                snapshot['id'], key, resource="snapshot")['meta']
+            self.assertEqual(md[key], get_value[key])
+
+    @decorators.idempotent_id('5d537913-ce6f-4771-beb2-84e2390b06d3')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_in_snapshot_creation(self):
+
+        md = {u"key1": u"value1", u"key2": u"value2", }
+
+        # create snapshot with metadata
+        snapshot = self.create_snapshot_wait_for_active(
+            share_id=self.share_id, metadata=md,
+            cleanup_in_class=False)
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md)
+
+    @decorators.idempotent_id('7cbdf3c5-fb72-4ea5-9e60-ba50bad68ee9')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_get_delete_metadata(self):
+
+        md = {u"key3": u"value3", u"key4": u"value4", u"key.5.1": u"value.5"}
+
+        # create snapshot
+        snapshot = self.create_snapshot_wait_for_active(
+            share_id=self.share_id,
+            cleanup_in_class=False)
+
+        # set metadata
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md, resource="snapshot")
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md)
+
+        # delete metadata
+        for key in md.keys():
+            self.shares_v2_client.delete_metadata(
+                snapshot['id'], key, resource="snapshot")
+
+        # verify deletion of metadata
+        get_metadata = self.shares_v2_client.get_metadata(
+            snapshot['id'], resource="snapshot")['metadata']
+        self.assertEmpty(get_metadata)
+
+    @decorators.idempotent_id('23ec837d-1b50-499c-bbb9-a7bde843c9e8')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_not_delete_pre_metadata(self):
+        md1 = {u"key9": u"value9", u"key10": u"value10", }
+        md2 = {u"key11": u"value11", u"key12": u"value12", }
+
+        # create snapshot
+        snapshot = self.create_snapshot_wait_for_active(
+            share_id=self.share_id,
+            cleanup_in_class=False)
+
+        # set metadata
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md1, resource="snapshot")
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md1)
+
+        # set metadata again
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md2, resource="snapshot")
+
+        # verify metadata
+        md1.update(md2)
+        md = md1
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md)
+
+        # delete metadata
+        for key in md.keys():
+            self.shares_v2_client.delete_metadata(
+                snapshot['id'], key, resource="snapshot")
+
+        # verify deletion of metadata
+        get_metadata = self.shares_v2_client.get_metadata(
+            snapshot['id'], resource="snapshot")['metadata']
+        self.assertEmpty(get_metadata)
+
+    @decorators.idempotent_id('b7a00be5-3dd1-4d25-8723-c662581c923f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_key_already_exist(self):
+        md1 = {u"key9": u"value9", u"key10": u"value10", }
+        md2 = {u"key9": u"value13", u"key11": u"value11", }
+
+        # create snapshot
+        snapshot = self.create_snapshot_wait_for_active(
+            share_id=self.share_id,
+            cleanup_in_class=False)
+
+        # set metadata
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md1, resource="snapshot")
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md1)
+
+        # set metadata again
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md2, resource="snapshot")
+
+        # verify metadata
+        md1.update(md2)
+        self._verify_snapshot_metadata(snapshot, md1)
+
+        # delete metadata
+        for key in md1.keys():
+            self.shares_v2_client.delete_metadata(
+                snapshot['id'], key, resource="snapshot")
+
+        # verify deletion of metadata
+        get_metadata = self.shares_v2_client.get_metadata(
+            snapshot['id'], resource="snapshot")['metadata']
+        self.assertEmpty(get_metadata)
+
+    @decorators.idempotent_id('90120310-07a9-43f4-9d5e-38d0a3f2f5bb')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_and_update_metadata_by_key(self):
+
+        md1 = {u"key5": u"value5", u"key6": u"value6", }
+        md2 = {u"key7": u"value7", u"key8": u"value8", }
+
+        # create snapshot
+        snapshot = self.create_snapshot_wait_for_active(
+            share_id=self.share_id,
+            cleanup_in_class=False)
+
+        # set metadata
+        self.shares_v2_client.set_metadata(
+            snapshot['id'], md1, resource="snapshot")
+
+        # update metadata
+        self.shares_v2_client.update_all_metadata(
+            snapshot['id'], md2, resource="snapshot")
+
+        # verify metadata
+        self._verify_snapshot_metadata(snapshot, md2)
+
+    @decorators.idempotent_id('8963b7ae-db3a-476e-b0c7-29023e7aa321')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_min_size_key(self):
+        data = {"k": "value"}
+
+        self.shares_v2_client.set_metadata(self.snap_id,
+                                           data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data['k'], body_get.get('k'))
+
+    @decorators.idempotent_id('dc226070-5820-4df2-a30a-9dfb2f037a4b')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_max_size_key(self):
+        max_key = "k" * 255
+        data = {max_key: "value"}
+
+        self.shares_v2_client.set_metadata(self.snap_id,
+                                           data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertIn(max_key, body_get)
+        self.assertEqual(data[max_key], body_get.get(max_key))
+
+    @decorators.idempotent_id('940c283f-4f43-4122-86e8-32230da81886')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_min_size_value(self):
+        data = {"key": "v"}
+
+        self.shares_v2_client.set_metadata(self.snap_id,
+                                           data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data['key'], body_get['key'])
+
+    @decorators.idempotent_id('85c480bc-0ffa-43e1-bc0a-284c5641996d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_metadata_max_size_value(self):
+        max_value = "v" * 1023
+        data = {"key": max_value}
+
+        self.shares_v2_client.set_metadata(self.snap_id,
+                                           data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data['key'], body_get['key'])
+
+    @decorators.idempotent_id('c42335ae-ee90-4b73-b022-51c0a9bc301d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_upd_metadata_min_size_key(self):
+        data = {"k": "value"}
+
+        self.shares_v2_client.update_all_metadata(self.snap_id,
+                                                  data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data, body_get)
+
+    @decorators.idempotent_id('1b5f06b0-bbff-49d1-8a4b-6e912039e2ba')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_upd_metadata_max_size_key(self):
+        max_key = "k" * 255
+        data = {max_key: "value"}
+
+        self.shares_v2_client.update_all_metadata(self.snap_id,
+                                                  data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data, body_get)
+
+    @decorators.idempotent_id('849fdcd4-9b4c-4aea-833a-240d7d06966b')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_upd_metadata_min_size_value(self):
+        data = {"key": "v"}
+
+        self.shares_v2_client.update_all_metadata(self.snap_id,
+                                                  data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data, body_get)
+
+    @decorators.idempotent_id('fdfbe469-6403-41de-b909-c4c13fc57407')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_upd_metadata_max_size_value(self):
+        max_value = "v" * 1023
+        data = {"key": max_value}
+
+        self.shares_v2_client.update_all_metadata(self.snap_id,
+                                                  data, resource="snapshot")
+
+        body_get = self.shares_v2_client.get_metadata(
+            self.snap_id, resource="snapshot")['metadata']
+        self.assertEqual(data, body_get)
diff --git a/manila_tempest_tests/tests/api/test_snapshot_metadata_negative.py b/manila_tempest_tests/tests/api/test_snapshot_metadata_negative.py
new file mode 100644
index 0000000..7a80e4a
--- /dev/null
+++ b/manila_tempest_tests/tests/api/test_snapshot_metadata_negative.py
@@ -0,0 +1,142 @@
+# 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 ddt
+from tempest import config
+from tempest.lib.common.utils import data_utils
+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 import utils
+
+CONF = config.CONF
+LATEST_MICROVERSION = CONF.share.max_api_microversion
+
+
+@ddt.ddt
+class ShareSnapshotMetadataNegativeTest(base.BaseSharesMixedTest):
+    @classmethod
+    def skip_checks(cls):
+        super(ShareSnapshotMetadataNegativeTest, cls).skip_checks()
+        utils.check_skip_if_microversion_not_supported("2.73")
+        if not CONF.share.run_snapshot_tests:
+            raise cls.skipException('Snapshot tests are disabled.')
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareSnapshotMetadataNegativeTest, cls).resource_setup()
+        # create share_type
+        extra_specs = {}
+        if CONF.share.capability_snapshot_support:
+            extra_specs.update({'snapshot_support': True})
+        if CONF.share.capability_create_share_from_snapshot_support:
+            extra_specs.update({'create_share_from_snapshot_support': True})
+        cls.share_type = cls.create_share_type(extra_specs=extra_specs)
+        cls.share_type_id = cls.share_type['id']
+
+        # create share
+        cls.share_name = data_utils.rand_name("tempest-share-name")
+        cls.share_desc = data_utils.rand_name("tempest-share-description")
+        cls.metadata = {
+            'foo_key_share_1': 'foo_value_share_1',
+            'bar_key_share_1': 'foo_value_share_1',
+        }
+        cls.share = cls.create_share(
+            name=cls.share_name,
+            description=cls.share_desc,
+            metadata=cls.metadata,
+            share_type_id=cls.share_type_id,
+        )
+        cls.share_id = cls.share["id"]
+
+        # create snapshot
+        cls.snap_name = data_utils.rand_name("tempest-snapshot-name")
+        cls.snap_desc = data_utils.rand_name(
+            "tempest-snapshot-description")
+        cls.snap = cls.create_snapshot_wait_for_active(
+            cls.share_id, cls.snap_name, cls.snap_desc)
+        cls.snap_id = cls.snap['id']
+
+    @decorators.idempotent_id('8be4773b-6af9-413f-97e2-8acdb6149e7a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_try_set_metadata_to_unexisting_snapshot(self):
+        md = {u"key1": u"value1", u"key2": u"value2", }
+        self.assertRaises(lib_exc.NotFound,
+                          self.shares_v2_client.set_metadata,
+                          "wrong_snapshot_id", md, resource="snapshot")
+
+    @decorators.idempotent_id('03a7f6e9-de8b-4669-87e1-b179308b477d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_try_update_all_metadata_to_unexisting_snapshot(self):
+        md = {u"key1": u"value1", u"key2": u"value2", }
+        self.assertRaises(lib_exc.NotFound,
+                          self.shares_v2_client.update_all_metadata,
+                          "wrong_snapshot_id", md, resource="snapshot")
+
+    @decorators.idempotent_id('ef0afcc8-7b12-41bc-8aa1-4916ad4b4560')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_set_metadata_with_empty_key(self):
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.set_metadata,
+                          self.snap_id, {"": "value"}, resource="snapshot")
+
+    @decorators.idempotent_id('9f2aee7c-ebd6-4516-87f7-bd85453d74c9')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_upd_metadata_with_empty_key(self):
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.update_all_metadata,
+                          self.snap_id, {"": "value"}, resource="snapshot")
+
+    @decorators.idempotent_id('ef61255e-462c-49fe-8e94-ff3afafcccb3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_set_metadata_with_too_big_key(self):
+        too_big_key = "x" * 256
+        md = {too_big_key: "value"}
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.set_metadata,
+                          self.snap_id, md, resource="snapshot")
+
+    @decorators.idempotent_id('f896f354-6179-4abb-b0c5-7b7dc96f0870')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_upd_metadata_with_too_big_key(self):
+        too_big_key = "x" * 256
+        md = {too_big_key: "value"}
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.update_all_metadata,
+                          self.snap_id, md, resource="snapshot")
+
+    @decorators.idempotent_id('1bf97c18-27df-4618-94f4-224d1a98bc0c')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_set_metadata_with_too_big_value(self):
+        too_big_value = "x" * 1024
+        md = {"key": too_big_value}
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.set_metadata,
+                          self.snap_id, md, resource="snapshot")
+
+    @decorators.idempotent_id('2b9e08fa-b35d-4bfe-9137-e59ab50bd9ef')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_upd_metadata_with_too_big_value(self):
+        too_big_value = "x" * 1024
+        md = {"key": too_big_value}
+        self.assertRaises(lib_exc.BadRequest,
+                          self.shares_v2_client.update_all_metadata,
+                          self.snap_id, md, resource="snapshot")
+
+    @decorators.idempotent_id('9afb381d-c48c-4c2c-a5b5-42463daef5a2')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_try_delete_unexisting_metadata(self):
+        self.assertRaises(lib_exc.NotFound,
+                          self.shares_v2_client.delete_metadata,
+                          self.snap_id, "wrong_key", resource="snapshot")
diff --git a/manila_tempest_tests/tests/rbac/__init__.py b/manila_tempest_tests/tests/rbac/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/__init__.py
diff --git a/manila_tempest_tests/tests/rbac/base.py b/manila_tempest_tests/tests/rbac/base.py
new file mode 100644
index 0000000..d3c63de
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/base.py
@@ -0,0 +1,204 @@
+# 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.
+
+
+from tempest import clients
+from tempest import config
+from tempest.lib import auth
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+
+from manila_tempest_tests.common import waiters
+
+CONF = config.CONF
+
+
+class ShareRbacBaseTests(object):
+
+    identity_version = 'v3'
+    protocols = ['nfs', 'cifs', 'glusterfs', 'hdfs', 'cephfs', 'maprfs']
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacBaseTests, cls).skip_checks()
+        if not CONF.enforce_scope.manila:
+            raise cls.skipException(
+                "Tempest is not configured to enforce_scope for manila, "
+                "skipping RBAC tests. To enable these tests set "
+                "`tempest.conf [enforce_scope] manila=True`."
+            )
+        if not CONF.share.default_share_type_name:
+            raise cls.skipException("Secure rbac tests require a default "
+                                    "share type")
+        if not any(p in CONF.share.enable_protocols for p in cls.protocols):
+            message = "%s tests are disabled" % cls.protocol
+            raise cls.skipException(message)
+
+    @classmethod
+    def delete_resource(cls, client, **kwargs):
+        key_names = {
+            'st': 'share_type',
+            'sn': 'share_network',
+        }
+        key, resource_id = list(kwargs.items())[0]
+        key = key.rsplit('_', 1)[0]
+        resource_name = key_names[key] if key in key_names else key
+
+        del_action = getattr(client, 'delete_{}'.format(resource_name))
+        test_utils.call_and_ignore_notfound_exc(
+            del_action, resource_id)
+        test_utils.call_and_ignore_notfound_exc(
+            client.wait_for_resource_deletion, **kwargs)
+
+    @classmethod
+    def create_share(cls, client, share_type_id, size=None, name=None,
+                     metadata=None):
+        kwargs = {}
+        name = name or data_utils.rand_name('share')
+        metadata = metadata or {}
+        kwargs.update({
+            'share_protocol': cls.protocol,
+            'size': size or CONF.share.share_size,
+            'name': name or data_utils.rand_name('share'),
+            'share_type_id': share_type_id,
+            'metadata': metadata,
+        })
+        share = client.create_share(**kwargs)['share']
+        waiters.wait_for_resource_status(client, share['id'], 'available')
+        cls.addClassResourceCleanup(
+            cls.delete_resource, client,
+            share_id=share['id'])
+        return share
+
+    @classmethod
+    def create_snapshot(cls, client, share_id, name=None, metadata=None):
+        name = name or data_utils.rand_name('snapshot')
+        snapshot = client.create_snapshot(
+            share_id, name=name, metadata=metadata)['snapshot']
+        waiters.wait_for_resource_status(
+            client, snapshot['id'], 'available', resource_name='snapshot')
+        cls.addClassResourceCleanup(
+            cls.delete_resource, client, snapshot_id=snapshot['id'])
+        return snapshot
+
+    @classmethod
+    def create_share_network(cls, client, name=None):
+        name = name or data_utils.rand_name('share_network')
+        share_network = client.create_share_network(name=name)['share_network']
+
+        cls.addClassResourceCleanup(
+            cls.delete_resource, client, sn_id=share_network['id'])
+        return share_network
+
+    @classmethod
+    def create_share_type(cls):
+        name = data_utils.rand_name('share-type')
+        extra_specs = {
+            'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+        }
+        share_type = cls.admin_shares_v2_client.create_share_type(
+            name=name, extra_specs=extra_specs)['share_type']
+        cls.addClassResourceCleanup(
+            cls.delete_resource, cls.admin_shares_v2_client,
+            st_id=share_type['id'])
+        return share_type
+
+    @classmethod
+    def create_share_group_type(cls, share_types, is_public=True,
+                                group_specs=None):
+        name = data_utils.rand_name('share-group-type')
+        share_group_type = (
+            cls.admin_shares_v2_client.create_share_group_type(
+                name=name, share_types=share_types, is_public=is_public,
+                group_specs=group_specs))['share_group_type']
+        cls.addClassResourceCleanup(
+            cls.delete_resource, cls.admin_shares_v2_client,
+            share_group_type_id=share_group_type['id'])
+        return share_group_type
+
+    @classmethod
+    def create_share_group(cls, client, share_group_type_id, share_type_ids):
+        name = data_utils.rand_name('share-group')
+        share_group = client.create_share_group(
+            name=name, share_group_type_id=share_group_type_id,
+            share_type_ids=share_type_ids)['share_group']
+        waiters.wait_for_resource_status(
+            client, share_group['id'], 'available',
+            resource_name='share_group')
+        cls.addClassResourceCleanup(
+            cls.delete_resource, client,
+            share_group_id=share_group['id'])
+        return share_group
+
+    @classmethod
+    def get_share_type(cls):
+        return cls.shares_v2_client.get_default_share_type()['share_type']
+
+    def do_request(self, method, expected_status=200, client=None, **payload):
+        if not client:
+            client = self.client
+        if isinstance(expected_status, type(Exception)):
+            self.assertRaises(expected_status,
+                              getattr(client, method),
+                              **payload)
+        else:
+            response = getattr(client, method)(**payload)
+            self.assertEqual(response.response.status, expected_status)
+            return response
+
+    @classmethod
+    def setup_user_client(cls, client, project_id=None):
+        """Set up project user with its own client.
+
+        This is useful for testing protection of resources in separate
+        projects.
+        NOTE(lkuchlan): Tempest creates 'project_member' and 'project_reader'
+        dynamic credentials in different projects. So this method is also
+        necessary for testing protection of resources in a specific project.
+
+        Returns a client object and the user's ID.
+        """
+
+        projects_client = client.identity_v3.ProjectsClient()
+        users_client = client.identity_v3.UsersClient()
+        roles_client = client.identity_v3.RolesClient()
+
+        user_dict = {
+            'name': data_utils.rand_name('user'),
+            'password': data_utils.rand_password(),
+        }
+        user_id = users_client.create_user(
+            **user_dict)['user']['id']
+        cls.addClassResourceCleanup(users_client.delete_user, user_id)
+
+        if not project_id:
+            project_id = projects_client.create_project(
+                data_utils.rand_name())['project']['id']
+            cls.addClassResourceCleanup(
+                projects_client.delete_project,
+                project_id)
+
+        member_role_id = roles_client.list_roles(
+            name='member')['roles'][0]['id']
+        roles_client.create_user_role_on_project(
+            project_id, user_id, member_role_id)
+        creds = auth.KeystoneV3Credentials(
+            user_id=user_id,
+            password=user_dict['password'],
+            project_id=project_id)
+        auth_provider = clients.get_auth_provider(creds)
+        creds = auth_provider.fill_credentials()
+        client = clients.Manager(credentials=creds)
+        return client
diff --git a/manila_tempest_tests/tests/rbac/test_availability_zones.py b/manila_tempest_tests/tests/rbac/test_availability_zones.py
new file mode 100644
index 0000000..1754726
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_availability_zones.py
@@ -0,0 +1,69 @@
+# 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.lib import decorators
+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
+
+
+class ShareRbacAvailabilityZonesTests(rbac_base.ShareRbacBaseTests,
+                                      metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacAvailabilityZonesTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+
+    @abc.abstractmethod
+    def test_list_availability_zones(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacAvailabilityZonesTests,
+                               base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @decorators.idempotent_id('87d9bb1c-f4de-40e5-8f25-05a6e1055c0b')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
+
+
+class TestProjectMemberTestsNFS(ShareRbacAvailabilityZonesTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_member']
+
+    @decorators.idempotent_id('ee2db349-176a-47bc-a20d-5ba9b5f8a813')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
+
+
+class TestProjectReaderTestsNFS(ShareRbacAvailabilityZonesTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_reader']
+
+    @decorators.idempotent_id('a095fac8-ae62-4be7-8a3e-b0fc1bc71348')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
diff --git a/manila_tempest_tests/tests/rbac/test_export_locations.py b/manila_tempest_tests/tests/rbac/test_export_locations.py
new file mode 100644
index 0000000..4bd7074
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_export_locations.py
@@ -0,0 +1,216 @@
+# 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 ShareRbacExportLocationsTests(rbac_base.ShareRbacBaseTests,
+                                    metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacExportLocationsTests, 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(ShareRbacExportLocationsTests, 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())
+
+    @abc.abstractmethod
+    def test_list_export_locations(self):
+        pass
+
+    @abc.abstractmethod
+    def test_show_export_location(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacExportLocationsTests,
+                               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('c8d75c9f-104b-48a8-9817-17280ce516a8')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_export_locations(self):
+        locations = self.do_request(
+            'list_share_export_locations', expected_status=200,
+            share_id=self.share['id'])['export_locations']
+        self.assertNotEmpty(locations)
+
+        alt_locations = self.do_request(
+            'list_share_export_locations', expected_status=200,
+            share_id=self.alt_share['id'])['export_locations']
+        self.assertNotEmpty(alt_locations)
+
+    @decorators.idempotent_id('01ac6355-fcad-4af8-b0ad-748fc111051d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_show_export_location(self):
+        export_location = self.share_member_client.list_share_export_locations(
+            self.share['id'])['export_locations']
+        self.do_request(
+            'get_share_export_location', expected_status=200,
+            share_id=self.share['id'],
+            export_location_uuid=export_location[0]['id'])
+
+        export_location = (
+            self.alt_project_share_v2_client.list_share_export_locations(
+                self.alt_share['id'])['export_locations'])
+        self.do_request(
+            'get_share_export_location', expected_status=200,
+            share_id=self.alt_share['id'],
+            export_location_uuid=export_location[0]['id'])
+
+
+class TestProjectMemberTestsNFS(ShareRbacExportLocationsTests,
+                                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('b25351bb-102f-437e-a0c1-01d926fa0a7d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_export_locations(self):
+        locations = self.do_request(
+            'list_share_export_locations', expected_status=200,
+            share_id=self.share['id'])['export_locations']
+        self.assertNotEmpty(locations)
+
+        self.do_request(
+            'list_share_export_locations', expected_status=lib_exc.Forbidden,
+            share_id=self.alt_share['id'])
+
+    @decorators.idempotent_id('95297484-1081-4225-986d-e4b3017d992f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_show_export_location(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        export_location = share_client.list_share_export_locations(
+            self.share['id'])['export_locations']
+        self.do_request(
+            'get_share_export_location', expected_status=200,
+            share_id=self.share['id'],
+            export_location_uuid=export_location[0]['id'])
+
+        export_location = (
+            self.alt_project_share_v2_client.list_share_export_locations(
+                self.alt_share['id'])['export_locations'])
+        self.do_request(
+            'get_share_export_location', expected_status=lib_exc.Forbidden,
+            share_id=self.alt_share['id'],
+            export_location_uuid=export_location[0]['id'])
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+    """Test suite for basic share export location 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()
+        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('889ecfa7-89b3-4b16-a368-f55bbc6af228')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_export_locations(self):
+        super(TestProjectReaderTestsNFS, self).test_list_export_locations()
+
+    @decorators.idempotent_id('1ab5f0c2-d844-4284-9b66-1ba2aa14b835')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_show_export_location(self):
+        super(TestProjectReaderTestsNFS, self).test_show_export_location()
+
+
+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_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..8a6d46f
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_rules.py
@@ -0,0 +1,529 @@
+# 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'}
+
+    def access(self, share_id, access_type, access_to, access_level='rw'):
+        access = {}
+        access['share_id'] = share_id
+        access['access_type'] = access_type
+        access['access_to'] = 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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.do_request(
+            'create_access_rule', expected_status=200,
+            **self.access(self.share['id'], access_type, access_to))['access']
+        waiters.wait_for_resource_status(
+            self.client, self.share["id"], "active",
+            resource_name='access_rule', rule_id=access["id"])
+        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_type, access_to))['access']
+        waiters.wait_for_resource_status(
+            self.client, self.alt_share["id"], "active",
+            resource_name='access_rule', rule_id=alt_access["id"])
+        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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type,
+            access_to=access_to, cleanup=False)
+        self.do_request(
+            'delete_access_rule', expected_status=202,
+            share_id=self.share['id'], rule_id=access['id'])
+        self.client.wait_for_resource_deletion(
+            rule_id=access['id'], share_id=self.share['id'])
+
+        alt_access = self.allow_access(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            access_type=access_type, access_to=access_to,
+            cleanup=False)
+        self.do_request(
+            'delete_access_rule', expected_status=202,
+            share_id=self.alt_share['id'], rule_id=alt_access['id'])
+        self.client.wait_for_resource_deletion(
+            rule_id=alt_access['id'], share_id=self.alt_share['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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        share_client = getattr(self, 'share_member_client', self.client)
+        access = self.allow_access(
+            share_client, self.share['id'], access_type=access_type,
+            access_to=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=access_type, access_to=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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        share_client = getattr(self, 'share_member_client', self.client)
+        access = self.allow_access(
+            share_client, self.share['id'], access_type=access_type,
+            access_to=access_to)
+        alt_access = self.allow_access(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            access_type=access_type, access_to=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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        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_type, access_to))['access']
+        waiters.wait_for_resource_status(
+            share_client, self.share["id"], "active",
+            resource_name='access_rule', rule_id=access["id"])
+        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'], access_type, access_to))
+
+    @decorators.idempotent_id('8665d1b1-de4c-42d4-93ff-8dc6d2b73a2d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_access(self):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        share_client = getattr(self, 'share_member_client', self.client)
+        access = self.allow_access(
+            share_client, self.share['id'], access_type=access_type,
+            access_to=access_to, cleanup=False)
+        self.do_request(
+            'delete_access_rule', expected_status=202,
+            share_id=self.share['id'], rule_id=access['id'])
+        self.client.wait_for_resource_deletion(
+            rule_id=access['id'], share_id=self.share['id'])
+
+        alt_access = self.allow_access(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            access_type=access_type, access_to=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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        share_client = getattr(self, 'share_member_client', self.client)
+        access = self.allow_access(
+            share_client, self.share['id'], access_type=access_type,
+            access_to=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=access_type, access_to=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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        share_client = getattr(self, 'share_member_client', self.client)
+        access = self.allow_access(
+            share_client, self.share['id'], access_type=access_type,
+            access_to=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=access_type, access_to=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()
+
+    @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):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        self.do_request(
+            'create_access_rule', expected_status=lib_exc.Forbidden,
+            **self.access(self.share['id'], access_type, access_to))
+
+        self.do_request(
+            'create_access_rule', expected_status=lib_exc.Forbidden,
+            **self.access(self.alt_share['id'], access_type, access_to))
+
+    @decorators.idempotent_id('7a702c74-8d31-49e3-859a-cc8a78d7915e')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_access(self):
+        access_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_type, access_to = (
+            utils.get_access_rule_data_from_config(self.protocol))
+        access = self.allow_access(
+            self.share_member_client, self.share['id'],
+            access_type=access_type, access_to=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=access_type, access_to=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_scheduler_stats.py b/manila_tempest_tests/tests/rbac/test_scheduler_stats.py
new file mode 100644
index 0000000..c1194b0
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_scheduler_stats.py
@@ -0,0 +1,73 @@
+# 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 ShareRbacSchedulerStatsTests(rbac_base.ShareRbacBaseTests,
+                                   metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacSchedulerStatsTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+
+    @abc.abstractmethod
+    def test_list_storage_pools(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacSchedulerStatsTests, base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @decorators.idempotent_id('1ec4d0f5-0d60-4bbc-88a4-57fa92f6f62f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_storage_pools(self):
+        self.do_request(
+            'list_pools', expected_status=200)
+
+
+class ProjectMemberTests(ShareRbacSchedulerStatsTests, base.BaseSharesTest):
+
+    credentials = ['project_member']
+
+    @decorators.idempotent_id('905aa5ea-eff9-4022-be41-df7a8593809d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_storage_pools(self):
+        self.do_request(
+            'list_pools', expected_status=lib_exc.Forbidden)
+
+
+class ProjectReaderTests(ShareRbacSchedulerStatsTests, base.BaseSharesTest):
+
+    credentials = ['project_reader']
+
+    @decorators.idempotent_id('faab12f9-ff51-458d-af47-362d872761e9')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_storage_pools(self):
+        self.do_request(
+            'list_pools', expected_status=lib_exc.Forbidden)
diff --git a/manila_tempest_tests/tests/rbac/test_services.py b/manila_tempest_tests/tests/rbac/test_services.py
new file mode 100644
index 0000000..5bb9bbe
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_services.py
@@ -0,0 +1,66 @@
+# 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 ShareRbacServicesTests(rbac_base.ShareRbacBaseTests,
+                             metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacServicesTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+
+    def test_list_services(self):
+        pass
+
+
+class TestProjectAdminTests(ShareRbacServicesTests, base.BaseSharesTest):
+    credentials = ['project_admin']
+
+    @decorators.idempotent_id('08ec3a0b-6e4a-4cbf-bd15-3f48f8ddf71f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_services(self):
+        self.do_request('list_services', expected_status=200)
+
+
+class TestProjectMemberTests(ShareRbacServicesTests, base.BaseSharesTest):
+    credentials = ['project_member']
+
+    @decorators.idempotent_id('7431dca6-9b03-48d3-b97c-41f72f7ed0a3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_services(self):
+        self.do_request('list_services', expected_status=lib_exc.Forbidden)
+
+
+class TestProjectReaderTests(TestProjectMemberTests):
+    credentials = ['project_reader']
+
+    @decorators.idempotent_id('eca71619-d563-4d15-9e49-b661e6da46c0')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_services(self):
+        super(TestProjectReaderTests, self).test_list_services()
diff --git a/manila_tempest_tests/tests/rbac/test_share_group_types.py b/manila_tempest_tests/tests/rbac/test_share_group_types.py
new file mode 100644
index 0000000..ac2f54b
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_group_types.py
@@ -0,0 +1,372 @@
+# 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.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 ShareRbacShareGroupTypesTests(rbac_base.ShareRbacBaseTests,
+                                    metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacShareGroupTypesTests, 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())
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacShareGroupTypesTests, cls).skip_checks()
+        if not CONF.share.run_share_group_tests:
+            raise cls.skipException('Share Group tests disabled.')
+
+        utils.check_skip_if_microversion_not_supported(
+            constants.MIN_SHARE_GROUP_MICROVERSION)
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareRbacShareGroupTypesTests, cls).resource_setup()
+        cls.group_specs1 = {u'key1': u'value1'}
+        cls.group_specs2 = {u'key2': u'value2'}
+        cls.share_type = cls.create_share_type()
+        cls.share_group_type = cls.create_share_group_type(
+            cls.share_type['id'], group_specs=cls.group_specs1)
+        cls.private_share_group_type = cls.create_share_group_type(
+            cls.share_type['id'], is_public=False)
+
+    @abc.abstractmethod
+    def test_create_share_group_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_share_group_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share_group_types(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_group_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_create_share_group_type_extra_specs(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_group_type_extra_spec(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_group_type_extra_spec(self):
+        pass
+
+    @abc.abstractmethod
+    def test_add_share_group_type_access(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share_group_type_access(self):
+        pass
+
+    @abc.abstractmethod
+    def test_remove_share_group_type_access(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacShareGroupTypesTests, base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @decorators.idempotent_id('9ea9954a-ae09-4d02-a082-9a72b80009fc')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_group_type(self):
+        share_group_type = self.do_request(
+            'create_share_group_type', expected_status=200,
+            name='gt', share_types=self.share_type['id'])['share_group_type']
+        self.addCleanup(self.delete_resource, self.client,
+                        share_group_type_id=share_group_type['id'])
+
+    @decorators.idempotent_id('fcad2b86-ca43-42b0-82bd-37e6f760e4d2')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_group_type(self):
+        self.do_request(
+            'get_share_group_type', expected_status=200,
+            share_group_type_id=self.share_group_type['id'])
+
+    @decorators.idempotent_id('7871b1b5-610a-425c-9363-d0bcf2beff72')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_group_types(self):
+        share_group_type_list = self.do_request(
+            'list_share_group_types', expected_status=200)['share_group_types']
+        share_group_type_id_list = [
+            sgt['id'] for sgt in share_group_type_list
+        ]
+        self.assertIn(self.share_group_type['id'], share_group_type_id_list)
+
+    @decorators.idempotent_id('c23da121-8b1f-4443-80cc-11881745a1c3')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_share_group_type(self):
+        share_group_type = self.create_share_group_type(
+            share_types=self.share_type['id'])
+        self.do_request(
+            'delete_share_group_type', expected_status=204,
+            share_group_type_id=share_group_type['id'])
+
+    @decorators.idempotent_id('80eb22cb-846a-4b51-a71d-ceef0b804901')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_group_type_extra_specs(self):
+        self.do_request(
+            'create_share_group_type_specs', expected_status=200,
+            share_group_type_id=self.share_group_type['id'],
+            group_specs_dict=self.group_specs2)
+        self.addCleanup(
+            self.admin_shares_v2_client.delete_share_group_type_spec,
+            self.share_group_type['id'], group_spec_key='key2')
+
+    @decorators.idempotent_id('fe29877d-2226-42ca-b492-4be0dacd6eaf')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_update_share_group_type_extra_spec(self):
+        self.do_request(
+            'update_share_group_type_spec', expected_status=200,
+            share_group_type_id=self.share_group_type['id'],
+            group_spec_key='key', group_spec_value='value_updated')
+
+    @decorators.idempotent_id('743c18dc-8c3a-4934-9ef8-8b342daffe7c')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_share_group_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_group_type_specs(
+            self.share_group_type['id'], self.group_specs2)
+        self.do_request(
+            'delete_share_group_type_spec', expected_status=204,
+            share_group_type_id=self.share_group_type['id'],
+            group_spec_key='key2')
+
+    @decorators.idempotent_id('89876c46-1167-450d-8b98-746d97fff388')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_add_share_group_type_access(self):
+        self.do_request(
+            'add_access_to_share_group_type', expected_status=202,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+        self.addCleanup(
+            self.client.remove_access_from_share_group_type,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+
+    @decorators.idempotent_id('64a7be53-d1af-40c3-950b-743a2704ac97')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_group_type_access(self):
+        self.client.add_access_to_share_group_type(
+            self.private_share_group_type['id'], self.client.project_id)
+        self.addCleanup(
+            self.client.remove_access_from_share_group_type,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+        access_list = self.do_request(
+            'list_access_to_share_group_type', expected_status=200,
+            share_group_type_id=self.private_share_group_type['id']
+        )['share_group_type_access']
+
+        project_id_list = [
+            access['project_id'] for access in access_list
+        ]
+
+        self.assertIn(self.client.project_id, project_id_list)
+
+    @decorators.idempotent_id('fc67ba18-78e9-4c02-9b37-2bd49c8a4470')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_remove_share_group_type_access(self):
+        self.client.add_access_to_share_group_type(
+            self.private_share_group_type['id'], self.client.project_id)
+        self.do_request(
+            'remove_access_from_share_group_type', expected_status=202,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+
+
+class ProjectMemberTests(ShareRbacShareGroupTypesTests, base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_admin']
+
+    @decorators.idempotent_id('f9e6f2fd-7c1a-4eee-817c-bf1988904515')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_group_type(self):
+        self.do_request(
+            'create_share_group_type', expected_status=lib_exc.Forbidden,
+            name='gt', share_types=self.share_type['id'])
+
+    @decorators.idempotent_id('8eaf4a99-9706-41c9-8b12-40856d0900f4')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_group_type(self):
+        self.do_request(
+            'get_share_group_type', expected_status=200,
+            share_group_type_id=self.share_group_type['id'])
+
+    @decorators.idempotent_id('d2dd61f4-c763-49f9-9c93-8b587879f554')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_group_types(self):
+        share_group_type_list = self.do_request(
+            'list_share_group_types', expected_status=200)['share_group_types']
+        share_group_type_id_list = [
+            sgt['id'] for sgt in share_group_type_list
+        ]
+        self.assertIn(self.share_group_type['id'], share_group_type_id_list)
+
+    @decorators.idempotent_id('8f45798f-717d-41b0-acba-a80dd647cddf')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_group_type(self):
+        share_group_type = self.create_share_group_type(
+            share_types=self.share_type['id'])
+        self.do_request(
+            'delete_share_group_type', expected_status=lib_exc.Forbidden,
+            share_group_type_id=share_group_type['id'])
+
+    @decorators.idempotent_id('2fa2f953-f068-4c60-ab52-eeb1bd69a7a4')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_group_type_extra_specs(self):
+        self.do_request(
+            'create_share_group_type_specs', expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.share_group_type['id'],
+            group_specs_dict=self.group_specs2)
+
+    @decorators.idempotent_id('30c73c94-b7bc-4e1f-8172-192335997879')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_group_type_extra_spec(self):
+        self.do_request(
+            'update_share_group_type_spec', expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.share_group_type['id'],
+            group_spec_key='key', group_spec_value='value_updated')
+
+    @decorators.idempotent_id('95aa1fbf-3eaf-4d65-96b5-4554b0fb0937')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_group_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_group_type_specs(
+            self.share_group_type['id'], self.group_specs2)
+        self.do_request(
+            'delete_share_group_type_spec', expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.share_group_type['id'],
+            group_spec_key='key2')
+
+    @decorators.idempotent_id('85b69e26-9c67-45c4-80e0-2ce212977c2a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_add_share_group_type_access(self):
+        self.do_request(
+            'add_access_to_share_group_type',
+            expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+
+    @decorators.idempotent_id('027314a9-6b14-4ae9-83f2-471e84ccaa01')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_share_group_type_access(self):
+        self.admin_shares_v2_client.add_access_to_share_group_type(
+            self.private_share_group_type['id'], self.client.project_id)
+        self.addCleanup(
+            self.admin_shares_v2_client.remove_access_from_share_group_type,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+        self.do_request(
+            'list_access_to_share_group_type',
+            expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.private_share_group_type['id'])
+
+    @decorators.idempotent_id('d8518122-dabd-4d2d-8b6a-4eed975e19ee')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_remove_share_group_type_access(self):
+        self.admin_shares_v2_client.add_access_to_share_group_type(
+            self.private_share_group_type['id'], self.client.project_id)
+        self.addCleanup(
+            self.admin_shares_v2_client.remove_access_from_share_group_type,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+        self.do_request(
+            'remove_access_from_share_group_type',
+            expected_status=lib_exc.Forbidden,
+            share_group_type_id=self.private_share_group_type['id'],
+            project_id=self.client.project_id)
+
+
+class ProjectReaderTests(ProjectMemberTests):
+
+    credentials = ['project_reader', 'project_member', 'project_admin']
+
+    @decorators.idempotent_id('8c47bbe9-f3f1-419e-b00b-97c9c942a48a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_group_type(self):
+        super(ProjectReaderTests, self).test_create_share_group_type()
+
+    @decorators.idempotent_id('fe3b28a3-6980-4782-8eaa-518bbd3913d1')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_group_type(self):
+        super(ProjectReaderTests, self).test_get_share_group_type()
+
+    @decorators.idempotent_id('47f92f0b-424e-4685-a742-8a4e00cc6901')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_group_types(self):
+        super(ProjectReaderTests, self).test_list_share_group_types()
+
+    @decorators.idempotent_id('e853fd60-8906-4e38-b0b4-ec5723696518')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_group_type(self):
+        super(ProjectReaderTests, self).test_delete_share_group_type()
+
+    @decorators.idempotent_id('caa6d960-4f34-4dff-9cc0-9a0cde44c2ae')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_group_type_extra_specs(self):
+        super(
+            ProjectReaderTests,
+            self).test_create_share_group_type_extra_specs()
+
+    @decorators.idempotent_id('2782c329-2447-49f7-95e7-0c4c766cfda3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_group_type_extra_spec(self):
+        super(
+            ProjectReaderTests, self).test_update_share_group_type_extra_spec()
+
+    @decorators.idempotent_id('003a0eee-0075-47b0-ba8a-8e57e958c1d3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_group_type_extra_spec(self):
+        super(
+            ProjectReaderTests, self).test_delete_share_group_type_extra_spec()
+
+    @decorators.idempotent_id('93bba264-104c-48af-af91-5a79ec3e695e')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_add_share_group_type_access(self):
+        super(ProjectReaderTests, self).test_add_share_group_type_access()
+
+    @decorators.idempotent_id('176b280c-7a46-43ae-8164-3bdd945d2dd4')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_list_share_group_type_access(self):
+        super(ProjectReaderTests, self).test_list_share_group_type_access()
+
+    @decorators.idempotent_id('00caa020-3805-4322-aac1-86d4552268a2')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_remove_share_group_type_access(self):
+        super(ProjectReaderTests, self).test_remove_share_group_type_access()
diff --git a/manila_tempest_tests/tests/rbac/test_share_groups.py b/manila_tempest_tests/tests/rbac/test_share_groups.py
new file mode 100644
index 0000000..b09a5e4
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_groups.py
@@ -0,0 +1,474 @@
+# 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.common.utils import data_utils
+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
+
+CONF = config.CONF
+
+
+class ShareRbacShareGroupsTests(rbac_base.ShareRbacBaseTests,
+                                metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacShareGroupsTests, 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(ShareRbacShareGroupsTests, 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(ShareRbacShareGroupsTests, cls).resource_setup()
+        cls.share_type = cls.create_share_type()
+        cls.share_group_type = cls.create_share_group_type(
+            cls.share_type['id'])
+
+    def share_group(self, share_group_type_id, share_type_ids):
+        share_group = {}
+        share_group['name'] = data_utils.rand_name('share_group')
+        share_group['share_group_type_id'] = share_group_type_id
+        share_group['share_type_ids'] = [share_type_ids]
+        return share_group
+
+    @abc.abstractmethod
+    def test_get_share_group(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share_groups(self):
+        pass
+
+    @abc.abstractmethod
+    def test_create_share_group(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_group(self):
+        pass
+
+    @abc.abstractmethod
+    def test_force_delete_share_group(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_group(self):
+        pass
+
+    @abc.abstractmethod
+    def test_reset_share_group(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacShareGroupsTests, 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()
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('0de993c5-8389-4997-8f7f-345e27f563f1')
+    def test_get_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'get_share_group', expected_status=200,
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'get_share_group', expected_status=200,
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('3b277a44-dcae-46da-a58c-f5281d8abc84')
+    def test_list_share_groups(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+
+        params = {"all_tenants": 1}
+        share_group_list = self.do_request(
+            'list_share_groups', expected_status=200,
+            params=params)['share_groups']
+        share_group_id_list = [
+            s['id'] for s in share_group_list
+        ]
+
+        self.assertIn(share_group['id'], share_group_id_list)
+        self.assertIn(alt_share_group['id'], share_group_id_list)
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('d060996e-c5f2-4dff-820b-6892a096a425')
+    def test_create_share_group(self):
+        share_group = self.do_request(
+            'create_share_group', expected_status=202,
+            **self.share_group(self.share_group_type['id'],
+                               self.share_type['id']))['share_group']
+        waiters.wait_for_resource_status(
+            self.client, share_group['id'], 'available',
+            resource_name='share_group')
+        self.addCleanup(self.client.wait_for_resource_deletion,
+                        share_group_id=share_group['id'])
+        self.addCleanup(self.client.delete_share_group, share_group['id'])
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('ea6cbb78-057e-4fbc-86bf-125b033cb76f')
+    def test_delete_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=202,
+            share_group_id=share_group['id'])
+        self.client.wait_for_resource_deletion(
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=202,
+            share_group_id=alt_share_group['id'])
+        self.client.wait_for_resource_deletion(
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('2cb00ffb-47e3-495e-853c-007752c9e679')
+    def test_force_delete_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_force_delete', expected_status=202,
+            share_group_id=share_group['id'])
+        self.client.wait_for_resource_deletion(
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_force_delete', expected_status=202,
+            share_group_id=alt_share_group['id'])
+        self.client.wait_for_resource_deletion(
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('1bab40d5-bdba-4a23-9300-807fe513bf15')
+    def test_update_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=200,
+            share_group_id=share_group['id'], name=name)
+
+        alt_share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=200,
+            share_group_id=alt_share_group['id'], name=name)
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('069bc68e-6411-44b8-abe9-399885f0eee5')
+    def test_reset_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_reset_state', expected_status=202,
+            share_group_id=share_group['id'], status='error')
+
+        alt_share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_reset_state', expected_status=202,
+            share_group_id=alt_share_group['id'], status='error')
+
+
+class TestProjectMemberTestsNFS(ShareRbacShareGroupsTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_admin', 'project_alt_member']
+    protocol = 'nfs'
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('a29e1a68-220e-40fc-98ea-9092fd256d07')
+    def test_get_share_group(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_group = self.create_share_group(
+            share_client, self.share_group_type['id'], [self.share_type['id']])
+        self.do_request(
+            'get_share_group', expected_status=200,
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'get_share_group', expected_status=lib_exc.NotFound,
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('d9c04932-c47e-46e0-bfcf-79c2af32c4c7')
+    def test_list_share_groups(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_group = self.create_share_group(
+            share_client, self.share_group_type['id'], [self.share_type['id']])
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+
+        params = {"all_tenants": 1}
+        share_group_list = self.do_request(
+            'list_share_groups', expected_status=200,
+            params=params)['share_groups']
+        share_group_id_list = [
+            s['id'] for s in share_group_list
+        ]
+
+        self.assertIn(share_group['id'], share_group_id_list)
+        self.assertNotIn(alt_share_group['id'], share_group_id_list)
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('ebad2242-1fb5-4d99-9a5a-281c1944e03d')
+    def test_create_share_group(self):
+        share_group = self.do_request(
+            'create_share_group', expected_status=202,
+            **self.share_group(self.share_group_type['id'],
+                               self.share_type['id']))['share_group']
+        waiters.wait_for_resource_status(
+            self.client, share_group['id'], 'available',
+            resource_name='share_group')
+        self.addCleanup(self.client.wait_for_resource_deletion,
+                        share_group_id=share_group['id'])
+        self.addCleanup(self.client.delete_share_group, share_group['id'])
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('f5c243e4-5128-4a1c-9a15-8c9f0a44437e')
+    def test_delete_share_group(self):
+        share_group = self.create_share_group(
+            self.client, self.share_group_type['id'], [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=202,
+            share_group_id=share_group['id'])
+        self.client.wait_for_resource_deletion(
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=lib_exc.NotFound,
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('36a58d50-1257-479f-80a2-f9b7a00814e2')
+    def test_force_delete_share_group(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_group = self.create_share_group(
+            share_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_force_delete', expected_status=lib_exc.Forbidden,
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_force_delete', expected_status=lib_exc.Forbidden,
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('cf9e34b6-6c04-4920-a811-2dbcf07ba14e')
+    def test_update_share_group(self):
+        share_group = self.create_share_group(
+            self.client, self.share_group_type['id'], [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=200,
+            share_group_id=share_group['id'], name=name)
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=lib_exc.NotFound,
+            share_group_id=alt_share_group['id'], name=name)
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('2108c4cd-74e0-467f-823a-e44cf8686afa')
+    def test_reset_share_group(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_group = self.create_share_group(
+            share_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_reset_state', expected_status=lib_exc.Forbidden,
+            share_group_id=share_group['id'], status='error')
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'share_group_reset_state', expected_status=lib_exc.Forbidden,
+            share_group_id=alt_share_group['id'], status='error')
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+    """Test suite for basic share group operations by reader user
+
+    In order to test certain share operations we must create a share group
+    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()
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('ec0ecbb0-5d45-4624-bb26-8b2e140e2ea9')
+    def test_get_share_group(self):
+        super(TestProjectReaderTestsNFS, self).test_get_share_group()
+
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('4ac87837-5bdf-4253-ab50-dd6efdcea285')
+    def test_list_share_groups(self):
+        super(TestProjectReaderTestsNFS, self).test_list_share_groups()
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('526dcd91-e789-48f8-b209-c384d77e5803')
+    def test_create_share_group(self):
+        self.do_request(
+            'create_share_group', expected_status=lib_exc.Forbidden,
+            **self.share_group(self.share_group_type['id'],
+                               self.share_type['id']))
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('fdf4d49e-a576-441f-9a3c-e2d58c0d8679')
+    def test_delete_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=lib_exc.Forbidden,
+            share_group_id=share_group['id'])
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        self.do_request(
+            'delete_share_group', expected_status=lib_exc.Forbidden,
+            share_group_id=alt_share_group['id'])
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('eddca093-e3a1-4a79-a8c7-8fd04c77b02f')
+    def test_force_delete_share_group(self):
+        super(TestProjectReaderTestsNFS, self).test_force_delete_share_group()
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('4530c19d-0aa5-402e-ac83-a3f2333f6c71')
+    def test_update_share_group(self):
+        share_group = self.create_share_group(
+            self.share_member_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=lib_exc.Forbidden,
+            share_group_id=share_group['id'], name=name)
+
+        alt_share_group = self.create_share_group(
+            self.alt_project_share_v2_client, self.share_group_type['id'],
+            [self.share_type['id']])
+        name = data_utils.rand_name('rename_share')
+        self.do_request(
+            'update_share_group', expected_status=lib_exc.Forbidden,
+            share_group_id=alt_share_group['id'], name=name)
+
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @decorators.idempotent_id('37f23531-69b5-418d-bd91-7913341586ec')
+    def test_reset_share_group(self):
+        super(TestProjectReaderTestsNFS, self).test_reset_share_group()
+
+
+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_instance_export_locations.py b/manila_tempest_tests/tests/rbac/test_share_instance_export_locations.py
new file mode 100644
index 0000000..4cc6fb4
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_instance_export_locations.py
@@ -0,0 +1,220 @@
+# Copyright 2023 NetApp, 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 ShareRbacInstanceExportLocationsTests(rbac_base.ShareRbacBaseTests,
+                                            metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacInstanceExportLocationsTests, 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(ShareRbacInstanceExportLocationsTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+        cls.admin_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(ShareRbacInstanceExportLocationsTests, cls).resource_setup()
+        share_type = cls.get_share_type()
+
+        # 'share_member_client' attribute is initialized in the 'setup_clients'
+        # of the reader class in order to use member credentials.
+        share_client = getattr(cls, 'share_member_client', cls.client)
+        share = cls.create_share(share_client, share_type['id'])
+
+        alt_share = cls.create_share(
+            cls.alt_project_share_v2_client, share_type['id'])
+
+        cls.share_instances = cls.admin_client.get_instances_of_share(
+            share['id'])['share_instances']
+        cls.alt_share_instances = cls.admin_client.get_instances_of_share(
+            alt_share['id'])['share_instances']
+
+    @abc.abstractmethod
+    def test_share_instance_list_export_locations(self):
+        pass
+
+    @abc.abstractmethod
+    def test_share_instance_show_export_location(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacInstanceExportLocationsTests,
+                               base.BaseSharesTest):
+
+    credentials = ['project_admin', 'project_alt_member']
+    protocol = 'nfs'
+
+    @decorators.idempotent_id('f3218212-d70b-4a3d-bc05-8905a4f14279')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_list_export_locations(self):
+        locations = self.do_request(
+            'list_share_instance_export_locations', expected_status=200,
+            instance_id=self.share_instances[0]['id'])
+        self.assertNotEmpty(locations)
+
+        alt_locations = self.do_request(
+            'list_share_instance_export_locations', expected_status=200,
+            instance_id=self.alt_share_instances[0]['id'])
+        self.assertNotEmpty(alt_locations)
+
+    @decorators.idempotent_id('c58c74cf-4fcd-4404-a2f9-1a9e6b4443c4')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_show_export_location(self):
+        export_location = (
+            self.client.list_share_instance_export_locations(
+                self.share_instances[0]['id'])['export_locations'])
+        self.do_request(
+            'get_share_instance_export_location', expected_status=200,
+            instance_id=self.share_instances[0]['id'],
+            export_location_uuid=export_location[0]['id'])
+
+        alt_export_location = (
+            self.client.list_share_instance_export_locations(
+                self.alt_share_instances[0]['id'])['export_locations'])
+        self.do_request(
+            'get_share_instance_export_location', expected_status=200,
+            instance_id=self.alt_share_instances[0]['id'],
+            export_location_uuid=alt_export_location[0]['id'])
+
+
+class TestProjectMemberTestsNFS(ShareRbacInstanceExportLocationsTests,
+                                base.BaseSharesTest):
+    """Test suite for share instance export location operations by member
+
+    In order to test certain share operations we must create a share
+    resource for this. Since project member user is limited in intances
+    operations, we are forced to use admin credentials to get to instances,
+    so we can test other operations.
+    """
+
+    credentials = ['project_member', 'project_admin', 'project_alt_member']
+    protocol = 'nfs'
+
+    @decorators.idempotent_id('27d495dd-b52d-417d-bfbf-9bb700e85f4d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_list_export_locations(self):
+        self.do_request(
+            'list_share_instance_export_locations',
+            expected_status=lib_exc.Forbidden,
+            instance_id=self.share_instances[0]['id'])
+
+        self.do_request(
+            'list_share_instance_export_locations',
+            expected_status=lib_exc.Forbidden,
+            instance_id=self.alt_share_instances[0]['id'])
+
+    @decorators.idempotent_id('8de74960-b9cf-4ee6-81dc-fbb5dbb291dd')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_show_export_location(self):
+        export_location = (
+            self.admin_client.list_share_instance_export_locations(
+                self.share_instances[0]['id'])['export_locations'])
+        self.do_request(
+            'get_share_instance_export_location',
+            expected_status=lib_exc.Forbidden,
+            instance_id=self.share_instances[0]['id'],
+            export_location_uuid=export_location[0]['id'])
+
+        alt_export_location = (
+            self.admin_client.list_share_instance_export_locations(
+                self.alt_share_instances[0]['id'])['export_locations'])
+        self.do_request(
+            'get_share_instance_export_location',
+            expected_status=lib_exc.Forbidden,
+            instance_id=self.alt_share_instances[0]['id'],
+            export_location_uuid=alt_export_location[0]['id'])
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+    """Test suite for share instance export location 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 member credentials, so we can test other share
+    operations. In this class we use member user to create a share and admin
+    to list its instances. That way we can perform a reader actions on
+    this resource.
+    """
+
+    credentials = ['project_reader', 'project_member', 'project_admin',
+                   'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(TestProjectReaderTestsNFS, cls).setup_clients()
+        # Initialize a member user in the same project of reader user
+        # for creating a share resource.
+        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('9db505c1-45d3-4d82-8879-38c4861e4fb3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_list_export_locations(self):
+        (super(TestProjectReaderTestsNFS, self)
+            .test_share_instance_list_export_locations())
+
+    @decorators.idempotent_id('09009203-ff20-4914-8764-7865839e29b2')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_share_instance_show_export_location(self):
+        (super(TestProjectReaderTestsNFS, self)
+            .test_share_instance_show_export_location())
+
+
+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/manila_tempest_tests/tests/rbac/test_share_network.py b/manila_tempest_tests/tests/rbac/test_share_network.py
new file mode 100644
index 0000000..3665b6b
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_network.py
@@ -0,0 +1,285 @@
+# 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.common.utils import data_utils
+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 ShareRbacShareNetworkTests(rbac_base.ShareRbacBaseTests,
+                                 metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacShareNetworkTests, 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(ShareRbacShareNetworkTests, cls).resource_setup()
+        cls.share_type = cls.get_share_type()
+
+    @abc.abstractmethod
+    def test_create_share_network(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share_network(self):
+        pass
+
+    @abc.abstractmethod
+    def test_show_share_network(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_network(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_network(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacShareNetworkTests, base.BaseSharesTest):
+
+    credentials = ['project_admin', 'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, 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('358dd850-cd81-4b81-aefa-3dfcb7aa4551')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_network(self):
+        share_network = self.do_request(
+            'create_share_network', expected_status=200)['share_network']
+        self.addCleanup(
+            self.delete_resource, self.client, sn_id=share_network['id'])
+
+    @decorators.idempotent_id('deb20301-9d7c-4c08-b1f0-fc2c403ea708')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        params = {"all_tenants": 1}
+        share_network_list = self.do_request(
+            'list_share_networks', expected_status=200,
+            params=params)['share_networks']
+        share_network_id_list = [
+            s['id'] for s in share_network_list
+        ]
+
+        self.assertIn(share_network['id'], share_network_id_list)
+        self.assertIn(alt_share_network['id'], share_network_id_list)
+
+    @decorators.idempotent_id('43a3be84-d08b-4f17-89cf-02abda6df580')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        self.do_request(
+            'get_share_network', expected_status=200,
+            share_network_id=share_network['id'])
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'get_share_network', expected_status=200,
+            share_network_id=alt_share_network['id'])
+
+    @decorators.idempotent_id('6c403ed6-b810-4794-8e9b-d57f173443a2')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        self.do_request(
+            'delete_share_network', expected_status=202,
+            sn_id=share_network['id'])
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'delete_share_network', expected_status=202,
+            sn_id=alt_share_network['id'])
+
+    @decorators.idempotent_id('abd2443d-3490-462a-8e51-73b6a8f48795')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_update_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        name = data_utils.rand_name("updated_share_network")
+        self.do_request(
+            'update_share_network', expected_status=200,
+            sn_id=share_network['id'], name=name)
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'update_share_network', expected_status=200,
+            sn_id=alt_share_network['id'], name=name)
+
+
+class ProjectMemberTests(ShareRbacShareNetworkTests, base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_alt_member']
+
+    @decorators.idempotent_id('d051c749-3d1c-4485-86c5-6eb860b49cad')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_network(self):
+        share_network = self.do_request(
+            'create_share_network', expected_status=200)['share_network']
+        self.addCleanup(
+            self.delete_resource, self.client, sn_id=share_network['id'])
+
+    @decorators.idempotent_id('ac33cd51-1efe-4aaf-99ab-b510b7551571')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_network(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_network = self.create_share_network(share_client)
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        share_network_list = self.do_request(
+            'list_share_networks', expected_status=200)['share_networks']
+        share_network_id_list = [
+            s['id'] for s in share_network_list
+        ]
+
+        self.assertIn(share_network['id'], share_network_id_list)
+        self.assertNotIn(alt_share_network['id'], share_network_id_list)
+
+    @decorators.idempotent_id('dc3f8f95-f8c5-4030-93dd-e4c56e40b477')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_show_share_network(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share_network = self.create_share_network(share_client)
+        self.do_request(
+            'get_share_network', expected_status=200,
+            share_network_id=share_network['id'])
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'get_share_network', expected_status=lib_exc.NotFound,
+            share_network_id=alt_share_network['id'])
+
+    @decorators.idempotent_id('717977ab-f077-411a-9bdc-06c8ec9d4f8c')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_network(self):
+        share_network = self.create_share_network(self.client)
+        self.do_request(
+            'delete_share_network', expected_status=202,
+            sn_id=share_network['id'])
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'delete_share_network', expected_status=lib_exc.NotFound,
+            sn_id=alt_share_network['id'])
+
+    @decorators.idempotent_id('d1fce94c-b163-452d-bf79-13b6edf47e30')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_network(self):
+        share_network = self.create_share_network(self.client)
+        name = data_utils.rand_name("updated_share_network")
+        self.do_request(
+            'update_share_network', expected_status=200,
+            sn_id=share_network['id'], name=name)
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'update_share_network', expected_status=lib_exc.NotFound,
+            sn_id=alt_share_network['id'], name=name)
+
+
+class ProjectReaderTests(ProjectMemberTests):
+    """Test suite for basic share network operations by reader user
+
+    In order to test certain share operations we must create a share network
+    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(ProjectReaderTests, 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()
+        cls.alt_project_share_v2_client = (
+            cls.os_project_alt_member.share_v2.SharesV2Client())
+
+    @decorators.idempotent_id('73dd9f09-7106-4fd5-a484-0eb986002e3b')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_network(self):
+        self.do_request(
+            'create_share_network', expected_status=lib_exc.Forbidden)
+
+    @decorators.idempotent_id('841e9e69-2a22-4572-9147-b233c8a842bc')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_network(self):
+        super(ProjectReaderTests, self).test_list_share_network()
+
+    @decorators.idempotent_id('c98893c8-cdc6-42af-a842-1ee9466904ae')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_show_share_network(self):
+        super(ProjectReaderTests, self).test_show_share_network()
+
+    @decorators.idempotent_id('f8f26bce-ff82-4472-a8dd-0f46c1757386')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        self.do_request(
+            'delete_share_network', expected_status=lib_exc.Forbidden,
+            sn_id=share_network['id'])
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'delete_share_network', expected_status=lib_exc.Forbidden,
+            sn_id=alt_share_network['id'])
+
+    @decorators.idempotent_id('67b745cd-e669-4872-bbb7-9307960fbd77')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_network(self):
+        share_network = self.create_share_network(self.share_member_client)
+        name = data_utils.rand_name("updated_share_network")
+        self.do_request(
+            'update_share_network', expected_status=lib_exc.Forbidden,
+            sn_id=share_network['id'], name=name)
+
+        alt_share_network = self.create_share_network(
+            self.alt_project_share_v2_client)
+        self.do_request(
+            'update_share_network', expected_status=lib_exc.Forbidden,
+            sn_id=alt_share_network['id'], name=name)
diff --git a/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py b/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py
new file mode 100644
index 0000000..0fae6f0
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py
@@ -0,0 +1,170 @@
+# 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 ShareRbacExtraSpecsTests(rbac_base.ShareRbacBaseTests,
+                               metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacExtraSpecsTests, 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())
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareRbacExtraSpecsTests, cls).resource_setup()
+        cls.extra_specs = {u'key': u'value'}
+        cls.share_type = cls.create_share_type()
+
+    @abc.abstractmethod
+    def test_create_share_type_extra_specs(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_share_type_extra_specs(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_type_extra_spec(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_type_extra_spec(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacExtraSpecsTests, base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, 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('d51817f4-b186-4eca-8779-f3c36dcd98e7')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        self.do_request(
+            'create_share_type_extra_specs', expected_status=200,
+            share_type_id=self.share_type['id'], extra_specs=self.extra_specs)
+        self.addCleanup(
+            self.admin_shares_v2_client.delete_share_type_extra_spec,
+            self.share_type['id'], extra_spec_name='key')
+
+    @decorators.idempotent_id('d4deeb0b-8765-4487-9f1f-9f10088934dd')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        self.do_request(
+            'get_share_type_extra_specs', expected_status=200,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('bb27641b-5249-4343-bb08-5a123f31b9f1')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        self.do_request(
+            'update_share_type_extra_spec', expected_status=200,
+            share_type_id=self.share_type['id'], spec_name='key',
+            spec_value='value_updated')
+
+    @decorators.idempotent_id('81d59322-8ec1-4f32-a50d-2fedd1cca655')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_type_extra_specs(
+            self.share_type['id'], self.extra_specs)
+        self.do_request(
+            'delete_share_type_extra_spec', expected_status=202,
+            share_type_id=self.share_type['id'], extra_spec_name='key')
+
+
+class ProjectMemberTests(ShareRbacExtraSpecsTests, base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_admin']
+
+    @decorators.idempotent_id('446c1e7c-5ca2-46f5-b2f3-6417152e5bf8')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        self.do_request(
+            'create_share_type_extra_specs', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], extra_specs=self.extra_specs)
+
+    @decorators.idempotent_id('aabdf0c1-8b68-4c40-a542-cc1dbd039279')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        self.do_request(
+            'get_share_type_extra_specs', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('3629f91c-ad21-4321-acd9-7fca92a4721a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        self.do_request(
+            'update_share_type_extra_spec', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], spec_name='key',
+            spec_value='value_updated')
+
+    @decorators.idempotent_id('0bee97ab-b406-481c-9b8b-4813fb9f49dc')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_type_extra_specs(
+            self.share_type['id'], self.extra_specs)
+        self.do_request(
+            'delete_share_type_extra_spec', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], extra_spec_name='key')
+        self.addCleanup(
+            self.admin_shares_v2_client.delete_share_type_extra_spec,
+            self.share_type['id'], extra_spec_name='key')
+
+
+class ProjectReaderTests(ProjectMemberTests):
+
+    credentials = ['project_reader', 'project_admin']
+
+    @decorators.idempotent_id('da80b823-9a96-45c3-8f86-e9f7fc5ad2c6')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        super(ProjectReaderTests, self).test_create_share_type_extra_specs()
+
+    @decorators.idempotent_id('78989220-22dc-46d2-b83b-63f070988eed')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        super(ProjectReaderTests, self).test_get_share_type_extra_specs()
+
+    @decorators.idempotent_id('c77173d4-b90c-4edf-a9b6-a26c81aaec42')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        super(ProjectReaderTests, self).test_update_share_type_extra_spec()
+
+    @decorators.idempotent_id('46fc8e62-b987-444f-ab9f-cd86a8960156')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        super(ProjectReaderTests, self).test_delete_share_type_extra_spec()
diff --git a/manila_tempest_tests/tests/rbac/test_share_types.py b/manila_tempest_tests/tests/rbac/test_share_types.py
new file mode 100644
index 0000000..e4e6016
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_types.py
@@ -0,0 +1,190 @@
+# 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.common.utils import data_utils
+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 ShareRbacShareTypesTests(rbac_base.ShareRbacBaseTests,
+                               metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacShareTypesTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareRbacShareTypesTests, cls).resource_setup()
+        cls.share_type = cls.get_share_type()
+
+    def share_type_properties(self):
+        share_type = {}
+        share_type['extra_specs'] = {
+            'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+        }
+        share_type['name'] = data_utils.rand_name("share-type")
+        return share_type
+
+    @abc.abstractmethod
+    def test_create_share_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_share_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share_type(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_type(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacShareTypesTests, base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, 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('b24bf137-352a-4ebd-b736-27518d32c1bd')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_type(self):
+        share_type = self.do_request(
+            'create_share_type', expected_status=200,
+            **self.share_type_properties())['share_type']
+        self.addCleanup(self.delete_resource, self.client,
+                        st_id=share_type['id'])
+
+    @decorators.idempotent_id('741d69f3-b3fe-49cf-9e33-6b0696b353ec')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_type(self):
+        self.do_request(
+            'get_share_type', expected_status=200,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('3f811ac6-a345-424f-863a-1a7a49ba0a32')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_type(self):
+        share_type_list = self.do_request(
+            'list_share_types', expected_status=200)['share_types']
+        share_type_id_list = [
+            st['id'] for st in share_type_list
+        ]
+        self.assertIn(self.share_type['id'], share_type_id_list)
+
+    @decorators.idempotent_id('3bb9aaab-3c17-45be-a9b1-dd8b6942cb59')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_update_share_type(self):
+        share_type = self.client.create_share_type(
+            **self.share_type_properties())['share_type']
+        self.addCleanup(self.client.delete_share_type, share_type['id'])
+
+        name = data_utils.rand_name("updated_share_type")
+        self.do_request(
+            'update_share_type', expected_status=200,
+            share_type_id=share_type['id'], name=name)
+
+
+class ProjectMemberTests(ShareRbacShareTypesTests, base.BaseSharesTest):
+
+    credentials = ['project_member']
+
+    @decorators.idempotent_id('270761cf-07b4-4fc7-96b5-4deb205adce3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type(self):
+        self.do_request(
+            'create_share_type', expected_status=lib_exc.Forbidden,
+            **self.share_type_properties())
+
+    @decorators.idempotent_id('d3f53218-d92f-489d-8e2e-985178e7fd02')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_type(self):
+        self.do_request(
+            'get_share_type', expected_status=200,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('757c7ccd-e14e-4c1a-9172-998ae5eed1b8')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_type(self):
+        share_type_list = self.do_request(
+            'list_share_types', expected_status=200)['share_types']
+        share_type_id_list = [
+            st['id'] for st in share_type_list
+        ]
+        self.assertIn(self.share_type['id'], share_type_id_list)
+
+    @decorators.idempotent_id('5210170c-b749-4645-a86f-7347c3ba3e99')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type(self):
+        name = data_utils.rand_name("updated_share_type")
+        self.do_request(
+            'update_share_type', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], name=name)
+
+
+class ProjectReaderTests(ShareRbacShareTypesTests, base.BaseSharesTest):
+
+    credentials = ['project_reader']
+
+    @decorators.idempotent_id('f4c352c4-c12b-4722-9fe7-9a2ec639ee63')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type(self):
+        self.do_request(
+            'create_share_type', expected_status=lib_exc.Forbidden,
+            **self.share_type_properties())
+
+    @decorators.idempotent_id('e9d9f244-7778-443b-aadc-bac9f2b687b7')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_type(self):
+        self.do_request(
+            'get_share_type', expected_status=200,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('cf0e97f1-4853-4cf2-9e9a-041c6e57bab5')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_share_type(self):
+        share_type_list = self.do_request(
+            'list_share_types', expected_status=200)['share_types']
+        share_type_id_list = [
+            st['id'] for st in share_type_list
+        ]
+        self.assertIn(self.share_type['id'], share_type_id_list)
+
+    @decorators.idempotent_id('338d579b-ff91-4a30-af53-d0b317919efb')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type(self):
+        name = data_utils.rand_name("updated_share_type")
+        self.do_request(
+            'update_share_type', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], name=name)
diff --git a/manila_tempest_tests/tests/rbac/test_shares.py b/manila_tempest_tests/tests/rbac/test_shares.py
new file mode 100644
index 0000000..2ca3c92
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_shares.py
@@ -0,0 +1,677 @@
+# 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.common.utils import data_utils
+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
+
+CONF = config.CONF
+
+
+class ShareRbacSharesTests(rbac_base.ShareRbacBaseTests,
+                           metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacSharesTests, 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(ShareRbacSharesTests, 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(ShareRbacSharesTests, cls).resource_setup()
+        cls.share_type = cls.get_share_type()
+
+    def share(self, share_type_id, size=None):
+        share = {}
+        share['name'] = data_utils.rand_name('share')
+        share['size'] = size or CONF.share.share_size
+        share['share_type_id'] = share_type_id
+        share['share_protocol'] = self.protocol
+        return share
+
+    @abc.abstractmethod
+    def test_get_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_create_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_force_delete_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_reset_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_shrink_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_extend_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_set_share_metadata(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_share_metadata(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_metadata(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacSharesTests, 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('14a52454-cba0-4973-926a-28e924ae2e63')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'get_share', expected_status=200, share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'get_share', expected_status=200,
+            share_id=alt_share['id'])
+
+    @decorators.idempotent_id('5f8c06e6-5b80-45f8-aefb-1b55617d1bd1')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+
+        params = {"all_tenants": 1}
+        share_list = self.do_request(
+            'list_shares', expected_status=200, params=params)['shares']
+        share_id_list = [
+            s['id'] for s in share_list
+        ]
+
+        self.assertIn(share['id'], share_id_list)
+        self.assertIn(alt_share['id'], share_id_list)
+
+    @decorators.idempotent_id('34b84af3-a9ea-4c19-8414-e4e44648099c')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_share(self):
+        share = self.do_request(
+            'create_share', expected_status=200,
+            **self.share(self.share_type['id']))['share']
+        waiters.wait_for_resource_status(self.client,
+                                         share['id'], 'available')
+        self.addCleanup(self.delete_resource, self.client,
+                        share_id=share['id'])
+
+    @decorators.idempotent_id('44f2eae6-44d4-4962-a94a-d2717b74728f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'delete_share', expected_status=202, share_id=share['id'])
+        self.client.wait_for_resource_deletion(share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'delete_share', expected_status=202,
+            share_id=alt_share['id'])
+        self.client.wait_for_resource_deletion(share_id=alt_share['id'])
+
+    @decorators.idempotent_id('2e915a27-488d-4e33-b2f8-37758ef11653')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'force_delete', expected_status=202, s_id=share['id'])
+        self.client.wait_for_resource_deletion(share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'force_delete', expected_status=202,
+            s_id=alt_share['id'])
+        self.client.wait_for_resource_deletion(share_id=alt_share['id'])
+
+    @decorators.idempotent_id('5c2bda4c-0179-4af9-b18c-430a7d31f962')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_update_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        name = data_utils.rand_name("updated_share")
+        self.do_request(
+            'update_share', expected_status=200,
+            share_id=share['id'], name=name)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        name = data_utils.rand_name("updated_share")
+        self.do_request(
+            'update_share', expected_status=200,
+            share_id=alt_share['id'], name=name)
+
+    @decorators.idempotent_id('44fb7049-8fc0-4584-9ff1-7527395d2ec5')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'reset_state', expected_status=202, s_id=share['id'],
+            status="error")
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'reset_state', expected_status=202,
+            s_id=alt_share['id'], status="error")
+
+    @decorators.idempotent_id('cc49ae58-6696-4030-a029-a66bae2efa96')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_shrink_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'],
+            size=CONF.share.share_size + 1)
+        self.do_request(
+            'shrink_share', expected_status=202, share_id=share['id'],
+            new_size=CONF.share.share_size)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            size=CONF.share.share_size + 1)
+        self.do_request(
+            'shrink_share', expected_status=202,
+            share_id=alt_share['id'], new_size=CONF.share.share_size)
+        waiters.wait_for_resource_status(
+            self.alt_project_share_v2_client, alt_share['id'], 'available')
+
+    @decorators.idempotent_id('2cfa04e5-16cc-43e4-b892-c1a11b0a2f2d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_extend_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=202, share_id=share['id'],
+            new_size=CONF.share.share_size + 1)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=202,
+            share_id=alt_share['id'], new_size=CONF.share.share_size + 1)
+        waiters.wait_for_resource_status(
+            self.alt_project_share_v2_client, alt_share['id'], 'available')
+
+    @decorators.idempotent_id('d6014579-d772-441a-a9b1-01b1e87caeaa')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_share_metadata(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=200, resource_id=share['id'],
+            metadata={'key': 'value'})
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=200,
+            resource_id=alt_share['id'], metadata={'key': 'value'})
+
+    @decorators.idempotent_id('2d91e97e-d0e5-4112-8b22-60cd4659586c')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share_metadata(self):
+        metadata = {'key': 'value'}
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata', expected_status=200, resource_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata', expected_status=200,
+            resource_id=alt_share['id'])
+
+    @decorators.idempotent_id('4cd807d6-bac4-4d0f-a207-c84dfe77f032')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share_metadata(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'],
+            metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=200, resource_id=share['id'],
+            key='key')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=200,
+            resource_id=alt_share['id'], key='key')
+
+
+class TestProjectMemberTestsNFS(ShareRbacSharesTests, base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_alt_member']
+    protocol = 'nfs'
+
+    @decorators.idempotent_id('75b9fd40-ae63-4caf-9c93-0fe24b2ce904')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        self.do_request(
+            'get_share', expected_status=200, share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'get_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'])
+
+    @decorators.idempotent_id('92fd157a-f357-4a08-9fc6-9e77a55b89a8')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+
+        # We expect this key to be ignored since project_member isn't an admin
+        params = {"all_tenants": 1}
+        share_list = self.do_request(
+            'list_shares', expected_status=200, params=params)['shares']
+        share_id_list = [
+            s['id'] for s in share_list
+        ]
+
+        self.assertIn(share['id'], share_id_list)
+        self.assertNotIn(alt_share['id'], share_id_list)
+
+    @decorators.idempotent_id('7a6eef6b-bf8e-4cb3-a39c-6dc7fbe115ab')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_share(self):
+        share = self.do_request(
+            'create_share', expected_status=200,
+            **self.share(self.share_type['id']))['share']
+        waiters.wait_for_resource_status(self.client,
+                                         share['id'], 'available')
+        self.addCleanup(self.delete_resource, self.client,
+                        share_id=share['id'])
+
+    @decorators.idempotent_id('6c546ed7-ebfd-4ac5-a626-d333a25a9e66')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share(self):
+        share = self.create_share(self.client, self.share_type['id'])
+        self.do_request(
+            'delete_share', expected_status=202, share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'delete_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'])
+
+    @decorators.idempotent_id('2349d2b0-6314-4018-85e5-696f8d1ca94a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        self.do_request(
+            'force_delete', expected_status=lib_exc.Forbidden,
+            s_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'force_delete', expected_status=lib_exc.Forbidden,
+            s_id=alt_share['id'])
+
+    @decorators.idempotent_id('20d6360d-5cea-4305-be36-7e1429007598')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_update_share(self):
+        share = self.create_share(self.client, self.share_type['id'])
+        name = data_utils.rand_name("rename_share")
+        self.do_request(
+            'update_share', expected_status=200, share_id=share['id'],
+            name=name)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        alt_name = data_utils.rand_name("rename_share")
+        self.do_request(
+            'update_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'], name=alt_name)
+
+    @decorators.idempotent_id('483cbaef-a53d-433a-9259-f2ecc209f405')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        self.do_request(
+            'reset_state', expected_status=lib_exc.Forbidden,
+            s_id=share['id'], status="error")
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'reset_state', expected_status=lib_exc.NotFound,
+            s_id=alt_share['id'], status="error")
+
+    @decorators.idempotent_id('56a07567-d0a9-460a-9267-fcd82306a371')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_shrink_share(self):
+        share = self.create_share(self.client, self.share_type['id'], size=2)
+        self.do_request(
+            'shrink_share', expected_status=202,
+            share_id=share['id'], new_size=CONF.share.share_size)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'], size=2)
+        self.do_request(
+            'shrink_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'], new_size=CONF.share.share_size)
+
+    @decorators.idempotent_id('c09e6a72-5b99-4be6-8ffe-8ecaad0be990')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_extend_share(self):
+        share = self.create_share(self.client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=202,
+            share_id=share['id'], new_size=CONF.share.share_size + 1)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'], new_size=CONF.share.share_size + 1)
+
+    @decorators.idempotent_id('f1c03630-987c-4f19-938d-4a0ef6529177')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_share_metadata(self):
+        share = self.create_share(
+            self.client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=200, resource_id=share['id'],
+            metadata={'key': 'value'})
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_share['id'], metadata={'key': 'value'})
+
+    @decorators.idempotent_id('a69a2b85-3374-4621-83a9-89937ddb520b')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share_metadata(self):
+        metadata = {'key': 'value'}
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'],
+                                  metadata=metadata)
+        self.do_request(
+            'get_metadata', expected_status=200, resource_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_share['id'])
+
+    @decorators.idempotent_id('bea5518a-338e-494d-9034-1d03658ed58b')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share_metadata(self):
+        share = self.create_share(
+            self.client, self.share_type['id'], metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=200, resource_id=share['id'],
+            key='key')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_share['id'], key='key')
+
+
+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('dc439eaf-c885-4002-be8f-4c488beeca81')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share(self):
+        super(TestProjectReaderTestsNFS, self).test_get_share()
+
+    @decorators.idempotent_id('1fbb1078-4386-4b52-aa88-e6be4a286791')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_share(self):
+        super(TestProjectReaderTestsNFS, self).test_list_share()
+
+    @decorators.idempotent_id('350ba4c9-def9-4865-824a-de1ddff5dcf9')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_share(self):
+        self.do_request(
+            'create_share', expected_status=lib_exc.Forbidden,
+            **self.share(self.share_type['id']))
+
+    @decorators.idempotent_id('eb92b142-fd8d-47e3-99fe-944cce747ad7')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'delete_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(
+            'delete_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'])
+
+    @decorators.idempotent_id('cb040955-5897-409f-aea0-84b6ae16b77e')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_share(self):
+        super(TestProjectReaderTestsNFS, self).test_force_delete_share()
+
+    @decorators.idempotent_id('3184269a-11ca-4484-8a4d-b855a6e1800f')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_update_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        name = data_utils.rand_name("rename_share")
+        self.do_request(
+            'update_share', expected_status=lib_exc.Forbidden,
+            share_id=share['id'], name=name)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        alt_name = data_utils.rand_name("rename_share")
+        self.do_request(
+            'update_share', expected_status=lib_exc.Forbidden,
+            share_id=alt_share['id'], name=alt_name)
+
+    @decorators.idempotent_id('e5ae5b56-38c0-44ec-b8e0-4bc2a5c1d28a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_share(self):
+        super(TestProjectReaderTestsNFS, self).test_reset_share()
+
+    @decorators.idempotent_id('f85818b1-b93a-4b89-8aa4-b099e582be7c')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_shrink_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'],
+            size=CONF.share.share_size + 1)
+        self.do_request(
+            'shrink_share', expected_status=lib_exc.Forbidden,
+            share_id=share['id'], new_size=CONF.share.share_size)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            size=CONF.share.share_size + 1)
+        self.do_request(
+            'shrink_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'], new_size=CONF.share.share_size)
+
+    @decorators.idempotent_id('0b57aedb-6b68-498f-814e-173c47e6c307')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_extend_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=lib_exc.Forbidden,
+            share_id=share['id'], new_size=CONF.share.share_size + 1)
+        waiters.wait_for_resource_status(self.client, share['id'], 'available')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'extend_share', expected_status=lib_exc.NotFound,
+            share_id=alt_share['id'], new_size=CONF.share.share_size + 1)
+
+    @decorators.idempotent_id('3def3f4e-33fc-4726-8818-6cffbc2cab51')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_set_share_metadata(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=share['id'], metadata={'key': 'value'})
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_share['id'], metadata={'key': 'value'})
+
+    @decorators.idempotent_id('28cacc77-556f-4707-ba2b-5ef3e56d6ef9')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_share_metadata(self):
+        super(TestProjectReaderTestsNFS, self).test_get_share_metadata()
+
+    @decorators.idempotent_id('55486589-a4ef-44f2-b489-96bc29dcd243')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_share_metadata(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'],
+            metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=share['id'], key='key')
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'],
+            metadata={'key': 'value'})
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_share['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_snapshots.py b/manila_tempest_tests/tests/rbac/test_snapshots.py
new file mode 100644
index 0000000..810ba9b
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_snapshots.py
@@ -0,0 +1,591 @@
+# 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.common.utils import data_utils
+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 ShareRbacSnapshotsTests(rbac_base.ShareRbacBaseTests,
+                              metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacSnapshotsTests, 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(ShareRbacSnapshotsTests, 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())
+
+    @abc.abstractmethod
+    def test_get_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_list_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_create_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_force_delete_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_rename_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_reset_snapshot(self):
+        pass
+
+    @abc.abstractmethod
+    def test_set_snapshot_metadata(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_snapshot_metadata(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_snapshot_metadata(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacSnapshotsTests, 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('e55b1a01-0fcb-42aa-8cc4-b041fc75f1e4')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_snapshot(self):
+        snapshot = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        self.do_request(
+            'get_snapshot', expected_status=200, snapshot_id=snapshot['id'])
+
+        alt_snapshot = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'get_snapshot', expected_status=200,
+            snapshot_id=alt_snapshot['id'])
+
+    @decorators.idempotent_id('3b209017-f5ad-4daa-8932-582a75975bbe')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_snapshot(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+
+        params = {"all_tenants": 1}
+        snapshot_list = self.do_request(
+            'list_snapshots', expected_status=200, params=params)['snapshots']
+        snapshot_id_list = [
+            s['id'] for s in snapshot_list
+        ]
+
+        self.assertIn(snap['id'], snapshot_id_list)
+        self.assertIn(alt_snap['id'], snapshot_id_list)
+
+    @decorators.idempotent_id('2b90d3e9-ec71-468a-86e9-e8955139ad48')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_snapshot(self):
+        snapshot = self.do_request(
+            'create_snapshot', expected_status=202,
+            share_id=self.share['id'])['snapshot']
+        waiters.wait_for_resource_status(
+            self.client, snapshot['id'], 'available', resource_name='snapshot')
+        self.addCleanup(self.delete_resource, self.client,
+                        snapshot_id=snapshot['id'])
+
+    @decorators.idempotent_id('6de91ee0-d27e-409a-957b-75489d4e7291')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_snapshot(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=202, snap_id=snap['id'])
+        self.client.wait_for_resource_deletion(snapshot_id=snap['id'])
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=202,
+            snap_id=alt_snap['id'])
+        self.client.wait_for_resource_deletion(snapshot_id=alt_snap['id'])
+
+    @decorators.idempotent_id('3ac10dfb-3445-4052-855a-a17056d16a9c')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_snapshot(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        self.do_request(
+            'force_delete', expected_status=202, s_id=snap['id'],
+            s_type='snapshots')
+        self.client.wait_for_resource_deletion(snapshot_id=snap['id'])
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'force_delete', expected_status=202,
+            s_id=alt_snap['id'], s_type='snapshots')
+        self.client.wait_for_resource_deletion(snapshot_id=alt_snap['id'])
+
+    @decorators.idempotent_id('513c8fef-9597-4e6c-a811-fb89b456d457')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_rename_snapshot(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        name = data_utils.rand_name("updated_snapshot")
+        self.do_request(
+            'rename_snapshot', expected_status=200, snapshot_id=snap['id'],
+            name=name)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'rename_snapshot', expected_status=200,
+            snapshot_id=alt_snap['id'], name=name)
+
+    @decorators.idempotent_id('a5e99bfb-8767-4680-9e39-bde767e4b8f8')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_snapshot(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        self.do_request(
+            'snapshot_reset_state', expected_status=202,
+            snapshot_id=snap['id'], status='error')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'snapshot_reset_state', expected_status=202,
+            snapshot_id=alt_snap['id'], status='error')
+
+    @decorators.idempotent_id('8c0858d5-5670-4c21-ab1f-7d74a7f8cb6d')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_set_snapshot_metadata(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        metadata = {u'key': u'value'}
+        self.do_request(
+            'set_metadata', expected_status=200,
+            resource_id=snap['id'], resource='snapshot', metadata=metadata)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'set_metadata', expected_status=200,
+            resource_id=alt_snap['id'], resource='snapshot', metadata=metadata)
+
+    @decorators.idempotent_id('235b3fe2-55bf-4a43-b703-ca413ce76a41')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_get_snapshot_metadata(self):
+        metadata = {u'key': u'value'}
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata_item', expected_status=200,
+            resource_id=snap['id'], key='key', resource='snapshot')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata_item', expected_status=200,
+            resource_id=alt_snap['id'], key='key', resource='snapshot')
+
+    @decorators.idempotent_id('7490eb85-fcdc-45ae-89ba-14cf34c58b3b')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_delete_snapshot_metadata(self):
+        metadata = {u'key': u'value'}
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'], metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=200, resource_id=snap['id'],
+            resource='snapshot', key='key')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=200, resource_id=alt_snap['id'],
+            resource='snapshot', key='key')
+
+
+class TestProjectMemberTestsNFS(ShareRbacSnapshotsTests, 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('4ba65029-5c8b-4e96-940a-094d9f662cf6')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_snapshot(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        snapshot = self.create_snapshot(share_client, self.share['id'])
+        self.do_request(
+            'get_snapshot', expected_status=200, snapshot_id=snapshot['id'])
+
+        alt_snapshot = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'get_snapshot', expected_status=lib_exc.NotFound,
+            snapshot_id=alt_snapshot['id'])
+
+    @decorators.idempotent_id('0dcc1f68-86e2-432e-ad50-51c3cb78b986')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_snapshot(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        snap = self.create_snapshot(share_client, self.share['id'])
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+
+        # We expect this key to be ignored since project_member isn't an admin
+        params = {"all_tenants": 1}
+        snapshot_list = self.do_request(
+            'list_snapshots', expected_status=200, params=params)['snapshots']
+        snapshot_id_list = [
+            s['id'] for s in snapshot_list
+        ]
+
+        self.assertIn(snap['id'], snapshot_id_list)
+        self.assertNotIn(alt_snap['id'], snapshot_id_list)
+
+    @decorators.idempotent_id('d880b3f0-9027-4141-b28a-13e797919af7')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_snapshot(self):
+        snapshot = self.do_request(
+            'create_snapshot', expected_status=202,
+            share_id=self.share['id'])['snapshot']
+        waiters.wait_for_resource_status(
+            self.client, snapshot['id'], 'available', resource_name='snapshot')
+        self.addCleanup(self.delete_resource, self.client,
+                        snapshot_id=snapshot['id'])
+
+    @decorators.idempotent_id('e3fdd270-971f-4478-9e64-9bd11166bab6')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_snapshot(self):
+        snap = self.create_snapshot(self.client, self.share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=202, snap_id=snap['id'])
+        self.client.wait_for_resource_deletion(snapshot_id=snap['id'])
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=lib_exc.NotFound,
+            snap_id=alt_snap['id'])
+
+    @decorators.idempotent_id('a93d6946-1d86-40a1-af01-90e843f8f575')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_snapshot(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        snap = self.create_snapshot(share_client, self.share['id'])
+        self.do_request(
+            'force_delete', expected_status=lib_exc.Forbidden, s_id=snap['id'],
+            s_type='snapshots')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'force_delete', expected_status=lib_exc.Forbidden,
+            s_id=alt_snap['id'], s_type='snapshots')
+
+    @decorators.idempotent_id('6da7bf79-25ab-4475-a5e0-1046781e9bc7')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_rename_snapshot(self):
+        snap = self.create_snapshot(self.client, self.share['id'])
+        name = data_utils.rand_name("updated_snapshot")
+        self.do_request(
+            'rename_snapshot', expected_status=200, snapshot_id=snap['id'],
+            name=name)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'rename_snapshot', expected_status=lib_exc.NotFound,
+            snapshot_id=alt_snap['id'], name=name)
+
+    @decorators.idempotent_id('22ba2e2e-6788-4075-9e92-af140d3b1238')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_snapshot(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        snap = self.create_snapshot(share_client, self.share['id'])
+        self.do_request(
+            'snapshot_reset_state', expected_status=lib_exc.Forbidden,
+            snapshot_id=snap['id'], status='error')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'snapshot_reset_state', expected_status=lib_exc.Forbidden,
+            snapshot_id=alt_snap['id'], status='error')
+
+    @decorators.idempotent_id('a2849a7a-66ae-4cf9-9bac-6420dddd8f03')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_set_snapshot_metadata(self):
+        snap = self.create_snapshot(self.client, self.share['id'])
+        metadata = {u'key': u'value'}
+        self.do_request(
+            'set_metadata', expected_status=200,
+            resource_id=snap['id'], resource='snapshot', metadata=metadata)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.NotFound,
+            resource_id=alt_snap['id'], resource='snapshot', metadata=metadata)
+
+    @decorators.idempotent_id('9a3fc032-eb0c-49e9-8026-d26b05520d95')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_get_snapshot_metadata(self):
+        metadata = {u'key': u'value'}
+        share_client = getattr(self, 'share_member_client', self.client)
+        snap = self.create_snapshot(
+            share_client, self.share['id'], metadata=metadata)
+        self.do_request(
+            'get_metadata_item', expected_status=200,
+            resource_id=snap['id'], key='key', resource='snapshot')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            metadata=metadata)
+        self.do_request(
+            'get_metadata_item', expected_status=lib_exc.NotFound,
+            resource_id=alt_snap['id'], key='key', resource='snapshot')
+
+    @decorators.idempotent_id('aa3ecadd-b87f-4bcd-ab2c-6a19d27c0adb')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_delete_snapshot_metadata(self):
+        metadata = {u'key': u'value'}
+        snap = self.create_snapshot(
+            self.client, self.share['id'], metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=200, resource_id=snap['id'],
+            resource='snapshot', key='key')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.NotFound,
+            resource_id=alt_snap['id'], resource='snapshot', key='key')
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+    """Test suite for basic share snapshot operations by reader user
+
+    In order to test certain share operations we must create a share snapshot
+    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('46a09178-0264-4f56-9a5f-9a0583e72e4d')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_get_snapshot(self):
+        super(TestProjectReaderTestsNFS, self).test_get_snapshot()
+
+    @decorators.idempotent_id('fef4285a-a489-4fec-97af-763c2e33282e')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_list_snapshot(self):
+        super(TestProjectReaderTestsNFS, self).test_list_snapshot()
+
+    @decorators.idempotent_id('17a80156-8cd6-420e-8ffe-97103edef4c3')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_create_snapshot(self):
+        self.do_request(
+            'create_snapshot', expected_status=lib_exc.Forbidden,
+            share_id=self.share['id'])
+
+    @decorators.idempotent_id('b0ca5483-ebdb-484c-a975-525e4d7deca2')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_delete_snapshot(self):
+        snap = self.create_snapshot(self.share_member_client, self.share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=lib_exc.Forbidden,
+            snap_id=snap['id'])
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'delete_snapshot', expected_status=lib_exc.NotFound,
+            snap_id=alt_snap['id'])
+
+    @decorators.idempotent_id('ed0af390-e3d0-432b-9147-c0d569181b92')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_force_delete_snapshot(self):
+        super(TestProjectReaderTestsNFS, self).test_force_delete_snapshot()
+
+    @decorators.idempotent_id('21db863f-c2a4-4d07-b435-2a000255ea3b')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_rename_snapshot(self):
+        snap = self.create_snapshot(self.share_member_client, self.share['id'])
+        name = data_utils.rand_name("updated_snapshot")
+        self.do_request(
+            'rename_snapshot', expected_status=lib_exc.Forbidden,
+            snapshot_id=snap['id'], name=name)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'rename_snapshot', expected_status=lib_exc.NotFound,
+            snapshot_id=alt_snap['id'], name=name)
+
+    @decorators.idempotent_id('b8c9c9a4-3b2a-4b1c-80d8-2ec87d708111')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    def test_reset_snapshot(self):
+        super(TestProjectReaderTestsNFS, self).test_reset_snapshot()
+
+    @decorators.idempotent_id('c9177029-3161-4b5b-b7cb-76f8259a459a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_set_snapshot_metadata(self):
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'])
+        metadata = {u'key': u'value'}
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=snap['id'], resource='snapshot', metadata=metadata)
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'])
+        self.do_request(
+            'set_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_snap['id'], resource='snapshot', metadata=metadata)
+
+    @decorators.idempotent_id('e5471262-fb4f-4a80-91c1-cc925b94f2c1')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_get_snapshot_metadata(self):
+        super(TestProjectMemberTestsNFS, self).test_get_snapshot_metadata()
+
+    @decorators.idempotent_id('e1c0251b-b8f4-439f-b697-ea3fc024c2ff')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+    @utils.skip_if_microversion_not_supported("2.73")
+    def test_delete_snapshot_metadata(self):
+        metadata = {u'key': u'value'}
+        snap = self.create_snapshot(
+            self.share_member_client, self.share['id'], metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=snap['id'], resource='snapshot', key='key')
+
+        alt_snap = self.create_snapshot(
+            self.alt_project_share_v2_client, self.alt_share['id'],
+            metadata=metadata)
+        self.do_request(
+            'delete_metadata', expected_status=lib_exc.Forbidden,
+            resource_id=alt_snap['id'], resource='snapshot', 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_user_messages.py b/manila_tempest_tests/tests/rbac/test_user_messages.py
new file mode 100644
index 0000000..b659f93
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_user_messages.py
@@ -0,0 +1,249 @@
+# 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.common.utils import data_utils
+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
+
+CONF = config.CONF
+
+
+class ShareRbacUserMessageTests(rbac_base.ShareRbacBaseTests,
+                                metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacUserMessageTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+        cls.share_admin_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):
+        # One of the options for generating a user message is to create a share
+        # type with invalid extra_specs. Creating a manila share with this
+        # share type will fail because no valid host is found.
+        extra_specs = {
+            'key': 'value',
+            'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+        }
+        share_type_name = data_utils.rand_name('share-type')
+        cls.share_type = cls.share_admin_client.create_share_type(
+            name=share_type_name, extra_specs=extra_specs)['share_type']
+        cls.addClassResourceCleanup(
+            cls.share_admin_client.delete_share_type, cls.share_type['id'])
+
+    def create_user_message(self, client, cleanup=True):
+        # Trigger a 'no valid host' situation to generate a message.
+        share = client.create_share(
+            share_type_id=self.share_type['id'])['share']
+        self.addCleanup(client.delete_share, share['id'])
+        waiters.wait_for_resource_status(client, share['id'], 'error')
+
+        message = waiters.wait_for_message(client, share['id'])
+        if cleanup:
+            self.addCleanup(client.delete_message, message['id'])
+        return message
+
+    @abc.abstractmethod
+    def test_list_messages(self):
+        pass
+
+    @abc.abstractmethod
+    def test_show_message(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_message(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacUserMessageTests, base.BaseSharesTest):
+
+    credentials = ['project_admin', 'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, 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('2067d8ba-953d-4035-b65d-6001b3d4ea8f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        message = self.create_user_message(
+            self.share_member_client, self.share_type)
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+
+        message_list = self.do_request(
+            'list_messages', expected_status=200)['messages']
+        message_id_list = [
+            s['id'] for s in message_list
+        ]
+
+        self.assertIn(message['id'], message_id_list)
+        self.assertIn(message_alt['id'], message_id_list)
+
+    @decorators.idempotent_id('ec46f10e-c768-4df5-b75a-0ce3e22d8038')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        message = self.create_user_message(
+            self.share_member_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message['id'], expected_status=200)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message_alt['id'], expected_status=200)
+
+    @decorators.idempotent_id('b91c355b-a5f8-47aa-8ab4-00a350f8ac7f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_message(self):
+        message = self.create_user_message(
+            self.share_member_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'], expected_status=204)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=204)
+
+
+class ProjectMemberTests(ShareRbacUserMessageTests, base.BaseSharesTest):
+    """Test suite for basic share use message operations by member user
+
+    In order to test share user message operations we need to preform an action
+    that generates a user message. One of the reasons for generating a user
+    message is share creation that fails because no valid host is found.
+    To achieve this goal we need to create a share type.
+    Since only user with admin credentials can create a share type, we have to
+    initialize these credentials within project member class.
+    """
+
+    credentials = ['project_member', 'project_admin', 'project_alt_member']
+
+    @decorators.idempotent_id('1fd0f86d-cb1e-4694-a54e-4b7774c7c652')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(share_client, self.share_type)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+
+        message_list = self.do_request(
+            'list_messages', expected_status=200)['messages']
+        message_id_list = [
+            s['id'] for s in message_list
+        ]
+
+        self.assertIn(message['id'], message_id_list)
+        self.assertNotIn(message_alt['id'], message_id_list)
+
+    @decorators.idempotent_id('283d33be-727b-4180-a503-95d31cc99a79')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(share_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message['id'], expected_status=200)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message_alt['id'],
+            expected_status=lib_exc.NotFound)
+
+    @decorators.idempotent_id('5821a3a9-6194-414a-9668-0d933a0d4fb0')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_message(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(
+            share_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'],
+            expected_status=204)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=lib_exc.NotFound)
+        self.addCleanup(self.share_admin_client.delete_message,
+                        message_alt['id'])
+
+
+class ProjectReaderTests(ProjectMemberTests):
+    """Test suite for basic share use message 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(ProjectReaderTests, 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('ab3b8812-47df-4472-a410-7f84d52999f3')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        super(ProjectReaderTests, self).test_list_messages()
+
+    @decorators.idempotent_id('f0603a61-b620-4f89-afc5-006d1195fa7f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        super(ProjectReaderTests, self).test_show_message()
+
+    @decorators.idempotent_id('a03695c7-e05a-4c89-9a04-7d94a8dd2419')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_message(self):
+        message = self.create_user_message(
+            self.share_member_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'],
+            expected_status=lib_exc.Forbidden)
+        self.addCleanup(self.share_admin_client.delete_message, message['id'])
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=lib_exc.Forbidden)
+        self.addCleanup(self.share_admin_client.delete_message,
+                        message_alt['id'])
diff --git a/manila_tempest_tests/tests/scenario/manager.py b/manila_tempest_tests/tests/scenario/manager.py
index a73ab44..fe2833a 100644
--- a/manila_tempest_tests/tests/scenario/manager.py
+++ b/manila_tempest_tests/tests/scenario/manager.py
@@ -16,7 +16,6 @@
 
 from oslo_log import log
 from oslo_utils import uuidutils
-from tempest.common import image as common_image
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
@@ -45,24 +44,16 @@
             'name': name,
             'container_format': fmt,
             'disk_format': disk_format or fmt,
+            'visibility': 'private'
         }
-        if CONF.image_feature_enabled.api_v1:
-            params['is_public'] = 'False'
-            params['properties'] = properties
-            params = {'headers': common_image.image_meta_to_headers(**params)}
-        else:
-            params['visibility'] = 'private'
-            # Additional properties are flattened out in the v2 API.
-            params.update(properties)
+        # Additional properties are flattened out in the v2 API.
+        params.update(properties)
         body = self.image_client.create_image(**params)
         image = body['image'] if 'image' in body else body
         self.addCleanup(self.image_client.delete_image, image['id'])
         self.assertEqual("queued", image['status'])
         with open(path, 'rb') as image_file:
-            if CONF.image_feature_enabled.api_v1:
-                self.image_client.update_image(image['id'], data=image_file)
-            else:
-                self.image_client.store_image_file(image['id'], image_file)
+            self.image_client.store_image_file(image['id'], image_file)
         return image['id']
 
     def glance_image_create(self):
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index a847217..6d6efc0 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -84,7 +84,7 @@
         if CONF.share.image_with_share_tools == 'centos':
             self.image_ref = self._create_centos_based_glance_image()
         elif CONF.share.image_with_share_tools:
-            images = self.compute_images_client.list_images()["images"]
+            images = self.image_client.list_images()["images"]
             for img in images:
                 if img["name"] == CONF.share.image_with_share_tools:
                     self.image_id = img['id']
@@ -186,8 +186,7 @@
                         storage_net_nic[0]['addr']
                     )
             # Attach a floating IP
-            self.compute_floating_ips_client.associate_floating_ip_to_server(
-                floating_ip['floating_ip_address'], instance['id'])
+            self.associate_floating_ip(floating_ip, instance)
 
         self.assertIsNotNone(server_ip)
         # Check ssh
diff --git a/manila_tempest_tests/utils.py b/manila_tempest_tests/utils.py
index 5ecfb36..d7d86f1 100644
--- a/manila_tempest_tests/utils.py
+++ b/manila_tempest_tests/utils.py
@@ -19,8 +19,11 @@
 
 from netaddr import ip
 from tempest import config
+from tempest.lib.common.utils import data_utils
 import testtools
 
+from manila_tempest_tests import utils
+
 CONF = config.CONF
 SHARE_NETWORK_SUBNETS_MICROVERSION = '2.51'
 SHARE_REPLICA_QUOTAS_MICROVERSION = "2.53"
@@ -140,6 +143,40 @@
     return address
 
 
+def generate_share_network_data():
+    data = {
+        "name": data_utils.rand_name("sn-name"),
+        "description": data_utils.rand_name("sn-desc"),
+        "neutron_net_id": data_utils.rand_name("net-id"),
+        "neutron_subnet_id": data_utils.rand_name("subnet-id"),
+    }
+    return data
+
+
+def generate_subnet_data():
+    data = {
+        "neutron_net_id": data_utils.rand_name("net-id"),
+        "neutron_subnet_id": data_utils.rand_name("subnet-id"),
+    }
+    return data
+
+
+def generate_security_service_data(set_ou=False):
+    data = {
+        "name": data_utils.rand_name("ss-name"),
+        "description": data_utils.rand_name("ss-desc"),
+        "dns_ip": utils.rand_ip(),
+        "server": utils.rand_ip(),
+        "domain": data_utils.rand_name("ss-domain"),
+        "user": data_utils.rand_name("ss-user"),
+        "password": data_utils.rand_name("ss-password"),
+    }
+    if set_ou:
+        data["ou"] = data_utils.rand_name("ss-ou")
+
+    return data
+
+
 def choose_matching_backend(share, pools, share_type):
     extra_specs = {}
     # fix extra specs with string values instead of boolean
@@ -190,6 +227,33 @@
     return extra_specs
 
 
+def get_access_rule_data_from_config(protocol):
+    """Get the first available access type/to combination from config.
+
+    This method opportunistically picks the first configured protocol
+    to create the share. Do not use this method in tests where you need
+    to test depth and breadth in the access types and access recipients.
+    """
+
+    if protocol in CONF.share.enable_ip_rules_for_protocols:
+        access_type = "ip"
+        access_to = rand_ip()
+    elif protocol in CONF.share.enable_user_rules_for_protocols:
+        access_type = "user"
+        access_to = CONF.share.username_for_user_rules
+    elif protocol in CONF.share.enable_cert_rules_for_protocols:
+        access_type = "cert"
+        access_to = "client3.com"
+    elif protocol in CONF.share.enable_cephx_rules_for_protocols:
+        access_type = "cephx"
+        access_to = data_utils.rand_name("cephx-id")
+    else:
+        message = "Unrecognized protocol and access rules configuration."
+        raise testtools.TestCase.skipException(message)
+
+    return access_type, access_to
+
+
 def replication_with_multitenancy_support():
     return (share_network_subnets_are_supported() and
             CONF.share.multitenancy_enabled)
diff --git a/playbooks/manila-tempest-plugin-standalone/run.yaml b/playbooks/manila-tempest-plugin-standalone/run.yaml
index 8df9205..26ad69a 100644
--- a/playbooks/manila-tempest-plugin-standalone/run.yaml
+++ b/playbooks/manila-tempest-plugin-standalone/run.yaml
@@ -5,7 +5,6 @@
 - hosts: tempest
   roles:
     - setup-tempest-run-dir
-    - set-tempest-config
     - setup-tempest-data-dir
     - acl-devstack-files
     - run-tempest
diff --git a/releasenotes/notes/bug-1993283-ee8d329ae65b4f78.yaml b/releasenotes/notes/bug-1993283-ee8d329ae65b4f78.yaml
new file mode 100644
index 0000000..3c5f775
--- /dev/null
+++ b/releasenotes/notes/bug-1993283-ee8d329ae65b4f78.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+  - |
+    `Bug #1993283 <https://bugs.launchpad.net/manila/+bug/1993283>`_:
+    Fixed SharesActionsTest cases for API version >= 2.73 since a
+    metadata field was added in that version.
diff --git a/requirements.txt b/requirements.txt
index 108bbee..95ad247 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,6 +4,6 @@
 
 pbr!=2.1.0,>=2.0.0 # Apache-2.0
 
-ddt>=1.6.0 # MIT
+ddt>=1.0.1 # MIT
 oslo.log>=3.36.0 # Apache-2.0
 tempest>=31.1.0 # Apache-2.0
diff --git a/roles/set-tempest-config/README.rst b/roles/set-tempest-config/README.rst
deleted file mode 100644
index 9402d3c..0000000
--- a/roles/set-tempest-config/README.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-set-tempest-config
-==================
-
-This is a workaround for the `merge_config_file <https://opendev
-.org/openstack/devstack/src/commit/76d7d7c90c3979c72404fddd31ee884c8bfdb1ec
-/inc/meta-config#L82>`_ routine that doesn't working correctly on jobs based on
-the "devstack-minimal" profile.
-
-**Role Variables**
-
-.. zuul:rolevar:: devstack_base_dir
-   :default: /opt/stack
-
-   The devstack base directory.
-
-.. zuul:rolevar:: devstack_local_conf_path
-   :default: "{{ devstack_base_dir }}/devstack/local.conf"
-
-   Where to find the local.conf file
diff --git a/roles/set-tempest-config/defaults/main.yml b/roles/set-tempest-config/defaults/main.yml
deleted file mode 100644
index 5cc7ca6..0000000
--- a/roles/set-tempest-config/defaults/main.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-devstack_base_dir: /opt/stack
-devstack_local_conf_path: "{{ devstack_base_dir }}/devstack/local.conf"
diff --git a/roles/set-tempest-config/tasks/main.yml b/roles/set-tempest-config/tasks/main.yml
deleted file mode 100644
index 3572ff5..0000000
--- a/roles/set-tempest-config/tasks/main.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-- name: Install required pip packages
-  pip:
-    name: devstack-tools
-    state: "latest"
-    virtualenv: /var/tmp/venv
-
-- name: Copy tempest config
-  shell: >-
-    . /var/tmp/venv/bin/activate && \
-    dsconf extract {{ devstack_local_conf_path }} \
-      test-config \
-      '$TEMPEST_CONFIG' \
-      {{ devstack_base_dir }}/tempest/etc/tempest.conf
-  become: yes
diff --git a/setup.py b/setup.py
index 566d844..cd35c3c 100644
--- a/setup.py
+++ b/setup.py
@@ -13,17 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
 import setuptools
 
-# In python < 2.7.4, a lazy loading of package `pbr` will break
-# setuptools if some other modules registered functions in `atexit`.
-# solution from: http://bugs.python.org/issue15881#msg170215
-try:
-    import multiprocessing  # noqa
-except ImportError:
-    pass
-
 setuptools.setup(
     setup_requires=['pbr>=2.0.0'],
     pbr=True)
diff --git a/tox.ini b/tox.ini
index 153ebbf..907516f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,6 @@
 [tox]
 minversion = 3.1.1
-envlist = py3,pypy,pep8
-skipsdist = True
+envlist = py3,pep8
 
 [testenv]
 basepython = python3
diff --git a/zuul.d/manila-tempest-jobs.yaml b/zuul.d/manila-tempest-jobs.yaml
index c7318af..3a48147 100644
--- a/zuul.d/manila-tempest-jobs.yaml
+++ b/zuul.d/manila-tempest-jobs.yaml
@@ -38,6 +38,7 @@
         tls-proxy: true
       devstack_localrc:
         USE_PYTHON3: true
+        MYSQL_REDUCE_MEMORY: True
         MANILA_USE_DOWNGRADE_MIGRATIONS: true
         MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE: false
         MANILA_ALLOW_NAS_SERVER_PORTS_ON_HOST: true
@@ -161,7 +162,9 @@
     name: manila-tempest-plugin-zfsonlinux
     description: Test ZFSOnLinux multibackend (DHSS=False) with postgresql db
     parent: manila-tempest-plugin-zfsonlinux-base
-    branches: &ubuntu_jammy_test_image_branches ^(?!stable/(yoga|xena|wallaby|victoria|ussuri)).*$
+    branches: &ubuntu_jammy_test_image_branches
+      regex: ^stable/(yoga|xena|wallaby|victoria|ussuri)$
+      negate: true
 
 - job:
     name: manila-tempest-plugin-lvm-base
@@ -174,6 +177,7 @@
       - openstack/neutron-dynamic-routing
     vars:
       tempest_test_regex: '(^manila_tempest_tests.tests)(?=.*\[.*\bbackend\b.*\])'
+      tempest_exclude_regex: "(^manila_tempest_tests.tests.scenario.*)"
       devstack_services: &devstack-with-ovs
         # NOTE(gouthamr): LP#1940324 prevents bgp usage with OVN, disable OVN
         br-ex-tcpdump: false
@@ -228,13 +232,25 @@
               multi_backend: true
               image_password: manila
 
+# NOTE(carloss): Nova bumped libvirt to a version available only on Ubuntu
+# Jammy. We are then forced to migrate this job to use Jammy. When LP Bug
+#1998489 is fixed, we will be able to unify the job above with this.
 - job:
     name: manila-tempest-plugin-lvm
     description: |
-      Test LVM multibackend (DHSS=False) in a 4+6 (dual-stack) devstack
-      environment with IPv6 control plane endpoints.
-    branches: *ubuntu_jammy_test_image_branches
+      Test LVM multibackend (DHSS=False) in a IPv4 environment.
+    branches:
+      regex: ^stable/(2023.1|zed|yoga|xena|wallaby|victoria|ussuri)$
+      negate: true
     parent: manila-tempest-plugin-lvm-base
+    vars:
+      devstack_localrc:
+        MANILA_SETUP_IPV6: false
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            share:
+              run_ipv6_tests: false
 
 - job:
     name: manila-tempest-plugin-container
@@ -305,6 +321,7 @@
         MANILA_USE_SERVICE_INSTANCE_PASSWORD: true
         MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True'
         TEMPEST_USE_TEST_ACCOUNTS: true
+        GLANCE_ENFORCE_SCOPE: false
       devstack_services:
         cinder: true
       devstack_local_conf:
@@ -396,6 +413,25 @@
     branches: *ubuntu_jammy_test_image_branches
 
 - job:
+    name: manila-tempest-plugin-cephfs-native-cephadm
+    description: Test CephFS Native (DHSS=False) deployed with cephadm
+    parent: manila-tempest-plugin-cephfs-native-base
+    vars:
+      configure_swap_size: 8192
+      tempest_test_regex: manila_tempest_tests.tests
+      tempest_exclude_regex: '(^manila_tempest_tests.tests.scenario.*ceph_fuse.*)'
+      devstack_localrc:
+        ENABLE_CEPH_NOVA: false
+        CONTAINER_IMAGE: 'quay.io/ceph/ceph:v17.2.5'
+        CEPHADM_DEPLOY: true
+        CEPHADM_DEV_OSD: true
+        TARGET_DEV_OSD_DIR: /opt/stack
+        CEPH_LOOPBACK_DISK_SIZE: 40G
+        DISABLE_CEPHADM_POST_DEPLOY: True
+        MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-master.qcow2
+        MANILA_SERVICE_IMAGE_NAME: manila-service-image-cephfs-master
+
+- job:
     name: manila-tempest-plugin-cephfs-nfs-base
     abstract: true
     description: Test CephFS NFS (DHSS=False)
@@ -405,6 +441,11 @@
       - openstack/neutron-dynamic-routing
     vars:
       tempest_concurrency: 2
+      # turning off some tests due to exhaustion of disk space
+      # https://bugs.launchpad.net/manila/+bug/2009083
+      tempest_exclude_regex: "\
+        (^manila_tempest_tests.tests.scenario.test_share_extend.TestShareExtendNFSIPv6.test_create_extend_and_write)|\
+        (^manila_tempest_tests.tests.scenario.test_share_shrink.TestShareShrinkNFSIPv6.test_create_shrink_and_write)"
       devstack_services: *devstack-with-ovs # LP 1940324
       devstack_plugins:
         devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
@@ -450,6 +491,119 @@
     description: Test CephFS NFS (DHSS=False)
     parent: manila-tempest-plugin-cephfs-nfs-base
     branches: *ubuntu_jammy_test_image_branches
+    nodeset: devstack-single-node-centos-9-stream
+    vars:
+      # TODO(gouthamr): some tests are disabled due to bugs
+      # IPv6 Tests: https://bugs.launchpad.net/manila/+bug/1998489
+      # snapshot clone fs sync: https://bugs.launchpad.net/manila/+bug/1989273
+      tempest_exclude_regex: "\
+          (^manila_tempest_tests.tests.scenario.*IPv6.*)|\
+          (^manila_tempest_tests.tests.scenario.test_share_basic_ops.TestShareBasicOpsNFS.test_write_data_to_share_created_from_snapshot)"
+      devstack_localrc:
+        MANILA_OPTGROUP_cephfsnfs_cephfs_ganesha_server_ip: "{{ hostvars[inventory_hostname]['nodepool']['private_ipv4'] }}"
+        CEPH_RELEASE: "quincy"
+        MANILA_SETUP_IPV6: false
+        NEUTRON_CREATE_INITIAL_NETWORKS: true
+        IP_VERSION: 4
+
+- job:
+    name: manila-tempest-plugin-multinode-base
+    abstract: true
+    description: |
+      Base job for testing multinode with Manila. Manila is enabled in
+      the controller node; and we have an additional compute node.
+    parent: tempest-multinode-full-py3
+    timeout: 10800
+    irrelevant-files: *irrelevant-files
+    required-projects: *manila-tempest-required-projects
+    vars:
+      tox_envlist: all
+      tempest_test_regex: manila_tempest_tests
+      tempest_plugins:
+        - manila-tempest-plugin
+      tempest_concurrency: 8
+      devstack_services:
+        cinder: false
+        c-bak: false
+        s-account: false
+        s-container: false
+        s-object: false
+        s-proxy: false
+        horizon: false
+        tls-proxy: true
+      devstack_localrc:
+        MANILA_USE_DOWNGRADE_MIGRATIONS: false
+        MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE: false
+        MANILA_ALLOW_NAS_SERVER_PORTS_ON_HOST: true
+        MANILA_SHARE_MIGRATION_PERIOD_TASK_INTERVAL: 1
+        MANILA_SERVER_MIGRATION_PERIOD_TASK_INTERVAL: 10
+        MANILA_REPLICA_STATE_UPDATE_INTERVAL: 10
+    group-vars:
+      tempest:
+        devstack_plugins:
+          manila: https://opendev.org/openstack/manila
+      subnode:
+        devstack_services:
+          cinder: false
+          c-bak: false
+
+- job:
+    name: manila-tempest-plugin-multinode-cephfs-nfs-cephadm
+    description: Test CephFS NFS (DHSS=False) in a Multinode devstack env
+    parent: manila-tempest-plugin-multinode-base
+    required-projects:
+      - openstack/devstack-plugin-ceph
+    vars:
+      configure_swap_size: 8192
+      tempest_concurrency: 2
+        # TODO(gouthamr): some tests are disabled due to bugs
+        # IPv6 Tests: https://bugs.launchpad.net/manila/+bug/1998489
+        # snapshot clone fs sync: https://bugs.launchpad.net/manila/+bug/1989273
+      tempest_exclude_regex: "\
+      (^manila_tempest_tests.tests.scenario.*IPv6.*)|\
+      (^manila_tempest_tests.tests.scenario.test_share_basic_ops.TestShareBasicOpsNFS.test_write_data_to_share_created_from_snapshot)"
+      devstack_localrc:
+        MYSQL_REDUCE_MEMORY: True
+        CEPHADM_DEPLOY: True
+        CEPHADM_DEV_OSD: true
+        CEPH_LOOPBACK_DISK_SIZE: 40GB
+        ENABLED_SHARE_PROTOCOLS: NFS
+        ENABLE_CEPH_MANILA: True
+        ENABLE_CEPH_NOVA: False
+        MANILA_CEPH_DRIVER: cephfsnfs
+        MANILA_CONFIGURE_DEFAULT_TYPES: true
+        MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True'
+        MANILA_ENABLED_BACKENDS: cephfsnfs
+        MANILA_OPTGROUP_cephfsnfs_cephfs_auth_id: manila
+        MANILA_OPTGROUP_cephfsnfs_cephfs_conf_path: /etc/ceph/ceph.conf
+        MANILA_OPTGROUP_cephfsnfs_cephfs_nfs_cluster_id: cephfs
+        MANILA_OPTGROUP_cephfsnfs_cephfs_protocol_helper_type: NFS
+        MANILA_OPTGROUP_cephfsnfs_driver_handles_share_servers: false
+        MANILA_OPTGROUP_cephfsnfs_share_driver: manila.share.drivers.cephfs.driver.CephFSDriver
+        MANILA_SERVICE_IMAGE_ENABLED: True
+        MANILA_SETUP_IPV6: false
+        SHARE_DRIVER: manila.share.drivers.cephfs.driver.CephFSDriver
+        TARGET_DEV_OSD_DIR: /opt/stack
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            share:
+              backend_names: cephfsnfs
+              capability_storage_protocol: NFS
+              default_share_type_name: default
+              enable_protocols: nfs
+              image_password: manila
+              multitenancy_enabled: false
+              run_share_group_tests: false
+    group-vars:
+      subnode:
+        devstack_plugins:
+          devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
+        devstack_localrc:
+          REMOTE_CEPH: True
+      tempest:
+        devstack_plugins:
+          devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
 
 - job:
     name: manila-tempest-plugin-dummy-no-dhss
@@ -639,6 +793,22 @@
               enable_ro_access_level_for_protocols: ""
 
 - job:
+    name: manila-tempest-plugin-dummy-no-dhss-rbac
+    parent: manila-tempest-plugin-dummy-no-dhss
+    description: |
+      This job runs the devstack with scope checks enabled,
+      on the Dummy driver with DHSS=False.
+    vars:
+      tempest_test_regex: 'manila_tempest_tests.tests.rbac'
+      devstack_localrc:
+        MANILA_ENFORCE_SCOPE: true
+      devstack_local_conf:
+        test-config:
+          "$TEMPEST_CONFIG":
+            share:
+              default_share_type_name: default
+
+- job:
     name: manila-tempest-plugin-lvm-fips-base
     parent: manila-tempest-plugin-lvm-base
     nodeset: devstack-single-node-centos-9-stream
@@ -664,7 +834,9 @@
 - job:
     name: manila-tempest-plugin-lvm-fips
     parent: manila-tempest-plugin-lvm-fips-base
-    branches: ^(?!stable/(yoga|xena|wallaby|victoria|ussuri)).*$
+    branches:
+      regex: ^stable/(yoga|xena|wallaby|victoria|ussuri)$
+      negate: true
 
 - project-template:
     name: manila-tempest-plugin-jobs-using-service-image
@@ -678,9 +850,9 @@
             voting: false
         - manila-tempest-plugin-generic:
             voting: false
-        - manila-tempest-plugin-cephfs-native:
+        - manila-tempest-plugin-cephfs-native-cephadm:
             voting: false
-        - manila-tempest-plugin-cephfs-nfs:
+        - manila-tempest-plugin-multinode-cephfs-nfs-cephadm:
             voting: false
         - manila-tempest-plugin-zfsonlinux:
             voting: false
diff --git a/zuul.d/manila-tempest-stable-jobs.yaml b/zuul.d/manila-tempest-stable-jobs.yaml
index d5adfce..0fb38ab 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/(2023.1|zed|yoga|xena)$
     vars: &manila_tempest_image_pinned_vars
       devstack_localrc:
         # NOTE(carloss): Pinning manila service image to a Focal version,
@@ -27,15 +27,12 @@
 
 - job:
     name: manila-tempest-plugin-lvm-stable
-    # NOTE(carloss): we are aware that focal is the current default, but
-    # in order to avoid breakages when devstack-minimal switches to a newer
-    # branch, we are pinning focal here.
-    nodeset: openstack-single-node-focal
     description: |
       Test LVM multibackend (DHSS=False) in a 4+6 (dual-stack) devstack
       environment with IPv6 control plane endpoints.
     branches: *manila_tempest_image_pinned_branches
     parent: manila-tempest-plugin-lvm-base
+    nodeset: openstack-single-node-focal
     vars: *manila_tempest_image_pinned_vars
 
 - job:
@@ -68,30 +65,21 @@
 - 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:
     name: manila-tempest-plugin-lvm-yoga
     parent: manila-tempest-plugin-lvm-base
-    nodeset: openstack-single-node-focal
     override-checkout: stable/yoga
     vars: *manila_tempest_image_pinned_vars
 
 - job:
     name: manila-tempest-plugin-lvm-xena
     parent: manila-tempest-plugin-lvm-base
-    nodeset: openstack-single-node-focal
     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 9db197c..48d3d4c 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -10,7 +10,7 @@
         - 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
         - manila-tempest-plugin-glusterfs-nfs: