Add check on role availability before request creds by roles

This commit adds a new method to the cred_provider abstract class,
is_role_available(), which will return true if the provider can provide
creds with the request roles, or false if it can't. This method is then
used before any calls to get_creds_by_roles() to definitively check
whether the test is expected to be able to be executed.

Closes-Bug: #1429322
Change-Id: I00f61007b2b0605c07ac77773151562c5cf6ce85
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 42062e7..f75f4c8 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -32,22 +32,23 @@
         if not CONF.service_available.swift:
             skip_msg = ("%s skipped as swift is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
-        if not CONF.auth.allow_tenant_isolation and \
-            not CONF.auth.locking_credentials_provider:
-            skip_msg = ("%s skipped because a credential provider able to "
-                        "provide credentials by role is needed" % cls.__name__)
-            raise cls.skipException(skip_msg)
 
     @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
         super(BaseObjectTest, cls).setup_credentials()
-
         cls.isolated_creds = credentials.get_isolated_credentials(
             cls.__name__, network_resources=cls.network_resources)
-        # Get isolated creds for normal user
-        cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
-            [CONF.object_storage.operator_role]))
+        operator_role = CONF.object_storage.operator_role
+        if not cls.isolated_creds.is_role_available(operator_role):
+            skip_msg = ("%s skipped because the configured credential provider"
+                        " is not able to provide credentials with the %s role "
+                        "assigned." % (cls.__name__, operator_role))
+            raise cls.skipException(skip_msg)
+        else:
+            # Get isolated creds for normal user
+            cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
+                [operator_role]))
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 0c7e991..74bc519 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -26,9 +26,16 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountQuotasTest, cls).setup_credentials()
-        cls.os_reselleradmin = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.reseller_admin_role]))
+        reseller_admin_role = CONF.object_storage.reseller_admin_role
+        if not cls.isolated_creds.is_role_available(reseller_admin_role):
+            skip_msg = ("%s skipped because the configured credential provider"
+                        " is not able to provide credentials with the %s role "
+                        "assigned." % (cls.__name__, reseller_admin_role))
+            raise cls.skipException(skip_msg)
+        else:
+            cls.os_reselleradmin = clients.Manager(
+                cls.isolated_creds.get_creds_by_roles(
+                    roles=[reseller_admin_role]))
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index d1e8f77..cfcdae4 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -29,9 +29,16 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountQuotasNegativeTest, cls).setup_credentials()
-        cls.os_reselleradmin = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.reseller_admin_role]))
+        reseller_admin_role = CONF.object_storage.reseller_admin_role
+        if not cls.isolated_creds.is_role_available(reseller_admin_role):
+            skip_msg = ("%s skipped because the configured credential provider"
+                        " is not able to provide credentials with the %s role "
+                        "assigned." % (cls.__name__, reseller_admin_role))
+            raise cls.skipException(skip_msg)
+        else:
+            cls.os_reselleradmin = clients.Manager(
+                cls.isolated_creds.get_creds_by_roles(
+                    roles=[reseller_admin_role]))
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 89de69b..8766e7d 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -236,10 +236,16 @@
     def get_admin_creds(self):
         return self.get_creds_by_roles([CONF.identity.admin_role])
 
-    def admin_available(self):
-        if not self.hash_dict['roles'].get(CONF.identity.admin_role):
+    def is_role_available(self, role):
+        if self.use_default_creds:
             return False
-        return True
+        else:
+            if self.hash_dict['roles'].get(role):
+                return True
+            return False
+
+    def admin_available(self):
+        return self.is_role_available(CONF.identity.admin_role)
 
 
 class NotLockingAccounts(Accounts):
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index c22dc1f..ea628f6 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -117,3 +117,7 @@
     @abc.abstractmethod
     def get_creds_by_roles(self, roles, force_new=False):
         return
+
+    @abc.abstractmethod
+    def is_role_available(self, role):
+        return
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index b36dd46..72a3183 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -387,3 +387,6 @@
 
     def is_multi_tenant(self):
         return True
+
+    def is_role_available(self, role):
+        return True
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7f0582a..45c7ddd 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -1372,9 +1372,16 @@
             raise cls.skipException(skip_msg)
         cls.set_network_resources()
         super(SwiftScenarioTest, cls).resource_setup()
-        cls.os_operator = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                [CONF.object_storage.operator_role]))
+        operator_role = CONF.object_storage.operator_role
+        if not cls.isolated_creds.is_role_available(operator_role):
+            skip_msg = ("%s skipped because the configured credential provider"
+                        " is not able to provide credentials with the %s role "
+                        "assigned." % (cls.__name__, operator_role))
+            raise cls.skipException(skip_msg)
+        else:
+            cls.os_operator = clients.Manager(
+                cls.isolated_creds.get_creds_by_roles(
+                    [operator_role]))
         # Clients for Swift
         cls.account_client = cls.os_operator.account_client
         cls.container_client = cls.os_operator.container_client