Merge "Fix share network subnet cleanup"
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 2c1b375..56a5b5a 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.73",
+               default="2.74",
                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 6ea0b92..bf944d4 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -1159,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):
@@ -1563,8 +1563,8 @@
         return rest_client.ResponseBody(resp, body)
 
     def create_share_replica(self, share_id, availability_zone=None,
-                             version=LATEST_MICROVERSION,
-                             scheduler_hints=None):
+                             scheduler_hints=None, share_network_id=None,
+                             version=LATEST_MICROVERSION):
         """Add a share replica of an existing share."""
         uri = "share-replicas"
         post_body = {
@@ -1574,6 +1574,9 @@
 
         if scheduler_hints:
             post_body["scheduler_hints"] = scheduler_hints
+        if share_network_id:
+            post_body['share_network_id'] = share_network_id
+
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_REPLICA_GRADUATION_VERSION)
         body = json.dumps({'share_replica': post_body})
@@ -2144,4 +2147,5 @@
                    f'/{resource}s/{resource_id}/metadata/{key}')
         resp, body = self.get(uri)
         self.expected_success(200, resp.status)
-        return self._parse_resp(body)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/manila_tempest_tests/tests/api/admin/test_replication.py b/manila_tempest_tests/tests/api/admin/test_replication.py
index 242e786..3458023 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication.py
@@ -105,9 +105,13 @@
 
         # NOTE(Yogi1): Cleanup needs to be disabled for replica that is
         # being promoted since it will become the 'primary'/'active' replica.
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
         replica = self.create_share_replica(
-            share["id"], self.replica_zone, cleanup=False,
-            client=self.admin_client, version=version)
+            share["id"], self.replica_zone, share_network_id=share_net_id,
+            cleanup=False, client=self.admin_client, version=version)
         # Wait for replica state to update after creation
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
@@ -156,11 +160,15 @@
     def test_force_delete_share_replica(self, version):
         """Test force deleting a replica that is in 'error_deleting' status."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False,
+            client=self.admin_client, version=version)
         self.admin_client.reset_share_replica_status(
             replica['id'], constants.STATUS_ERROR_DELETING, version=version)
         waiters.wait_for_resource_status(
@@ -179,11 +187,15 @@
     def test_reset_share_replica_status(self, version):
         """Test resetting a replica's 'status' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_status(replica['id'],
                                                      constants.STATUS_ERROR,
                                                      version=version)
@@ -200,11 +212,15 @@
     def test_reset_share_replica_state(self, version):
         """Test resetting a replica's 'replica_state' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_state(replica['id'],
                                                     constants.STATUS_ERROR,
                                                     version=version)
@@ -222,11 +238,12 @@
     def test_resync_share_replica(self, version):
         """Test resyncing a replica."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], share_network_id=share_net_id, version=version)
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
             constants.REPLICATION_STATE_IN_SYNC, resource_name='share_replica',
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types.py b/manila_tempest_tests/tests/api/admin/test_share_types.py
index d23171a..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/base.py b/manila_tempest_tests/tests/api/base.py
index 0674e96..c5282d9 100755
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -676,14 +676,17 @@
 
     @classmethod
     def create_share_replica(cls, share_id, availability_zone=None,
+                             scheduler_hints=None,
+                             share_network_id=None,
                              client=None, cleanup_in_class=False,
                              cleanup=True,
-                             version=CONF.share.max_api_microversion,
-                             scheduler_hints=None):
+                             version=CONF.share.max_api_microversion):
         client = client or cls.shares_v2_client
         replica = client.create_share_replica(
             share_id, availability_zone=availability_zone,
-            version=version, scheduler_hints=scheduler_hints)['share_replica']
+            scheduler_hints=scheduler_hints,
+            share_network_id=share_network_id,
+            version=version)['share_replica']
         resource = {
             "type": "share_replica",
             "id": replica["id"],
diff --git a/manila_tempest_tests/tests/api/test_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_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 9a9a478..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):
@@ -360,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,
diff --git a/manila_tempest_tests/tests/api/test_replication_negative.py b/manila_tempest_tests/tests/api/test_replication_negative.py
index dde5d80..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,7 +191,10 @@
 
     @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):
