Merge "[RBAC] Add share access rules tests"
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..648b282 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -1563,8 +1563,8 @@
         return rest_client.ResponseBody(resp, body)
 
     def create_share_replica(self, share_id, availability_zone=None,
-                             version=LATEST_MICROVERSION,
-                             scheduler_hints=None):
+                             scheduler_hints=None, share_network_id=None,
+                             version=LATEST_MICROVERSION):
         """Add a share replica of an existing share."""
         uri = "share-replicas"
         post_body = {
@@ -1574,6 +1574,9 @@
 
         if scheduler_hints:
             post_body["scheduler_hints"] = scheduler_hints
+        if share_network_id:
+            post_body['share_network_id'] = share_network_id
+
         headers, extra_headers = utils.get_extra_headers(
             version, constants.SHARE_REPLICA_GRADUATION_VERSION)
         body = json.dumps({'share_replica': post_body})
diff --git a/manila_tempest_tests/tests/api/admin/test_replication.py b/manila_tempest_tests/tests/api/admin/test_replication.py
index 242e786..3458023 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication.py
@@ -105,9 +105,13 @@
 
         # NOTE(Yogi1): Cleanup needs to be disabled for replica that is
         # being promoted since it will become the 'primary'/'active' replica.
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
         replica = self.create_share_replica(
-            share["id"], self.replica_zone, cleanup=False,
-            client=self.admin_client, version=version)
+            share["id"], self.replica_zone, share_network_id=share_net_id,
+            cleanup=False, client=self.admin_client, version=version)
         # Wait for replica state to update after creation
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
@@ -156,11 +160,15 @@
     def test_force_delete_share_replica(self, version):
         """Test force deleting a replica that is in 'error_deleting' status."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False,
+            client=self.admin_client, version=version)
         self.admin_client.reset_share_replica_status(
             replica['id'], constants.STATUS_ERROR_DELETING, version=version)
         waiters.wait_for_resource_status(
@@ -179,11 +187,15 @@
     def test_reset_share_replica_status(self, version):
         """Test resetting a replica's 'status' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_status(replica['id'],
                                                      constants.STATUS_ERROR,
                                                      version=version)
@@ -200,11 +212,15 @@
     def test_reset_share_replica_state(self, version):
         """Test resetting a replica's 'replica_state' attribute."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], self.replica_zone,
+            share_network_id=share_net_id,
+            cleanup_in_class=False, client=self.admin_client,
+            version=version)
         self.admin_client.reset_share_replica_state(replica['id'],
                                                     constants.STATUS_ERROR,
                                                     version=version)
@@ -222,11 +238,12 @@
     def test_resync_share_replica(self, version):
         """Test resyncing a replica."""
         utils.check_skip_if_microversion_not_supported(version)
-        replica = self.create_share_replica(self.share['id'],
-                                            self.replica_zone,
-                                            cleanup_in_class=False,
-                                            client=self.admin_client,
-                                            version=version)
+        share_net_id = None
+        if utils.is_microversion_ge(version, (
+                constants.SHARE_REPLICA_SHARE_NET_PARAM_VERSION)):
+            share_net_id = self.sn_id
+        replica = self.create_share_replica(
+            self.share['id'], share_network_id=share_net_id, version=version)
         waiters.wait_for_resource_status(
             self.admin_client, replica['id'],
             constants.REPLICATION_STATE_IN_SYNC, resource_name='share_replica',
diff --git a/manila_tempest_tests/tests/api/admin/test_share_networks.py b/manila_tempest_tests/tests/api/admin/test_share_networks.py
index 82d8a8a..3eedb4e 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_networks.py
@@ -18,6 +18,7 @@
 
 from manila_tempest_tests.tests.api import base
 from manila_tempest_tests.tests.api import test_share_networks
+from manila_tempest_tests import utils
 
 
 class ShareNetworkAdminTest(base.BaseSharesMixedTest,
@@ -26,7 +27,7 @@
     @classmethod
     def resource_setup(cls):
         super(ShareNetworkAdminTest, cls).resource_setup()
-        ss_data = cls.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         cls.ss_ldap = cls.create_security_service(**ss_data)
 
         cls.data_sn_with_ldap_ss = {
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index e7fe125..226e767 100755
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -676,14 +676,17 @@
 
     @classmethod
     def create_share_replica(cls, share_id, availability_zone=None,
+                             scheduler_hints=None,
+                             share_network_id=None,
                              client=None, cleanup_in_class=False,
                              cleanup=True,
-                             version=CONF.share.max_api_microversion,
-                             scheduler_hints=None):
+                             version=CONF.share.max_api_microversion):
         client = client or cls.shares_v2_client
         replica = client.create_share_replica(
             share_id, availability_zone=availability_zone,
-            version=version, scheduler_hints=scheduler_hints)['share_replica']
+            scheduler_hints=scheduler_hints,
+            share_network_id=share_network_id,
+            version=version)['share_replica']
         resource = {
             "type": "share_replica",
             "id": replica["id"],
@@ -906,40 +909,6 @@
                                     "cleanup '%s'. Skipping.", res["type"])
                 res["deleted"] = True
 
-    @classmethod
-    def generate_share_network_data(self):
-        data = {
-            "name": data_utils.rand_name("sn-name"),
-            "description": data_utils.rand_name("sn-desc"),
-            "neutron_net_id": data_utils.rand_name("net-id"),
-            "neutron_subnet_id": data_utils.rand_name("subnet-id"),
-        }
-        return data
-
-    @classmethod
-    def generate_subnet_data(self):
-        data = {
-            "neutron_net_id": data_utils.rand_name("net-id"),
-            "neutron_subnet_id": data_utils.rand_name("subnet-id"),
-        }
-        return data
-
-    @classmethod
-    def generate_security_service_data(self, set_ou=False):
-        data = {
-            "name": data_utils.rand_name("ss-name"),
-            "description": data_utils.rand_name("ss-desc"),
-            "dns_ip": utils.rand_ip(),
-            "server": utils.rand_ip(),
-            "domain": data_utils.rand_name("ss-domain"),
-            "user": data_utils.rand_name("ss-user"),
-            "password": data_utils.rand_name("ss-password"),
-        }
-        if set_ou:
-            data["ou"] = data_utils.rand_name("ss-ou")
-
-        return data
-
     # Useful assertions
     def assertDictMatch(self, d1, d2, approx_equal=False, tolerance=0.001):
         """Assert two dicts are equivalent.
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 0262142..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
@@ -249,7 +256,7 @@
     @utils.skip_if_microversion_not_supported("2.51")
     def test_try_add_replica_nonexistent_subnet(self):
         # Create a new share network only for a specific az
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
         subnet = utils.share_network_get_default_subnet(self.share_network)
         data['neutron_net_id'] = subnet['neutron_net_id']
         data['neutron_subnet_id'] = subnet['neutron_subnet_id']
