Merge "Fix stein: use the old terminology for exclusion list"
diff --git a/.zuul.yaml b/.zuul.yaml
index ebb7762..be5f933 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -11,9 +11,14 @@
         - nova-ceph-multistore:
             voting: false
         - cinder-tempest-plugin-cbak-ceph
+        - cinder-tempest-plugin-cbak-s3
+        - cinder-tempest-plugin-basic-wallaby
         - cinder-tempest-plugin-basic-victoria
         - cinder-tempest-plugin-basic-ussuri
         - cinder-tempest-plugin-basic-train
+        # Set this job to voting once we have some actual tests to run
+        - cinder-tempest-plugin-protection-functional:
+            voting: false
     gate:
       jobs:
         - cinder-tempest-plugin-lvm-lio-barbican
@@ -21,11 +26,32 @@
         - cinder-tempest-plugin-cbak-ceph
     experimental:
       jobs:
+        - cinder-tempest-plugin-cbak-ceph-wallaby
         - cinder-tempest-plugin-cbak-ceph-victoria
         - cinder-tempest-plugin-cbak-ceph-ussuri
         - cinder-tempest-plugin-cbak-ceph-train
 
 - job:
+    name: cinder-tempest-plugin-protection-functional
+    parent: devstack-tempest
+    required-projects:
+      - opendev.org/openstack/cinder-tempest-plugin
+      - opendev.org/openstack/cinder
+    vars:
+      tox_envlist: all
+      tempest_test_regex: 'cinder_tempest_plugin.rbac'
+      devstack_local_conf:
+        test-config:
+          $CINDER_CONF:
+            oslo_policy:
+              enforce_new_defaults: True
+          $TEMPEST_CONFIG:
+            enforce_scope:
+              cinder: True
+      tempest_plugins:
+        - cinder-tempest-plugin
+
+- job:
     name: cinder-tempest-plugin-lvm-barbican-base-abstract
     description: |
       This is a base job for lvm with lio & tgt targets
@@ -109,6 +135,12 @@
         c-bak: true
 
 - job:
+    name: cinder-tempest-plugin-cbak-ceph-wallaby
+    parent: cinder-tempest-plugin-cbak-ceph
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/wallaby
+
+- job:
     name: cinder-tempest-plugin-cbak-ceph-victoria
     parent: cinder-tempest-plugin-cbak-ceph
     nodeset: openstack-single-node-focal
@@ -167,6 +199,21 @@
         CINDER_ISCSI_HELPER: tgtadm
 
 - job:
+    name: cinder-tempest-plugin-cbak-s3
+    parent: cinder-tempest-plugin-basic
+    description: |
+      Integration tests that runs with the s3 backup driver with
+      Swift S3 API.
+    vars:
+      devstack_localrc:
+        CINDER_BACKUP_DRIVER: 's3_swift'
+      devstack_services:
+        c-bak: true
+        s3api: true
+        # Workaround: TLS proxy seems to cause S3 signature mismatch.
+        tls-proxy: false
+      tempest_test_regex: '(test_volume_backup|test_volumes_backup|test_snapshot_backup)'
+- job:
     name: cinder-tempest-plugin-basic
     parent: devstack-tempest
     description: |
@@ -187,6 +234,12 @@
       - ^releasenotes/.*$
 
 - job:
+    name: cinder-tempest-plugin-basic-wallaby
+    parent: cinder-tempest-plugin-basic
+    nodeset: openstack-single-node-focal
+    override-checkout: stable/wallaby
+
+- job:
     name: cinder-tempest-plugin-basic-victoria
     parent: cinder-tempest-plugin-basic
     nodeset: openstack-single-node-focal