+    @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
@@ -200,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
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 da3d5ee..1ae5351 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets.py
@@ -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'])
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 af4815f..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_snapshot_metadata.py b/manila_tempest_tests/tests/api/test_snapshot_metadata.py
index fb64618..0596213 100644
--- a/manila_tempest_tests/tests/api/test_snapshot_metadata.py
+++ b/manila_tempest_tests/tests/api/test_snapshot_metadata.py
@@ -72,7 +72,7 @@
         # verify metadata items
         for key in md:
             get_value = self.shares_v2_client.get_metadata_item(
-                snapshot['id'], key, resource="snapshot")
+                snapshot['id'], key, resource="snapshot")['meta']
             self.assertEqual(md[key], get_value[key])
 
     @decorators.idempotent_id('5d537913-ce6f-4771-beb2-84e2390b06d3')
diff --git a/manila_tempest_tests/tests/rbac/base.py b/manila_tempest_tests/tests/rbac/base.py
index 5aaf35e..b1eba9b 100644
--- a/manila_tempest_tests/tests/rbac/base.py
+++ b/manila_tempest_tests/tests/rbac/base.py
@@ -83,9 +83,10 @@
         return share
 
     @classmethod
-    def create_snapshot(cls, client, share_id, name=None):
+    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)['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(
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_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_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_shares.py b/manila_tempest_tests/tests/rbac/test_shares.py
index 50fa4ce..2ca3c92 100644
--- a/manila_tempest_tests/tests/rbac/test_shares.py
+++ b/manila_tempest_tests/tests/rbac/test_shares.py
@@ -361,9 +361,8 @@
             **self.share(self.share_type['id']))['share']
         waiters.wait_for_resource_status(self.client,
                                          share['id'], 'available')
-        self.addCleanup(self.client.wait_for_resource_deletion,
+        self.addCleanup(self.delete_resource, self.client,
                         share_id=share['id'])
-        self.addCleanup(self.client.delete_share, share['id'])
 
     @decorators.idempotent_id('6c546ed7-ebfd-4ac5-a626-d333a25a9e66')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
diff --git a/manila_tempest_tests/tests/rbac/test_snapshots.py b/manila_tempest_tests/tests/rbac/test_snapshots.py
index beffc52..810ba9b 100644
--- a/manila_tempest_tests/tests/rbac/test_snapshots.py
+++ b/manila_tempest_tests/tests/rbac/test_snapshots.py
@@ -24,6 +24,7 @@
 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
 
@@ -74,6 +75,18 @@
     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):
 
@@ -202,6 +215,60 @@
             '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):
 
@@ -320,6 +387,59 @@
             '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
@@ -405,6 +525,47 @@
     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'
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/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/zuul.d/manila-tempest-jobs.yaml b/zuul.d/manila-tempest-jobs.yaml
index de1298f..690b8bc 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
@@ -353,7 +354,6 @@
 
 - job:
     name: manila-tempest-plugin-cephfs-native-base
-    nodeset: openstack-single-node-focal
     abstract: true
     description: Test CephFS Native (DHSS=False)
     parent: manila-tempest-plugin-base
@@ -393,13 +393,32 @@
 
 - job:
     name: manila-tempest-plugin-cephfs-native
+    nodeset: openstack-single-node-focal
     description: Test CephFS Native (DHSS=False)
     parent: manila-tempest-plugin-cephfs-native-base
     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
-    nodeset: openstack-single-node-focal
     abstract: true
     description: Test CephFS NFS (DHSS=False)
     parent: manila-tempest-plugin-base
