[Gate Fix] Fix AttributeError in ServerActionsRbacTest

This PS fixes an AttributeError being raised in ServerActionsRbacTest
[0] due to a recent Tempest change [1]. Besides, the volume
creation was being done manually in Patrole, when the volume
should have been created using Tempest's base helper for creating
a volume.

This same issue applies with `test_create_image_volume_backed` in
the same class [2] due to a recent Tempest change [3], and besides
that, the previous way of spinning up a volume-backed server did
not leverage Tempest's helpers, which this PS corrects.

[0] http://logs.openstack.org/06/466806/8/check/gate-tempest-dsvm-patrole-admin-ubuntu-xenial/c186718/console.html#_2017-09-22_01_07_10_242418
[1] https://review.openstack.org/#/c/498888/
[2] http://logs.openstack.org/31/506531/3/check/gate-tempest-dsvm-patrole-member-ubuntu-xenial/01bfbc6/console.html#_2017-09-22_07_08_39_483859
[3] https://review.openstack.org/#/c/498886/

Change-Id: I6f93dc6961844e2154d348790cad3fde77b9d218
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
index aeefebf..51c065c 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_actions_rbac.py
@@ -19,6 +19,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -38,27 +39,11 @@
     @classmethod
     def resource_setup(cls):
         super(ServerActionsRbacTest, cls).resource_setup()
-        # Create test server
         cls.server_id = cls.create_test_server(wait_until='ACTIVE')['id']
         cls.flavor_ref = CONF.compute.flavor_ref
         cls.flavor_ref_alt = CONF.compute.flavor_ref_alt
         cls.image_ref = CONF.compute.image_ref
 
-        # Create a volume
-        volume_name = data_utils.rand_name(cls.__name__ + '-volume')
-        name_field = 'name'
-        if not CONF.volume_feature_enabled.api_v2:
-            name_field = 'display_name'
-
-        params = {name_field: volume_name,
-                  'imageRef': CONF.compute.image_ref,
-                  'size': CONF.volume.volume_size}
-        volume = cls.volumes_client.create_volume(**params)['volume']
-        waiters.wait_for_volume_resource_status(cls.volumes_client,
-                                                volume['id'], 'available')
-        cls.volumes.append(volume)
-        cls.volume_id = volume['id']
-
     def setUp(self):
         super(ServerActionsRbacTest, self).setUp()
         try:
@@ -73,57 +58,6 @@
             # Rebuilding the server in case something happened during a test
             self.__class__.server_id = self.rebuild_server(self.server_id)
 