diff --git a/manila_tempest_tests/tests/api/test_security_services.py b/manila_tempest_tests/tests/api/test_security_services.py
index f938a91..85ed5fb 100644
--- a/manila_tempest_tests/tests/api/test_security_services.py
+++ b/manila_tempest_tests/tests/api/test_security_services.py
@@ -162,7 +162,7 @@
     @decorators.idempotent_id('70927e29-4a6a-431a-bbc1-76bc419e0579')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_delete_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         self.service_names = ["ldap", "kerberos", "active_directory"]
         for ss_name in self.service_names:
             ss = self.create_security_service(ss_name, **data)
@@ -176,7 +176,7 @@
     def test_get_security_service(self, version):
         utils.check_skip_if_microversion_not_supported(version)
         with_ou = True if utils.is_microversion_ge(version, '2.44') else False
-        data = self.generate_security_service_data(set_ou=with_ou)
+        data = utils.generate_security_service_data(set_ou=with_ou)
 
         if utils.is_microversion_ge(version, '2.0'):
             ss = self.create_security_service(
@@ -196,11 +196,11 @@
     @decorators.idempotent_id('84d47747-13c8-4ab9-9fc4-a43fbb29ad18')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_update_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         ss = self.create_security_service(**data)
         self.assertDictContainsSubset(data, ss)
 
-        upd_data = self.generate_security_service_data()
+        upd_data = utils.generate_security_service_data()
         updated = self.shares_client.update_security_service(
             ss["id"], **upd_data)['security_service']
 
@@ -211,7 +211,7 @@
 
         if utils.is_microversion_ge(CONF.share.max_api_microversion, '2.44'):
             # update again with ou
-            upd_data_ou = self.generate_security_service_data(set_ou=True)
+            upd_data_ou = utils.generate_security_service_data(set_ou=True)
             updated_ou = self.shares_v2_client.update_security_service(
                 ss["id"], **upd_data_ou)['security_service']
 
@@ -225,7 +225,7 @@
     @testtools.skipIf(
         not CONF.share.multitenancy_enabled, "Only for multitenancy.")
     def test_try_update_valid_keys_sh_server_exists(self):
-        ss_data = self.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         ss = self.create_security_service(**ss_data)
 
         sn = self.shares_client.get_share_network(
@@ -274,7 +274,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_try_list_security_services_all_tenants_ignored(self):
         alt_security_service = self.create_security_service(
-            **self.generate_security_service_data(),
+            **utils.generate_security_service_data(),
             client=self.alt_shares_v2_client)
         alt_security_service_id = alt_security_service['id']
         sec_service_list = self.shares_client.list_security_services(
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping.py b/manila_tempest_tests/tests/api/test_security_services_mapping.py
index 2e7531d..6ce9a0a 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping.py
@@ -17,6 +17,7 @@
 from testtools import testcase as tc
 
 from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
 
 
 class SecurityServicesMappingTest(base.BaseSharesTest):
@@ -30,7 +31,7 @@
         super(SecurityServicesMappingTest, self).setUp()
 
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         self.sn = self.create_share_network(client=self.cl,
                                             add_security_services=False,
@@ -38,7 +39,7 @@
         self.assertDictContainsSubset(data, self.sn)
 
         # create security service
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
 
         self.ss = self.create_security_service(client=self.cl, **data)
         self.assertDictContainsSubset(data, self.ss)
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
index d0bb321..96506ce 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
@@ -146,7 +146,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_map_two_ss_with_same_type_to_sn(self):
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         sn = self.create_share_network(client=self.cl,
                                        add_security_services=False, **data)
@@ -155,7 +155,7 @@
         # create security services with same type
         security_services = []
         for i in range(2):
-            data = self.generate_security_service_data()
+            data = utils.generate_security_service_data()
             ss = self.create_security_service(client=self.cl, **data)
             self.assertDictContainsSubset(data, ss)
             security_services.insert(i, ss)
@@ -173,14 +173,14 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_delete_ss_that_assigned_to_sn(self):
         # create share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         sn = self.create_share_network(client=self.cl,
                                        add_security_services=False, **data)
         self.assertDictContainsSubset(data, sn)
 
         # create security service
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
 
         ss = self.create_security_service(client=self.cl, **data)
         self.assertDictContainsSubset(data, ss)
diff --git a/manila_tempest_tests/tests/api/test_security_services_negative.py b/manila_tempest_tests/tests/api/test_security_services_negative.py
index 08e3c7b..23c7cc1 100644
--- a/manila_tempest_tests/tests/api/test_security_services_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_negative.py
@@ -21,6 +21,7 @@
 from testtools import testcase as tc
 
 from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
 
 CONF = config.CONF
 LOG = log.getLogger(__name__)
@@ -93,7 +94,7 @@
     @testtools.skipIf(
         not CONF.share.multitenancy_enabled, "Only for multitenancy.")
     def test_try_update_invalid_keys_sh_server_exists(self):
-        ss_data = self.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         ss = self.create_security_service(**ss_data)
 
         sn = self.shares_client.get_share_network(
@@ -129,7 +130,7 @@
     @decorators.idempotent_id('288dbf42-ee22-4445-8363-7ebb1c3d89c9')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_get_deleted_security_service(self):
-        data = self.generate_security_service_data()
+        data = utils.generate_security_service_data()
         ss = self.create_security_service(**data)
         self.assertDictContainsSubset(data, ss)
 
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets.py b/manila_tempest_tests/tests/api/test_share_network_subnets.py
index cdf2162..da3d5ee 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets.py
@@ -61,7 +61,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
@@ -95,7 +95,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
index 7b0ca55..52b297e 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
@@ -55,7 +55,7 @@
     @decorators.idempotent_id('d20b6105-22d1-4fc0-8468-45dd019240c0')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_add_share_network_subnet_share_network_not_found(self):
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         self.assertRaises(lib_exc.NotFound,
                           self.shares_v2_client.create_subnet,
                           'fake_inexistent_id',
@@ -94,7 +94,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_add_share_network_subnet_missing_parameters(self):
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['availability_zone'] = self.az_name
 
         data.pop('neutron_net_id')
@@ -122,7 +122,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_get_deleted_subnet(self):
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = self.share_network_id
         az = self.shares_v2_client.list_availability_zones(
             )['availability_zones'][0]
diff --git a/manila_tempest_tests/tests/api/test_share_networks.py b/manila_tempest_tests/tests/api/test_share_networks.py
index e3d5a78..f990566 100644
--- a/manila_tempest_tests/tests/api/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/test_share_networks.py
@@ -165,7 +165,7 @@
         cls.share_type = cls.create_share_type()
         cls.share_type_id = cls.share_type['id']
 
-        ss_data = cls.generate_security_service_data()
+        ss_data = utils.generate_security_service_data()
         cls.ss_ldap = cls.create_security_service(**ss_data)
 
         cls.data_sn_with_ldap_ss = {
@@ -219,7 +219,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_delete_share_network(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create share network
         created = self.shares_client.create_share_network(
@@ -242,7 +242,7 @@
     @decorators.idempotent_id('1837fdd3-8068-4e88-bc50-9224498f84c0')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_update_share_network(self):
-        update_data = self.generate_share_network_data()
+        update_data = utils.generate_share_network_data()
         updated = self.shares_client.update_share_network(
             self.sn_with_ldap_ss["id"],
             **update_data)['share_network']
@@ -268,7 +268,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_recreate_share_network(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create share network
         sn1 = self.shares_client.create_share_network(**data)['share_network']
@@ -288,7 +288,7 @@
     @tc.attr(base.TAG_POSITIVE, base.TAG_API)
     def test_create_two_share_networks_with_same_net_and_subnet(self):
         # generate data for share network
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
 
         # create first share network
         sn1 = self.create_share_network(**data)
diff --git a/manila_tempest_tests/tests/api/test_share_networks_negative.py b/manila_tempest_tests/tests/api/test_share_networks_negative.py
index 3306068..94fa7b8 100644
--- a/manila_tempest_tests/tests/api/test_share_networks_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_networks_negative.py
@@ -88,7 +88,7 @@
     @decorators.idempotent_id('9166b81c-d6ab-4592-bcf7-9410250e30dd')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     def test_try_get_deleted_share_network(self):
-        data = self.generate_share_network_data()
+        data = utils.generate_share_network_data()
         sn = self.create_share_network(**data)
         self.assertDictContainsSubset(data, sn)
 
@@ -166,7 +166,7 @@
         az_name = az['name']
 
         # Generate subnet data
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         data['share_network_id'] = share_network['id']
         data['availability_zone'] = az_name
 
@@ -200,7 +200,7 @@
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
     @decorators.idempotent_id('f6f47c64-6821-4d4a-aa7d-3b0244158197')
     def test_check_add_share_network_subnet_share_network_not_found(self):
-        data = self.generate_subnet_data()
+        data = utils.generate_subnet_data()
         self.assertRaises(lib_exc.NotFound,
                           self.shares_v2_client.subnet_create_check,
                           'fake_inexistent_id',
diff --git a/manila_tempest_tests/tests/rbac/base.py b/manila_tempest_tests/tests/rbac/base.py
index db53795..5aaf35e 100644
--- a/manila_tempest_tests/tests/rbac/base.py
+++ b/manila_tempest_tests/tests/rbac/base.py
@@ -102,6 +102,19 @@
         return share_network
 
     @classmethod
+    def create_share_type(cls):
+        name = data_utils.rand_name('share-type')
+        extra_specs = {
+            'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+        }
+        share_type = cls.admin_shares_v2_client.create_share_type(
+            name=name, extra_specs=extra_specs)['share_type']
+        cls.addClassResourceCleanup(
+            cls.delete_resource, cls.admin_shares_v2_client,
+            st_id=share_type['id'])
+        return share_type
+
+    @classmethod
     def get_share_type(cls):
         return cls.shares_v2_client.get_default_share_type()['share_type']
 
diff --git a/manila_tempest_tests/tests/rbac/test_availability_zones.py b/manila_tempest_tests/tests/rbac/test_availability_zones.py
new file mode 100644
index 0000000..1754726
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_availability_zones.py
@@ -0,0 +1,69 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import abc
+
+from tempest.lib import decorators
+from testtools import testcase as tc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+
+class ShareRbacAvailabilityZonesTests(rbac_base.ShareRbacBaseTests,
+                                      metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacAvailabilityZonesTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+
+    @abc.abstractmethod
+    def test_list_availability_zones(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacAvailabilityZonesTests,
+                               base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @decorators.idempotent_id('87d9bb1c-f4de-40e5-8f25-05a6e1055c0b')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
+
+
+class TestProjectMemberTestsNFS(ShareRbacAvailabilityZonesTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_member']
+
+    @decorators.idempotent_id('ee2db349-176a-47bc-a20d-5ba9b5f8a813')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
+
+
+class TestProjectReaderTestsNFS(ShareRbacAvailabilityZonesTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_reader']
+
+    @decorators.idempotent_id('a095fac8-ae62-4be7-8a3e-b0fc1bc71348')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_availability_zones(self):
+        self.do_request('list_availability_zones', expected_status=200)
diff --git a/manila_tempest_tests/tests/rbac/test_export_locations.py b/manila_tempest_tests/tests/rbac/test_export_locations.py
index 168a6cb..4bd7074 100644
--- a/manila_tempest_tests/tests/rbac/test_export_locations.py
+++ b/manila_tempest_tests/tests/rbac/test_export_locations.py
@@ -77,13 +77,15 @@
     @decorators.idempotent_id('c8d75c9f-104b-48a8-9817-17280ce516a8')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
     def test_list_export_locations(self):
-        self.do_request(
+        locations = self.do_request(
             'list_share_export_locations', expected_status=200,
-            share_id=self.share['id'])
+            share_id=self.share['id'])['export_locations']
+        self.assertNotEmpty(locations)
 
-        self.do_request(
+        alt_locations = self.do_request(
             'list_share_export_locations', expected_status=200,
-            share_id=self.alt_share['id'])
+            share_id=self.alt_share['id'])['export_locations']
+        self.assertNotEmpty(alt_locations)
 
     @decorators.idempotent_id('01ac6355-fcad-4af8-b0ad-748fc111051d')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -122,9 +124,10 @@
     @decorators.idempotent_id('b25351bb-102f-437e-a0c1-01d926fa0a7d')
     @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
     def test_list_export_locations(self):
-        self.do_request(
+        locations = self.do_request(
             'list_share_export_locations', expected_status=200,
-            share_id=self.share['id'])
+            share_id=self.share['id'])['export_locations']
+        self.assertNotEmpty(locations)
 
         self.do_request(
             'list_share_export_locations', expected_status=lib_exc.Forbidden,
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_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_manage.py b/manila_tempest_tests/tests/rbac/test_share_manage.py
new file mode 100644
index 0000000..272ec66
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_manage.py
@@ -0,0 +1,241 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import abc
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.common import constants
+from manila_tempest_tests.common import waiters
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+CONF = config.CONF
+
+
+class ShareRbacManageShareTests(rbac_base.ShareRbacBaseTests,
+                                metaclass=abc.ABCMeta):
+
+    @classmethod
+    def skip_checks(cls):
+        super(ShareRbacManageShareTests, cls).skip_checks()
+        if not CONF.share.run_manage_unmanage_tests:
+            raise cls.skipException('Manage/unmanage tests are disabled.')
+        if cls.protocol not in CONF.share.enable_protocols:
+            message = "%s tests are disabled" % cls.protocol
+            raise cls.skipException(message)
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacManageShareTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+        cls.admin_shares_v2_client = (
+            cls.os_project_admin.share_v2.SharesV2Client())
+        cls.alt_project_share_v2_client = (
+            cls.os_project_alt_member.share_v2.SharesV2Client())
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareRbacManageShareTests, cls).resource_setup()
+        cls.share_type = cls.get_share_type()
+
+    def share_manage_preparations(self, share_id, unmanage=True):
+        share_info = self.admin_shares_v2_client.get_share(share_id)['share']
+        export_path = self.admin_shares_v2_client.list_share_export_locations(
+            share_id)['export_locations'][0]
+        protocol = share_info['share_proto']
+        service_host = share_info['host']
+
+        if unmanage:
+            self.admin_shares_v2_client.unmanage_share(share_id)
+            self.admin_shares_v2_client.wait_for_resource_deletion(
+                share_id=share_id)
+        return {
+            'export_path': export_path,
+            'protocol': protocol,
+            'service_host': service_host
+        }
+
+    @abc.abstractmethod
+    def test_manage_share(self):
+        pass
+
+    @abc.abstractmethod
+    def test_unmanage_share(self):
+        pass
+
+
+class TestProjectAdminTestsNFS(ShareRbacManageShareTests, base.BaseSharesTest):
+
+    credentials = ['project_admin', 'project_alt_member']
+    protocol = 'nfs'
+
+    @classmethod
+    def setup_clients(cls):
+        super(TestProjectAdminTestsNFS, cls).setup_clients()
+        project_member = cls.setup_user_client(
+            cls.persona, project_id=cls.persona.credentials.project_id)
+        cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+    @decorators.idempotent_id('8a21f805-2d45-4b0c-8ec5-3f45337bbf66')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_manage_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        share_data = self.share_manage_preparations(share['id'])
+        self.do_request(
+            'manage_share', expected_status=200,
+            share_type_id=self.share_type['id'], **share_data)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        alt_share_data = self.share_manage_preparations(alt_share['id'])
+        self.do_request(
+            'manage_share', expected_status=200,
+            share_type_id=self.share_type['id'], **alt_share_data)
+
+    @decorators.idempotent_id('be5b836d-d6cc-40a5-acf4-e5f249035383')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_unmanage_share(self):
+        share = self.create_share(
+            self.share_member_client, self.share_type['id'])
+        share_data = self.share_manage_preparations(
+            share['id'], unmanage=False)
+        self.do_request(
+            'unmanage_share', expected_status=202, share_id=share['id'])
+        self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
+
+        # Unmanaged share operation removes the share from the management of
+        # the shared file systems service without deleting the share.
+        # In order to be able to delete the share we need to manage it again,
+        # otherwise, it would leave some allocated space.
+        managed_share = self.client.manage_share(
+            share_type_id=self.share_type['id'], **share_data)['share']
+        waiters.wait_for_resource_status(
+            self.client, managed_share['id'], constants.STATUS_AVAILABLE)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        share_data = self.share_manage_preparations(
+            alt_share['id'], unmanage=False)
+        self.do_request(
+            'unmanage_share', expected_status=202, share_id=alt_share['id'])
+        self.shares_v2_client.wait_for_resource_deletion(
+            share_id=alt_share['id'])
+
+        alt_managed_share = self.client.manage_share(
+            share_type_id=self.share_type['id'], **share_data)['share']
+        waiters.wait_for_resource_status(
+            self.client, alt_managed_share['id'], constants.STATUS_AVAILABLE)
+
+
+class TestProjectMemberTestsNFS(ShareRbacManageShareTests,
+                                base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_admin', 'project_alt_member']
+    protocol = 'nfs'
+
+    @decorators.idempotent_id('46f884b2-531d-41c0-8455-8874629b3ea3')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_manage_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        share_data = self.share_manage_preparations(
+            share['id'], unmanage=False)
+        self.do_request(
+            'manage_share', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], **share_data)
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        alt_share_data = self.share_manage_preparations(
+            alt_share['id'], unmanage=False)
+        self.do_request(
+            'manage_share', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], **alt_share_data)
+
+    @decorators.idempotent_id('9dc2b1a5-8195-46b8-a28a-9710be352f18')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_unmanage_share(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        share = self.create_share(share_client, self.share_type['id'])
+        self.do_request(
+            'unmanage_share', expected_status=lib_exc.Forbidden,
+            share_id=share['id'])
+
+        alt_share = self.create_share(
+            self.alt_project_share_v2_client, self.share_type['id'])
+        self.do_request(
+            'unmanage_share', expected_status=lib_exc.Forbidden,
+            share_id=alt_share['id'])
+
+
+class TestProjectReaderTestsNFS(TestProjectMemberTestsNFS):
+    """Test suite for basic share operations by reader user
+
+    In order to test certain share operations we must create a share resource
+    for this. Since reader user is limited in resources creation, we are forced
+    to use admin credentials, so we can test other share operations.
+    In this class we use admin user to create a member user within reader
+    project. That way we can perform a reader actions on this resource.
+    """
+
+    credentials = ['project_reader', 'project_admin', 'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(TestProjectReaderTestsNFS, cls).setup_clients()
+        project_member = cls.setup_user_client(
+            cls.os_project_admin,
+            project_id=cls.persona.credentials.project_id)
+        cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+    @decorators.idempotent_id('cec85349-b7e3-440e-bbbc-3bb5999b119a')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_manage_share(self):
+        super(TestProjectReaderTestsNFS, self).test_manage_share()
+
+    @decorators.idempotent_id('a524620c-90b6-496c-8418-c469e711a607')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+    def test_unmanage_share(self):
+        super(TestProjectReaderTestsNFS, self).test_unmanage_share()
+
+
+class TestProjectAdminTestsCEPHFS(TestProjectAdminTestsNFS):
+    protocol = 'cephfs'
+
+
+class TestProjectMemberTestsCEPHFS(TestProjectMemberTestsNFS):
+    protocol = 'cephfs'
+
+
+class TestProjectReaderTestsCEPHFS(TestProjectReaderTestsNFS):
+    protocol = 'cephfs'
+
+
+class TestProjectAdminTestsCIFS(TestProjectAdminTestsNFS):
+    protocol = 'cifs'
+
+
+class TestProjectMemberTestsCIFS(TestProjectMemberTestsNFS):
+    protocol = 'cifs'
+
+
+class TestProjectReaderTestsCIFS(TestProjectReaderTestsNFS):
+    protocol = 'cifs'
diff --git a/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py b/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py
new file mode 100644
index 0000000..0fae6f0
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_share_type_extra_specs.py
@@ -0,0 +1,170 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import abc
+
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+CONF = config.CONF
+
+
+class ShareRbacExtraSpecsTests(rbac_base.ShareRbacBaseTests,
+                               metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacExtraSpecsTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+        cls.admin_shares_v2_client = (
+            cls.os_project_admin.share_v2.SharesV2Client())
+
+    @classmethod
+    def resource_setup(cls):
+        super(ShareRbacExtraSpecsTests, cls).resource_setup()
+        cls.extra_specs = {u'key': u'value'}
+        cls.share_type = cls.create_share_type()
+
+    @abc.abstractmethod
+    def test_create_share_type_extra_specs(self):
+        pass
+
+    @abc.abstractmethod
+    def test_get_share_type_extra_specs(self):
+        pass
+
+    @abc.abstractmethod
+    def test_update_share_type_extra_spec(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_share_type_extra_spec(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacExtraSpecsTests, base.BaseSharesTest):
+
+    credentials = ['project_admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, cls).setup_clients()
+        project_member = cls.setup_user_client(
+            cls.persona, project_id=cls.persona.credentials.project_id)
+        cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+    @decorators.idempotent_id('d51817f4-b186-4eca-8779-f3c36dcd98e7')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        self.do_request(
+            'create_share_type_extra_specs', expected_status=200,
+            share_type_id=self.share_type['id'], extra_specs=self.extra_specs)
+        self.addCleanup(
+            self.admin_shares_v2_client.delete_share_type_extra_spec,
+            self.share_type['id'], extra_spec_name='key')
+
+    @decorators.idempotent_id('d4deeb0b-8765-4487-9f1f-9f10088934dd')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        self.do_request(
+            'get_share_type_extra_specs', expected_status=200,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('bb27641b-5249-4343-bb08-5a123f31b9f1')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        self.do_request(
+            'update_share_type_extra_spec', expected_status=200,
+            share_type_id=self.share_type['id'], spec_name='key',
+            spec_value='value_updated')
+
+    @decorators.idempotent_id('81d59322-8ec1-4f32-a50d-2fedd1cca655')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_type_extra_specs(
+            self.share_type['id'], self.extra_specs)
+        self.do_request(
+            'delete_share_type_extra_spec', expected_status=202,
+            share_type_id=self.share_type['id'], extra_spec_name='key')
+
+
+class ProjectMemberTests(ShareRbacExtraSpecsTests, base.BaseSharesTest):
+
+    credentials = ['project_member', 'project_admin']
+
+    @decorators.idempotent_id('446c1e7c-5ca2-46f5-b2f3-6417152e5bf8')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        self.do_request(
+            'create_share_type_extra_specs', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], extra_specs=self.extra_specs)
+
+    @decorators.idempotent_id('aabdf0c1-8b68-4c40-a542-cc1dbd039279')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        self.do_request(
+            'get_share_type_extra_specs', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'])
+
+    @decorators.idempotent_id('3629f91c-ad21-4321-acd9-7fca92a4721a')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        self.do_request(
+            'update_share_type_extra_spec', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], spec_name='key',
+            spec_value='value_updated')
+
+    @decorators.idempotent_id('0bee97ab-b406-481c-9b8b-4813fb9f49dc')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        self.admin_shares_v2_client.create_share_type_extra_specs(
+            self.share_type['id'], self.extra_specs)
+        self.do_request(
+            'delete_share_type_extra_spec', expected_status=lib_exc.Forbidden,
+            share_type_id=self.share_type['id'], extra_spec_name='key')
+        self.addCleanup(
+            self.admin_shares_v2_client.delete_share_type_extra_spec,
+            self.share_type['id'], extra_spec_name='key')
+
+
+class ProjectReaderTests(ProjectMemberTests):
+
+    credentials = ['project_reader', 'project_admin']
+
+    @decorators.idempotent_id('da80b823-9a96-45c3-8f86-e9f7fc5ad2c6')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_create_share_type_extra_specs(self):
+        super(ProjectReaderTests, self).test_create_share_type_extra_specs()
+
+    @decorators.idempotent_id('78989220-22dc-46d2-b83b-63f070988eed')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_get_share_type_extra_specs(self):
+        super(ProjectReaderTests, self).test_get_share_type_extra_specs()
+
+    @decorators.idempotent_id('c77173d4-b90c-4edf-a9b6-a26c81aaec42')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_update_share_type_extra_spec(self):
+        super(ProjectReaderTests, self).test_update_share_type_extra_spec()
+
+    @decorators.idempotent_id('46fc8e62-b987-444f-ab9f-cd86a8960156')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_share_type_extra_spec(self):
+        super(ProjectReaderTests, self).test_delete_share_type_extra_spec()
diff --git a/manila_tempest_tests/tests/rbac/test_share_types.py b/manila_tempest_tests/tests/rbac/test_share_types.py
index 2263747..e4e6016 100644
--- a/manila_tempest_tests/tests/rbac/test_share_types.py
+++ b/manila_tempest_tests/tests/rbac/test_share_types.py
@@ -155,7 +155,7 @@
 
 class ProjectReaderTests(ShareRbacShareTypesTests, base.BaseSharesTest):
 
-    credentials = ['project_reader', 'project_member']
+    credentials = ['project_reader']
 
     @decorators.idempotent_id('f4c352c4-c12b-4722-9fe7-9a2ec639ee63')
     @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
diff --git a/manila_tempest_tests/tests/rbac/test_user_messages.py b/manila_tempest_tests/tests/rbac/test_user_messages.py
new file mode 100644
index 0000000..b659f93
--- /dev/null
+++ b/manila_tempest_tests/tests/rbac/test_user_messages.py
@@ -0,0 +1,249 @@
+# Copyright 2022 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import abc
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+from testtools import testcase as tc
+
+from manila_tempest_tests.common import waiters
+from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.rbac import base as rbac_base
+
+CONF = config.CONF
+
+
+class ShareRbacUserMessageTests(rbac_base.ShareRbacBaseTests,
+                                metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super(ShareRbacUserMessageTests, cls).setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.share_v2.SharesV2Client()
+        cls.share_admin_client = cls.os_project_admin.share_v2.SharesV2Client()
+        cls.alt_project_share_v2_client = (
+            cls.os_project_alt_member.share_v2.SharesV2Client())
+
+    @classmethod
+    def resource_setup(cls):
+        # One of the options for generating a user message is to create a share
+        # type with invalid extra_specs. Creating a manila share with this
+        # share type will fail because no valid host is found.
+        extra_specs = {
+            'key': 'value',
+            'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+        }
+        share_type_name = data_utils.rand_name('share-type')
+        cls.share_type = cls.share_admin_client.create_share_type(
+            name=share_type_name, extra_specs=extra_specs)['share_type']
+        cls.addClassResourceCleanup(
+            cls.share_admin_client.delete_share_type, cls.share_type['id'])
+
+    def create_user_message(self, client, cleanup=True):
+        # Trigger a 'no valid host' situation to generate a message.
+        share = client.create_share(
+            share_type_id=self.share_type['id'])['share']
+        self.addCleanup(client.delete_share, share['id'])
+        waiters.wait_for_resource_status(client, share['id'], 'error')
+
+        message = waiters.wait_for_message(client, share['id'])
+        if cleanup:
+            self.addCleanup(client.delete_message, message['id'])
+        return message
+
+    @abc.abstractmethod
+    def test_list_messages(self):
+        pass
+
+    @abc.abstractmethod
+    def test_show_message(self):
+        pass
+
+    @abc.abstractmethod
+    def test_delete_message(self):
+        pass
+
+
+class ProjectAdminTests(ShareRbacUserMessageTests, base.BaseSharesTest):
+
+    credentials = ['project_admin', 'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectAdminTests, cls).setup_clients()
+        project_member = cls.setup_user_client(
+            cls.persona, project_id=cls.persona.credentials.project_id)
+        cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+    @decorators.idempotent_id('2067d8ba-953d-4035-b65d-6001b3d4ea8f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        message = self.create_user_message(
+            self.share_member_client, self.share_type)
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+
+        message_list = self.do_request(
+            'list_messages', expected_status=200)['messages']
+        message_id_list = [
+            s['id'] for s in message_list
+        ]
+
+        self.assertIn(message['id'], message_id_list)
+        self.assertIn(message_alt['id'], message_id_list)
+
+    @decorators.idempotent_id('ec46f10e-c768-4df5-b75a-0ce3e22d8038')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        message = self.create_user_message(
+            self.share_member_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message['id'], expected_status=200)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message_alt['id'], expected_status=200)
+
+    @decorators.idempotent_id('b91c355b-a5f8-47aa-8ab4-00a350f8ac7f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_message(self):
+        message = self.create_user_message(
+            self.share_member_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'], expected_status=204)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=204)
+
+
+class ProjectMemberTests(ShareRbacUserMessageTests, base.BaseSharesTest):
+    """Test suite for basic share use message operations by member user
+
+    In order to test share user message operations we need to preform an action
+    that generates a user message. One of the reasons for generating a user
+    message is share creation that fails because no valid host is found.
+    To achieve this goal we need to create a share type.
+    Since only user with admin credentials can create a share type, we have to
+    initialize these credentials within project member class.
+    """
+
+    credentials = ['project_member', 'project_admin', 'project_alt_member']
+
+    @decorators.idempotent_id('1fd0f86d-cb1e-4694-a54e-4b7774c7c652')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(share_client, self.share_type)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+
+        message_list = self.do_request(
+            'list_messages', expected_status=200)['messages']
+        message_id_list = [
+            s['id'] for s in message_list
+        ]
+
+        self.assertIn(message['id'], message_id_list)
+        self.assertNotIn(message_alt['id'], message_id_list)
+
+    @decorators.idempotent_id('283d33be-727b-4180-a503-95d31cc99a79')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(share_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message['id'], expected_status=200)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, self.share_type)
+        self.do_request(
+            'get_message', message_id=message_alt['id'],
+            expected_status=lib_exc.NotFound)
+
+    @decorators.idempotent_id('5821a3a9-6194-414a-9668-0d933a0d4fb0')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_delete_message(self):
+        share_client = getattr(self, 'share_member_client', self.client)
+        message = self.create_user_message(
+            share_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'],
+            expected_status=204)
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=lib_exc.NotFound)
+        self.addCleanup(self.share_admin_client.delete_message,
+                        message_alt['id'])
+
+
+class ProjectReaderTests(ProjectMemberTests):
+    """Test suite for basic share use message operations by reader user
+
+    In order to test certain share operations we must create a share resource
+    for this. Since reader user is limited in resources creation, we are forced
+    to use admin credentials, so we can test other share operations.
+    In this class we use admin user to create a member user within reader
+    project. That way we can perform a reader actions on this resource.
+    """
+
+    credentials = ['project_reader', 'project_admin', 'project_alt_member']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ProjectReaderTests, cls).setup_clients()
+        project_member = cls.setup_user_client(
+            cls.os_project_admin,
+            project_id=cls.persona.credentials.project_id)
+        cls.share_member_client = project_member.share_v2.SharesV2Client()
+
+    @decorators.idempotent_id('ab3b8812-47df-4472-a410-7f84d52999f3')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_list_messages(self):
+        super(ProjectReaderTests, self).test_list_messages()
+
+    @decorators.idempotent_id('f0603a61-b620-4f89-afc5-006d1195fa7f')
+    @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+    def test_show_message(self):
+        super(ProjectReaderTests, self).test_show_message()
+
+    @decorators.idempotent_id('a03695c7-e05a-4c89-9a04-7d94a8dd2419')
+    @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+    def test_delete_message(self):
+        message = self.create_user_message(
+            self.share_member_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message['id'],
+            expected_status=lib_exc.Forbidden)
+        self.addCleanup(self.share_admin_client.delete_message, message['id'])
+
+        message_alt = self.create_user_message(
+            self.alt_project_share_v2_client, cleanup=False)
+        self.do_request(
+            'delete_message', message_id=message_alt['id'],
+            expected_status=lib_exc.Forbidden)
+        self.addCleanup(self.share_admin_client.delete_message,
+                        message_alt['id'])
diff --git a/manila_tempest_tests/utils.py b/manila_tempest_tests/utils.py
index 057558b..d7d86f1 100644
--- a/manila_tempest_tests/utils.py
+++ b/manila_tempest_tests/utils.py
@@ -22,6 +22,8 @@
 from tempest.lib.common.utils import data_utils
 import testtools
 
+from manila_tempest_tests import utils
+
 CONF = config.CONF
 SHARE_NETWORK_SUBNETS_MICROVERSION = '2.51'
 SHARE_REPLICA_QUOTAS_MICROVERSION = "2.53"
@@ -141,6 +143,40 @@
     return address
 
 
+def generate_share_network_data():
+    data = {
+        "name": data_utils.rand_name("sn-name"),
+        "description": data_utils.rand_name("sn-desc"),
+        "neutron_net_id": data_utils.rand_name("net-id"),
+        "neutron_subnet_id": data_utils.rand_name("subnet-id"),
+    }
+    return data
+
+
+def generate_subnet_data():
+    data = {
+        "neutron_net_id": data_utils.rand_name("net-id"),
+        "neutron_subnet_id": data_utils.rand_name("subnet-id"),
+    }
+    return data
+
+
+def generate_security_service_data(set_ou=False):
+    data = {
+        "name": data_utils.rand_name("ss-name"),
+        "description": data_utils.rand_name("ss-desc"),
+        "dns_ip": utils.rand_ip(),
+        "server": utils.rand_ip(),
+        "domain": data_utils.rand_name("ss-domain"),
+        "user": data_utils.rand_name("ss-user"),
+        "password": data_utils.rand_name("ss-password"),
+    }
+    if set_ou:
+        data["ou"] = data_utils.rand_name("ss-ou")
+
+    return data
+
+
 def choose_matching_backend(share, pools, share_type):
     extra_specs = {}
     # fix extra specs with string values instead of boolean
diff --git a/tox.ini b/tox.ini
index 153ebbf..907516f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,6 @@
 [tox]
 minversion = 3.1.1
-envlist = py3,pypy,pep8
-skipsdist = True
+envlist = py3,pep8
 
 [testenv]
 basepython = python3
diff --git a/zuul.d/manila-tempest-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