@@ -408,6 +427,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
@@ -453,6 +477,20 @@
     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-dummy-no-dhss
@@ -699,7 +737,7 @@
             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:
             voting: false
diff --git a/zuul.d/manila-tempest-stable-jobs.yaml b/zuul.d/manila-tempest-stable-jobs.yaml
index d5adfce..28db229 100644
--- a/zuul.d/manila-tempest-stable-jobs.yaml
+++ b/zuul.d/manila-tempest-stable-jobs.yaml
@@ -1,4 +1,4 @@
-# Stable wallaby / xena / yoga branch jobs to test the trunk version of
+# Stable xena / yoga / zed branch jobs to test the trunk version of
 # manila-tempest-plugin against those released stable branches of manila
 
 - job:
@@ -7,7 +7,7 @@
       Test the scenario test cases on the generic driver multibackend
       (DHSS=True) with NFS and CIFS
     parent: manila-tempest-plugin-generic-scenario-base
-    branches: &manila_tempest_image_pinned_branches ^(stable/(yoga|xena|wallaby)).*$
+    branches: &manila_tempest_image_pinned_branches ^(stable/(zed|yoga|xena)).*$
     vars: &manila_tempest_image_pinned_vars
       devstack_localrc:
         # NOTE(carloss): Pinning manila service image to a Focal version,
@@ -68,7 +68,7 @@
 - job:
     name: manila-tempest-plugin-lvm-fips-stable
     parent: manila-tempest-plugin-lvm-fips-base
-    branches: ^(stable/(yoga|xena|wallaby)).*$
+    branches: ^(stable/(yoga|xena)).*$
     vars: *manila_tempest_image_pinned_vars
 
 - job:
@@ -85,13 +85,6 @@
     override-checkout: stable/xena
     vars: *manila_tempest_image_pinned_vars
 
-- job:
-    name: manila-tempest-plugin-lvm-wallaby
-    parent: manila-tempest-plugin-lvm-base
-    nodeset: openstack-single-node-focal
-    override-checkout: stable/wallaby
-    vars: *manila_tempest_image_pinned_vars
-
 - project-template:
     name: manila-tempest-plugin-jobs-using-service-image-stable
     description: |