-    @classmethod
-    def resource_cleanup(cls):
-        # If a test case creates an image from a server that is created with
-        # a volume, a volume snapshot will automatically be created by default.
-        # We need to delete the volume snapshot.
-        try:
-            body = cls.snapshots_extensions_client.list_snapshots()
-            volume_snapshots = body['snapshots']
-        except Exception:
-            LOG.info("Cannot retrieve snapshots for cleanup.")
-        else:
-            for snapshot in volume_snapshots:
-                if snapshot['volumeId'] == cls.volume_id:
-                    # Wait for snapshot status to become 'available' before
-                    # deletion
-                    waiters.wait_for_volume_resource_status(
-                        cls.snapshots_extensions_client, snapshot['id'],
-                        'available')
-                    cls.snapshots_extensions_client.delete_snapshot(
-                        snapshot['id'])
-
-            for snapshot in volume_snapshots:
-                if snapshot['volumeId'] == cls.volume_id:
-                    cls.snapshots_extensions_client.wait_for_resource_deletion(
-                        snapshot['id'])
-
-        super(ServerActionsRbacTest, cls).resource_cleanup()
-
-    def _create_test_server_with_volume(self, volume_id):
-        # Create a server with the volume created earlier
-        server_name = data_utils.rand_name(self.__class__.__name__ + "-server")
-        bd_map_v2 = [{'uuid': volume_id,
-                      'source_type': 'volume',
-                      'destination_type': 'volume',
-                      'boot_index': 0,
-                      'delete_on_termination': True}]
-        device_mapping = {'block_device_mapping_v2': bd_map_v2}
-
-        # Since the server is booted from volume, the imageRef does not need
-        # to be specified.
-        server = self.servers_client.create_server(
-            name=server_name, imageRef='',
-            flavorRef=CONF.compute.flavor_ref,
-            **device_mapping)['server']
-
-        waiters.wait_for_server_status(
-            self.os_admin.servers_client, server['id'], 'ACTIVE')
-
-        self.servers.append(server)
-        return server
-
     def _test_start_server(self):
         self.servers_client.start_server(self.server_id)
         waiters.wait_for_server_status(
@@ -275,21 +209,30 @@
         self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
         # This function will also call show image
-        self.create_image_from_server(self.server_id,
-                                      wait_until='ACTIVE')
+        self.create_image_from_server(self.server_id, wait_until='ACTIVE')
 
     @test.services('image', 'volume')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:servers:create_image:allow_volume_backed")
     @decorators.idempotent_id('8b869f73-49b3-4cc4-a0ce-ef64f8e1d6f9')
-    def test_create_image_volume_backed(self):
-        server = self._create_test_server_with_volume(self.volume_id)
+    def test_create_image_from_volume_backed_server(self):
+        # volume_backed=True creates a volume and create server will be
+        # requested with 'block_device_mapping_v2' with necessary values for
+        # this test.
+        server = self.create_test_server(volume_backed=True,
+                                         wait_until='ACTIVE')
         self.rbac_utils.switch_role(self, toggle_rbac_role=True)
 
-        # This function will also call show image
-        self.create_image_from_server(server['id'],
-                                      wait_until='ACTIVE')
+        # This function will also call show image.
+        image = self.create_image_from_server(server['id'],
+                                              wait_until='ACTIVE',
+                                              wait_for_server=False)
+        self.addCleanup(self.compute_images_client.wait_for_resource_deletion,
+                        image['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.compute_images_client.delete_image, image['id'])
 
 
 class ServerActionsV214RbacTest(rbac_base.BaseV2ComputeRbacTest):
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py
index 35ca437..5248023 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_rbac.py
@@ -18,6 +18,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
@@ -98,8 +99,16 @@
 
         self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         # Use image_id='' to avoid using the default image in tempest.conf.
-        self.create_test_server(name=server_name, image_id='',
-                                **device_mapping)
+        server = self.create_test_server(name=server_name, image_id='',
+                                         **device_mapping)
+        # Delete the server and wait for the volume to become available to
+        # avoid clean up errors.
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        waiters.wait_for_volume_resource_status,
+                        self.volumes_client, volume_id, 'available')
+        self.addCleanup(waiters.wait_for_server_termination,
+                        self.servers_client, server['id'])
+        self.addCleanup(self.delete_server, server['id'])
 
     @test.services('network')
     @rbac_rule_validation.action(
diff --git a/patrole_tempest_plugin/tests/api/identity/rbac_base.py b/patrole_tempest_plugin/tests/api/identity/rbac_base.py
index 51daf96..8273022 100644
--- a/patrole_tempest_plugin/tests/api/identity/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/rbac_base.py
@@ -26,23 +26,23 @@
 LOG = logging.getLogger(__name__)
 
 
-class BaseIdentityV2RbacTest(base.BaseIdentityV2Test):
+class BaseIdentityRbacTest(base.BaseIdentityTest):
 
     @classmethod
     def skip_checks(cls):
-        super(BaseIdentityV2RbacTest, cls).skip_checks()
+        super(BaseIdentityRbacTest, cls).skip_checks()
         if not CONF.patrole.enable_rbac:
             raise cls.skipException(
                 "%s skipped as RBAC testing not enabled" % cls.__name__)
 
     @classmethod
     def setup_clients(cls):
-        super(BaseIdentityV2RbacTest, cls).setup_clients()
+        super(BaseIdentityRbacTest, cls).setup_clients()
         cls.rbac_utils = rbac_utils.RbacUtils(cls)
 
     @classmethod
     def resource_setup(cls):
-        super(BaseIdentityV2RbacTest, cls).resource_setup()
+        super(BaseIdentityRbacTest, cls).resource_setup()
         cls.endpoints = []
         cls.roles = []
         cls.services = []
@@ -66,7 +66,7 @@
             test_utils.call_and_ignore_notfound_exc(
                 cls.users_client.delete_user, user['id'])
 
-        super(BaseIdentityV2RbacTest, cls).resource_cleanup()
+        super(BaseIdentityRbacTest, cls).resource_cleanup()
 
     @classmethod
     def setup_test_endpoint(cls, service=None):
@@ -87,10 +87,6 @@
             params['publicurl'] = url
         elif cls.identity_version == 'v3':
             params['url'] = url
-        else:
-            LOG.debug("Keystone version is invalid."
-                      " Please enter a valid version number.")
-            raise KeyError
 
         endpoint = cls.endpoints_client.create_endpoint(**params)['endpoint']
         cls.endpoints.append(endpoint)
@@ -122,10 +118,6 @@
             service = service['OS-KSADM:service']
         elif cls.identity_version == 'v3':
             service = service['service']
-        else:
-            LOG.debug("Keystone version is invalid."
-                      " Please enter a valid version number.")
-            raise KeyError
 
         cls.services.append(service)
 
@@ -147,7 +139,7 @@
         return user
 
 
-class BaseIdentityV2AdminRbacTest(BaseIdentityV2RbacTest):
+class BaseIdentityV2AdminRbacTest(BaseIdentityRbacTest):
     """Base test class for the Identity v2 admin API.
 
     Keystone's v2 API is split into two APIs: an admin and non-admin API. RBAC
@@ -156,6 +148,8 @@
     request object has ``context_is_admin``. For more details, see the
     implementation of ``assert_admin`` in ``keystone.common.wsgi``.
     """
+    identity_version = 'v2'
+    credentials = ['primary']
 
     @classmethod
     def skip_checks(cls):
@@ -213,9 +207,10 @@
         return token_id
 
 
-class BaseIdentityV3RbacTest(BaseIdentityV2RbacTest):
+class BaseIdentityV3RbacTest(BaseIdentityRbacTest):
 
     identity_version = 'v3'
+    credentials = ['primary']
 
     @classmethod
     def setup_clients(cls):