diff --git a/cinder_tempest_plugin/rbac/__init__.py b/cinder_tempest_plugin/rbac/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cinder_tempest_plugin/rbac/__init__.py
diff --git a/cinder_tempest_plugin/rbac/v3/__init__.py b/cinder_tempest_plugin/rbac/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cinder_tempest_plugin/rbac/v3/__init__.py
diff --git a/cinder_tempest_plugin/rbac/v3/base.py b/cinder_tempest_plugin/rbac/v3/base.py
new file mode 100644
index 0000000..d1a11e5
--- /dev/null
+++ b/cinder_tempest_plugin/rbac/v3/base.py
@@ -0,0 +1,42 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest import config
+
+CONF = config.CONF
+
+
+class VolumeV3RbacBaseTests(object):
+
+    identity_version = 'v3'
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeV3RbacBaseTests, cls).skip_checks()
+        if not CONF.enforce_scope.cinder:
+            raise cls.skipException(
+                "Tempest is not configured to enforce_scope for cinder, "
+                "skipping RBAC tests. To enable these tests set "
+                "`tempest.conf [enforce_scope] cinder=True`."
+            )
+
+    def do_request(self, method, expected_status=200, client=None, **payload):
+        if not client:
+            client = self.client
+        if isinstance(expected_status, type(Exception)):
+            self.assertRaises(expected_status,
+                              getattr(client, method),
+                              **payload)
+        else:
+            response = getattr(client, method)(**payload)
+            self.assertEqual(response.response.status, expected_status)
+            return response
diff --git a/cinder_tempest_plugin/rbac/v3/test_capabilities.py b/cinder_tempest_plugin/rbac/v3/test_capabilities.py
new file mode 100644
index 0000000..1fa542d
--- /dev/null
+++ b/cinder_tempest_plugin/rbac/v3/test_capabilities.py
@@ -0,0 +1,80 @@
+#    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 exceptions
+
+from cinder_tempest_plugin.api.volume import base
+from cinder_tempest_plugin.rbac.v3 import base as rbac_base
+
+
+class VolumeV3RbacCapabilityTests(rbac_base.VolumeV3RbacBaseTests,
+                                  metaclass=abc.ABCMeta):
+
+    @classmethod
+    def setup_clients(cls):
+        super().setup_clients()
+        cls.persona = getattr(cls, 'os_%s' % cls.credentials[0])
+        cls.client = cls.persona.volume_capabilities_client_latest
+        # NOTE(lbragstad): This admin_client will be more useful later when
+        # cinder supports system-scope and we need it for administrative
+        # operations. For now, keep os_project_admin as the admin client until
+        # we have system-scope.
+        admin_client = cls.os_project_admin
+        cls.admin_capabilities_client = (
+            admin_client.volume_capabilities_client_latest)
+        cls.admin_stats_client = (
+            admin_client.volume_scheduler_stats_client_latest)
+
+    @classmethod
+    def setup_credentials(cls):
+        super().setup_credentials()
+        cls.os_primary = getattr(cls, 'os_%s' % cls.credentials[0])
+
+    @abc.abstractmethod
+    def test_get_capabilities(self):
+        """Test volume_extension:capabilities policy.
+
+        This test must check:
+          * whether the persona can fetch capabilities for a host.
+
+        """
+        pass
+
+
+class ProjectAdminTests(VolumeV3RbacCapabilityTests, base.BaseVolumeTest):
+
+    credentials = ['project_admin', 'system_admin']
+
+    def test_get_capabilities(self):
+        pools = self.admin_stats_client.list_pools()['pools']
+        host_name = pools[0]['name']
+        self.do_request('show_backend_capabilities', expected_status=200,
+                        host=host_name)
+
+
+class ProjectMemberTests(ProjectAdminTests, base.BaseVolumeTest):
+
+    credentials = ['project_member', 'project_admin', 'system_admin']
+
+    def test_get_capabilities(self):
+        pools = self.admin_stats_client.list_pools()['pools']
+        host_name = pools[0]['name']
+        self.do_request('show_backend_capabilities',
+                        expected_status=exceptions.Forbidden,
+                        host=host_name)
+
+
+class ProjectReaderTests(ProjectMemberTests, base.BaseVolumeTest):
+
+    credentials = ['project_reader', 'project_admin', 'system_admin']