diff --git a/zuul.d/manila-tempest-wallaby-jobs.yaml b/zuul.d/manila-tempest-wallaby-jobs.yaml
new file mode 100644
index 0000000..57fe515
--- /dev/null
+++ b/zuul.d/manila-tempest-wallaby-jobs.yaml
@@ -0,0 +1,131 @@
+# Stable wallaby branch jobs run with a pinned version of manila-tempest-plugin
+
+- job:
+    name: manila-tempest-plugin-generic-scenario-wallaby
+    description: |
+      Test the scenario test cases on the generic driver multibackend
+      (DHSS=True) with NFS and CIFS in the stable/wallaby branch
+    parent: manila-tempest-plugin-generic-scenario-base
+    vars: &manila_tempest_image_pinned_vars
+      devstack_localrc:
+        # NOTE(carloss): Pinning manila service image to a Focal version,
+        # since on Zed we moved to Ubuntu Jammy (22), and it requires more
+        # VM resources.
+        MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-1.3.0-76-ga216835.qcow2
+        MANILA_SERVICE_IMAGE_NAME: manila-service-image-1.3.0-76-ga216835
+    required-projects: &manila-tempest-plugin-pinned-version
+      - name: openstack/manila-tempest-plugin
+        override-checkout: 1.8.0
+
+- job:
+    name: manila-tempest-plugin-generic-wallaby
+    description: |
+      Test the generic driver multibackend (DHSS=True) with NFS and CIFS in
+      stable wallaby
+    parent: manila-tempest-plugin-generic-base
+    vars: *manila_tempest_image_pinned_vars
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-lvm-wallaby
+    description: |
+      Test LVM multibackend (DHSS=False) in a 4+6 (dual-stack) devstack
+      environment with IPv6 control plane endpoints on the stable/wallaby
+      branch
+    parent: manila-tempest-plugin-lvm-base
+    vars: *manila_tempest_image_pinned_vars
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-cephfs-native-wallaby
+    description: Test CephFS Native (DHSS=False) in stable/wallaby
+    parent: manila-tempest-plugin-cephfs-native-base
+    vars:
+      devstack_localrc:
+        # NOTE(gouthamr): The following need to use the latest images, however, there's a bug
+        # with cephfs on Ubuntu 20.04 LTS: https://tracker.ceph.com/issues/47236
+        # the latest image is built as https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-master.qcow2
+        MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-1.3.0-58-g2859569.qcow2
+        MANILA_SERVICE_IMAGE_NAME: manila-service-image-cephfs-1.3.0-58-g2859569
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-cephfs-nfs-wallaby
+    description: Test CephFS NFS (DHSS=False) in stable/wallaby
+    parent: manila-tempest-plugin-cephfs-nfs-base
+    vars: *manila_tempest_image_pinned_vars
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-zfsonlinux-wallaby
+    description: |
+      Test ZFSOnLinux multibackend (DHSS=False) with postgresql db in
+      stable wallaby
+    parent: manila-tempest-plugin-zfsonlinux-base
+    vars: *manila_tempest_image_pinned_vars
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-dummy-no-dhss-wallaby
+    description: Test the Dummy driver with DHSS=False in stable wallaby
+    parent: manila-tempest-plugin-dummy-no-dhss
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-dummy-dhss-wallaby
+    description: Test the Dummy driver with DHSS=True in stable wallaby
+    parent: manila-tempest-plugin-dummy-dhss
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-container-wallaby
+    description: |
+        Test the container driver multibackend (DHSS=True) with CIFS
+        and postgresql db. API only, in a minimal devstack in stable wallaby
+    parent: manila-tempest-plugin-container
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-glusterfs-native-wallaby
+    description: |
+      Test the GlusterFS driver (DHSS=False) with the native GlusterFS
+      protocol in stable wallaby
+    parent: manila-tempest-plugin-glusterfs-native
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-glusterfs-nfs-wallaby
+    description: |
+      Test the GlusterFS driver (DHSS=False) with the native NFS protocol in
+      stable wallaby
+    parent: manila-tempest-plugin-glusterfs-nfs
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- job:
+    name: manila-tempest-plugin-lvm-fips-wallaby
+    description: |
+      Test the LVM driver (DHSS=False) in a FIPS-enabled environment
+    parent: manila-tempest-plugin-lvm-fips-base
+    required-projects: *manila-tempest-plugin-pinned-version
+
+- project-template:
+    name: manila-tempest-plugin-jobs-using-service-image-wallaby
+    description: |
+      Runs jobs that will also perform scenario tests in the stable/wallaby
+      branches.
+    check:
+      jobs:
+        - manila-tempest-plugin-lvm-wallaby
+        - manila-tempest-plugin-generic-scenario-wallaby:
+            voting: false
+        - manila-tempest-plugin-generic-wallaby:
+            voting: false
+        - manila-tempest-plugin-cephfs-native-wallaby:
+            voting: false
+        - manila-tempest-plugin-cephfs-nfs-wallaby:
+            voting: false
+        - manila-tempest-plugin-zfsonlinux-wallaby:
+            voting: false
+    gate:
+      jobs:
+        - manila-tempest-plugin-lvm-wallaby
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index af9767c..48d3d4c 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -10,7 +10,6 @@
         - manila-tempest-plugin-dummy-dhss
         - manila-tempest-plugin-lvm-yoga
         - manila-tempest-plugin-lvm-xena
-        - manila-tempest-plugin-lvm-wallaby
         - manila-tempest-plugin-dummy-no-dhss-rbac
         - manila-tempest-plugin-container:
             voting: false