Merge "Fix doc issue of lock test accounts"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 4418b9d..3f9e70e 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -45,9 +45,9 @@
 
 # (Optional) Enables or disables syslog rfc5424 format for logging. If
 # enabled, prefixes the MSG part of the syslog message with APP-NAME
-# (RFC5424). The format without the APP-NAME is deprecated in I, and
-# will be removed in J. (boolean value)
-#use_syslog_rfc_format = false
+# (RFC5424). The format without the APP-NAME is deprecated in K, and
+# will be removed in L, along with this option. (boolean value)
+#use_syslog_rfc_format = true
 
 # Syslog facility to receive log lines. (string value)
 #syslog_log_facility = LOG_USER
@@ -240,9 +240,6 @@
 # value)
 #build_timeout = 300
 
-# Should the tests ssh to instances? (boolean value)
-#run_ssh = false
-
 # Auth method used for authenticate to the instance. Valid choices
 # are: keypair, configured, adminpass and disabled. Keypair: start the
 # servers with a ssh keypair. Configured: use the configured user and
@@ -289,7 +286,7 @@
 #fixed_network_name = <None>
 
 # Network used for SSH connections. Ignored if
-# use_floatingip_for_ssh=true or run_ssh=false. (string value)
+# use_floatingip_for_ssh=true or run_validation=false. (string value)
 #network_for_ssh = public
 
 # IP version used for SSH connections. (integer value)
@@ -1071,6 +1068,11 @@
 # From tempest.config
 #
 
+# Enable ssh on created servers and creation of additional validation
+# resources to enable remote access (boolean value)
+# Deprecated group/name - [compute]/run_ssh
+#run_validation = false
+
 # Default IP type used for validation: -fixed: uses the first IP
 # belonging to the fixed network -floating: creates and uses a
 # floating IP (string value)
diff --git a/requirements.txt b/requirements.txt
index 3a32b69..7fe8858 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-pbr>=0.6,!=0.7,<1.0
+pbr>=0.11,<2.0
 anyjson>=0.3.3
 httplib2>=0.7.5
 jsonschema>=2.0.0,<3.0.0
@@ -11,12 +11,12 @@
 netaddr>=0.7.12
 testrepository>=0.0.18
 pyOpenSSL>=0.11
-oslo.concurrency>=1.8.0,<1.9.0         # Apache-2.0
-oslo.config>=1.9.3,<1.10.0  # Apache-2.0
-oslo.i18n>=1.5.0,<1.6.0  # Apache-2.0
-oslo.log>=1.0.0,<1.1.0  # Apache-2.0
-oslo.serialization>=1.4.0,<1.5.0               # Apache-2.0
-oslo.utils>=1.4.0,<1.5.0                       # Apache-2.0
+oslo.concurrency>=1.8.0         # Apache-2.0
+oslo.config>=1.11.0  # Apache-2.0
+oslo.i18n>=1.5.0  # Apache-2.0
+oslo.log>=1.0.0  # Apache-2.0
+oslo.serialization>=1.4.0               # Apache-2.0
+oslo.utils>=1.4.0                       # Apache-2.0
 six>=1.9.0
 iso8601>=0.1.9
 fixtures>=0.3.14
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 26d6661..c4581e5 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -52,7 +52,6 @@
     def setup_credentials(cls):
         cls.set_network_resources()
         super(BaseComputeTest, cls).setup_credentials()
-        cls.multi_user = cls.check_multi_user()
 
     @classmethod
     def setup_clients(cls):
@@ -112,14 +111,6 @@
         super(BaseComputeTest, cls).resource_cleanup()
 
     @classmethod
-    def check_multi_user(cls):
-        # We have a list of accounts now, so just checking if the list is gt 2
-        if not cls.isolated_creds.is_multi_user():
-            msg = "Not enough users available for multi-user testing"
-            raise exceptions.InvalidConfiguration(msg)
-        return True
-
-    @classmethod
     def clear_servers(cls):
         LOG.debug('Clearing servers: %s', ','.join(
             server['id'] for server in cls.servers))
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 3b9e4b5..9012d3d 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -95,7 +95,7 @@
         self.assertTrue(found)
 
     @test.idempotent_id('cbc0f52f-05aa-492b-bdc1-84b575ca294b')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_vcpus(self):
         # Verify that the number of vcpus reported by the instance matches
@@ -106,7 +106,7 @@
         self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
 
     @test.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_host_name_is_same_as_server_name(self):
         # Verify the instance host name is the same as the server name
@@ -206,7 +206,7 @@
         cls.client = cls.servers_client
 
     @test.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_ephemeral_disk(self):
         # Verify that the ephemeral disk is created when creating server
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index dbfdbdb..c4cabaa 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -33,7 +33,7 @@
 
 
 class ServerActionsTestJSON(base.BaseV2ComputeTest):
-    run_ssh = CONF.compute.run_ssh
+    run_ssh = CONF.validation.run_validation
 
     def setUp(self):
         # NOTE(afazekas): Normally we use the same server with all test cases,
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index 258ff1f..9f007bf 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -92,9 +92,11 @@
 
     @classmethod
     def resource_cleanup(cls):
-        if cls.multi_user:
+        if hasattr(cls, 'image'):
             cls.images_client.delete_image(cls.image['id'])
+        if hasattr(cls, 'keypairname'):
             cls.keypairs_client.delete_keypair(cls.keypairname)
+        if hasattr(cls, 'security_group'):
             cls.security_client.delete_security_group(cls.security_group['id'])
         super(AuthorizationTestJSON, cls).resource_cleanup()
 
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 7f345ae..580fb84 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -85,7 +85,8 @@
         self.addCleanup(self._detach, self.server['id'], self.volume['id'])
 
     @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
-    @testtools.skipUnless(CONF.compute.run_ssh, 'SSH required for this test')
+    @testtools.skipUnless(CONF.validation.run_validation,
+                          'SSH required for this test')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 2ddc3fc..34ac860 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -116,20 +116,6 @@
         return resp, body
 
     @classmethod
-    def get_single_message(cls, message_uri):
-        """Wrapper utility that gets a single message."""
-        resp, body = cls.client.show_single_message(message_uri)
-
-        return resp, body
-
-    @classmethod
-    def get_multiple_messages(cls, message_uri):
-        """Wrapper utility that gets multiple messages."""
-        resp, body = cls.client.show_multiple_messages(message_uri)
-
-        return resp, body
-
-    @classmethod
     def delete_messages(cls, message_uri):
         """Wrapper utility that deletes messages."""
         resp, body = cls.client.delete_messages(message_uri)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 8bc9b12..0c7fa6b 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -15,8 +15,6 @@
 
 from tempest_lib import exceptions as lib_exc
 
-from tempest import clients
-from tempest.common import credentials
 from tempest.common import custom_matchers
 from tempest import config
 import tempest.test
@@ -38,19 +36,7 @@
         cls.set_network_resources()
         super(BaseObjectTest, cls).setup_credentials()
         operator_role = CONF.object_storage.operator_role
-        # There are no credentials by type used by object storage tests so
-        # isolated_creds must still be initialized
-        cls.isolated_creds = credentials.get_isolated_credentials(
-            cls.__name__, network_resources=cls.network_resources)
-        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]))
+        cls.os = cls.get_client_manager(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 364d6e1..04bfee4 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -15,7 +15,6 @@
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -28,15 +27,8 @@
     def setup_credentials(cls):
         super(AccountQuotasTest, cls).setup_credentials()
         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]))
+        cls.os_reselleradmin = cls.get_client_manager(
+            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 b32943c..a11b407 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -17,7 +17,6 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -30,15 +29,8 @@
     def setup_credentials(cls):
         super(AccountQuotasNegativeTest, cls).setup_credentials()
         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]))
+        cls.os_reselleradmin = cls.get_client_manager(
+            roles=[reseller_admin_role])
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 918bd5a..c28a3e0 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -20,7 +20,6 @@
 import testtools
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest.common import custom_matchers
 from tempest import config
 from tempest import test
@@ -35,9 +34,8 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountTest, cls).setup_credentials()
-        cls.os_operator = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.operator_role], force_new=True))
+        cls.os_operator = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index feccf18..dfc5dfa 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -15,7 +15,6 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -27,9 +26,8 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountNegativeTest, cls).setup_credentials()
-        cls.os_operator = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.operator_role], force_new=True))
+        cls.os_operator = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 1003f82..25dac6b 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -16,7 +16,6 @@
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -28,9 +27,8 @@
     @classmethod
     def setup_credentials(cls):
         super(ObjectTestACLs, cls).setup_credentials()
-        cls.os_operator = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.operator_role], force_new=True))
+        cls.os_operator = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 2c6d3cc..31c301a 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -16,7 +16,6 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -28,9 +27,8 @@
     @classmethod
     def setup_credentials(cls):
         super(ObjectACLsNegativeTest, cls).setup_credentials()
-        cls.os_operator = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.operator_role], force_new=True))
+        cls.os_operator = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 53bcfa6..4c0723d 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -22,7 +22,6 @@
 
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest import config
 from tempest import test
 
@@ -41,8 +40,8 @@
     @classmethod
     def setup_credentials(cls):
         super(ContainerSyncTest, cls).setup_credentials()
-        cls.os_alt = clients.Manager(cls.isolated_creds.get_creds_by_roles(
-            [CONF.object_storage.operator_role], force_new=True))
+        cls.os_alt = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 8075e91..b02f178 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -24,7 +24,6 @@
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest.common import custom_matchers
 from tempest import config
 from tempest import test
@@ -993,9 +992,8 @@
     @classmethod
     def setup_credentials(cls):
         super(PublicObjectTest, cls).setup_credentials()
-        cls.os_alt = clients.Manager(
-            cls.isolated_creds.get_creds_by_roles(
-                roles=[CONF.object_storage.operator_role], force_new=True))
+        cls.os_alt = cls.get_client_manager(
+            roles=[CONF.object_storage.operator_role], force_new=True)
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 35f51b9..af97794 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -17,7 +17,6 @@
 from tempest_lib import exceptions as lib_exc
 import yaml
 
-from tempest import clients
 from tempest import config
 import tempest.test
 
@@ -41,14 +40,7 @@
     def setup_credentials(cls):
         super(BaseOrchestrationTest, cls).setup_credentials()
         stack_owner_role = CONF.orchestration.stack_owner_role
-        if not cls.isolated_creds.is_role_available(stack_owner_role):
-            skip_msg = ("%s skipped because the configured credential provider"
-                        " is not able to provide credentials with the %s role "
-                        "assigned." % (cls.__name__, stack_owner_role))
-            raise cls.skipException(skip_msg)
-        else:
-            cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
-                [stack_owner_role]))
+        cls.os = cls.get_client_manager(roles=[stack_owner_role])
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 70a8594..f51d9aa 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -94,7 +94,7 @@
         versions = map(lambda x: x['id'], body['versions']['values'])
     else:
         versions = map(lambda x: x['id'], body['versions'])
-    return versions
+    return list(versions)
 
 
 def verify_keystone_api_versions(os, update):
@@ -175,6 +175,7 @@
 
     else:
         extensions = map(lambda x: x['alias'], resp)
+    extensions = list(extensions)
     if not results.get(service):
         results[service] = {}
     extensions_opt = get_enabled_extensions(service)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 1f85872..fee1467 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -413,7 +413,7 @@
         if not self.isolated_creds:
             return
         self._clear_isolated_net_resources()
-        for creds in self.isolated_creds.itervalues():
+        for creds in six.itervalues(self.isolated_creds):
             try:
                 self.creds_client.delete_user(creds.user_id)
             except lib_exc.NotFound:
diff --git a/tempest/config.py b/tempest/config.py
index a711b33..3f3e7e7 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -195,9 +195,6 @@
                help="Timeout in seconds to wait for an instance to build. "
                     "Other services that do not define build_timeout will "
                     "inherit this value."),
-    cfg.BoolOpt('run_ssh',
-                default=False,
-                help="Should the tests ssh to instances?"),
     cfg.StrOpt('ssh_auth_method',
                default='keypair',
                help="Auth method used for authenticate to the instance. "
@@ -249,7 +246,7 @@
     cfg.StrOpt('network_for_ssh',
                default='public',
                help="Network used for SSH connections. Ignored if "
-                    "use_floatingip_for_ssh=true or run_ssh=false."),
+                    "use_floatingip_for_ssh=true or run_validation=false."),
     cfg.IntOpt('ip_version_for_ssh',
                default=4,
                help="IP version used for SSH connections."),
@@ -558,6 +555,12 @@
                                 title='SSH Validation options')
 
 ValidationGroup = [
+    cfg.BoolOpt('run_validation',
+                default=False,
+                help='Enable ssh on created servers and creation of additional'
+                     ' validation resources to enable remote access',
+                deprecated_opts=[cfg.DeprecatedOpt('run_ssh',
+                                                   group='compute')]),
     cfg.StrOpt('connect_method',
                default='floating',
                choices=['fixed', 'floating'],
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7e0c3b3..50aa261 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -22,7 +22,6 @@
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
-from tempest import clients
 from tempest.common import fixed_network
 from tempest.common.utils.linux import remote_client
 from tempest import config
@@ -1341,15 +1340,7 @@
         cls.set_network_resources()
         super(SwiftScenarioTest, cls).setup_credentials()
         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]))
+        cls.os_operator = cls.get_client_manager(roles=[operator_role])
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index a73ae1c..8ec10c7 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -440,7 +440,7 @@
     @test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
     @test.services('compute', 'network')
     def test_cross_tenant_traffic(self):
-        if not self.isolated_creds.is_multi_tenant():
+        if not self.credentials_provider.is_multi_tenant():
             raise self.skipException("No secondary tenant defined")
         try:
             # deploy new tenant
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index f44fd5e..b795775 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -56,7 +56,7 @@
                     image=self.image_ref, flavor=self.flavor_ref
                 )
             )
-        self.run_ssh = CONF.compute.run_ssh and \
+        self.run_ssh = CONF.validation.run_validation and \
             self.image_utils.is_sshable_image(self.image_ref)
         self.ssh_user = self.image_utils.ssh_user(self.image_ref)
         LOG.debug('Starting test for i:{image}, f:{flavor}. '
diff --git a/tempest/test.py b/tempest/test.py
index 2d5e94a..d80e478 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -267,7 +267,7 @@
                      etype, cls.__name__))
             cls.tearDownClass()
             try:
-                raise etype, value, trace
+                six.reraise(etype, value, trace)
             finally:
                 del trace  # to avoid circular refs
 
@@ -305,7 +305,7 @@
         # the first one
         if re_raise and etype is not None:
             try:
-                raise etype, value, trace
+                six.reraise(etype, value, trace)
             finally:
                 del trace  # to avoid circular refs
 
@@ -414,39 +414,80 @@
                                                    format=self.log_format,
                                                    level=None))
 
-    @classmethod
-    def get_client_manager(cls, identity_version=None,
-                           credential_type='primary'):
-        """
-        Returns an OpenStack client manager
-        """
-        force_tenant_isolation = getattr(cls, 'force_tenant_isolation', None)
-        identity_version = identity_version or CONF.identity.auth_version
+    @property
+    def credentials_provider(self):
+        return self._get_credentials_provider()
 
-        if (not hasattr(cls, 'isolated_creds') or
-            not cls.isolated_creds.name == cls.__name__):
-            cls.isolated_creds = credentials.get_isolated_credentials(
+    @classmethod
+    def _get_credentials_provider(cls):
+        """Returns a credentials provider
+
+        If no credential provider exists yet creates one.
+        It uses self.identity_version if defined, or the configuration value
+        """
+        if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
+                not cls._creds_provider.name == cls.__name__):
+            force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
+                                             False)
+            identity_version = getattr(cls, 'identity_version', None)
+            identity_version = identity_version or CONF.identity.auth_version
+
+            cls._creds_provider = credentials.get_isolated_credentials(
                 name=cls.__name__, network_resources=cls.network_resources,
                 force_tenant_isolation=force_tenant_isolation,
-                identity_version=identity_version
-            )
+                identity_version=identity_version)
+        return cls._creds_provider
 
-        credentials_method = 'get_%s_creds' % credential_type
-        if hasattr(cls.isolated_creds, credentials_method):
-            creds = getattr(cls.isolated_creds, credentials_method)()
+    @classmethod
+    def get_client_manager(cls, identity_version=None,
+                           credential_type=None, roles=None, force_new=None):
+        """Returns an OpenStack client manager
+
+        Returns an OpenStack client manager based on either credential_type
+        or a list of roles. If neither is specified, it defaults to
+        credential_type 'primary'
+        :param identity_version: string - v2 or v3
+        :param credential_type: string - primary, alt or admin
+        :param roles: list of roles
+
+        :returns the created client manager
+        :raises skipException: if the requested credentials are not available
+        """
+        if all([roles, credential_type]):
+            msg = "Cannot get credentials by type and roles at the same time"
+            raise ValueError(msg)
+        if not any([roles, credential_type]):
+            credential_type = 'primary'
+        cls.identity_version = identity_version
+        cred_provider = cls._get_credentials_provider()
+        if roles:
+            for role in roles:
+                if not cred_provider.is_role_available(role):
+                    skip_msg = (
+                        "%s skipped because the configured credential provider"
+                        " is not able to provide credentials with the %s role "
+                        "assigned." % (cls.__name__, role))
+                    raise cls.skipException(skip_msg)
+            params = dict(roles=roles)
+            if force_new is not None:
+                params.update(force_new=force_new)
+            creds = cred_provider.get_creds_by_roles(**params)
         else:
-            raise exceptions.InvalidCredentials(
-                "Invalid credentials type %s" % credential_type)
-        os = clients.Manager(credentials=creds, service=cls._service)
-        return os
+            credentials_method = 'get_%s_creds' % credential_type
+            if hasattr(cred_provider, credentials_method):
+                creds = getattr(cred_provider, credentials_method)()
+            else:
+                raise exceptions.InvalidCredentials(
+                    "Invalid credentials type %s" % credential_type)
+        return clients.Manager(credentials=creds, service=cls._service)
 
     @classmethod
     def clear_isolated_creds(cls):
         """
         Clears isolated creds if set
         """
-        if hasattr(cls, 'isolated_creds'):
-            cls.isolated_creds.clear_isolated_creds()
+        if hasattr(cls, '_cred_provider'):
+            cls._creds_provider.clear_isolated_creds()
 
     @classmethod
     def set_validation_resources(cls, keypair=None, floating_ip=None,
@@ -464,6 +505,8 @@
         @param security_group_rules
         @param floating_ip
         """
+        if not CONF.validation.run_validation:
+            return
         if keypair is None:
             if CONF.validation.auth_method.lower() == "keypair":
                 keypair = True
@@ -514,16 +557,16 @@
         """
         # Make sure isolated_creds exists and get a network client
         networks_client = cls.get_client_manager().networks_client
-        isolated_creds = getattr(cls, 'isolated_creds', None)
+        cred_provider = cls._get_credentials_provider()
         # In case of nova network, isolated tenants are not able to list the
         # network configured in fixed_network_name, even if the can use it
         # for their servers, so using an admin network client to validate
         # the network name
         if (not CONF.service_available.neutron and
                 credentials.is_admin_available()):
-            admin_creds = isolated_creds.get_admin_creds()
+            admin_creds = cred_provider.get_admin_creds()
             networks_client = clients.Manager(admin_creds).networks_client
-        return fixed_network.get_tenant_network(isolated_creds,
+        return fixed_network.get_tenant_network(cred_provider,
                                                 networks_client)
 
     def assertEmpty(self, list, msg=None):
@@ -673,7 +716,7 @@
                 msg = ("Missing Identity Admin API credentials in"
                        "configuration.")
                 raise self.skipException(msg)
-            creds = self.isolated_creds.get_admin_creds()
+            creds = self.credentials_provider.get_admin_creds()
             os_adm = clients.Manager(credentials=creds)
             client = os_adm.negative_client
         else:
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py
index 87c4bb3..596e811 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_accounts.py
@@ -107,7 +107,8 @@
     def test_create_hash_file_previous_file(self):
         # Emulate the lock existing on the filesystem
         self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
-        with mock.patch('__builtin__.open', mock.mock_open(), create=True):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True):
             test_account_class = accounts.Accounts('v2', 'test_name')
             res = test_account_class._create_hash_file('12345')
         self.assertFalse(res, "_create_hash_file should return False if the "
@@ -116,7 +117,8 @@
     def test_create_hash_file_no_previous_file(self):
         # Emulate the lock not existing on the filesystem
         self.useFixture(mockpatch.Patch('os.path.isfile', return_value=False))
-        with mock.patch('__builtin__.open', mock.mock_open(), create=True):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True):
             test_account_class = accounts.Accounts('v2', 'test_name')
             res = test_account_class._create_hash_file('12345')
         self.assertTrue(res, "_create_hash_file should return True if the "
@@ -130,7 +132,7 @@
         mkdir_mock = self.useFixture(mockpatch.Patch('os.mkdir'))
         self.useFixture(mockpatch.Patch('os.path.isfile', return_value=False))
         test_account_class = accounts.Accounts('v2', 'test_name')
-        with mock.patch('__builtin__.open', mock.mock_open(),
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
                         create=True) as open_mock:
             test_account_class._get_free_hash(hash_list)
             lock_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
@@ -149,7 +151,8 @@
         # Emulate all lcoks in list are in use
         self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
         test_account_class = accounts.Accounts('v2', 'test_name')
-        with mock.patch('__builtin__.open', mock.mock_open(), create=True):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True):
             self.assertRaises(exceptions.InvalidConfiguration,
                               test_account_class._get_free_hash, hash_list)
 
@@ -168,7 +171,7 @@
             return True
 
         self.stubs.Set(os.path, 'isfile', _fake_is_file)
-        with mock.patch('__builtin__.open', mock.mock_open(),
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
                         create=True) as open_mock:
             test_account_class._get_free_hash(hash_list)
             lock_path = os.path.join(lockutils.get_lock_path(accounts.CONF),
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index 4e3aa4c..5c69c5e 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo.config import cfg
+from oslo_config import cfg
 from oslotest import mockpatch
 
 from tempest.common import credentials
diff --git a/tempest/tests/common/utils/test_file_utils.py b/tempest/tests/common/utils/test_file_utils.py
index 605e82a..937aefa 100644
--- a/tempest/tests/common/utils/test_file_utils.py
+++ b/tempest/tests/common/utils/test_file_utils.py
@@ -22,7 +22,8 @@
 class TestFileUtils(base.TestCase):
 
     def test_have_effective_read_path(self):
-        with mock.patch('__builtin__.open', mock.mock_open(), create=True):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True):
             result = file_utils.have_effective_read_access('fake_path')
         self.assertTrue(result)
 
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index 3a7b436..16f1ac7 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -33,7 +33,7 @@
         cmd = ' '.join([cmd, param])
         LOG.info("running: '%s'" % cmd)
         cmd_str = cmd
-        cmd = shlex.split(cmd.encode('utf-8'))
+        cmd = shlex.split(cmd)
         result = ''
         result_err = ''
         try:
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index b132f60..7850ee4 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -137,7 +137,7 @@
         resp, body = self.client.raw_request('PUT', '/images', body=req_body)
         self.assertEqual(200, resp.status)
         self.assertEqual('fake_response_body', body.read())
-        httplib.HTTPConnection.send.assert_call_count(req_body.len)
+        httplib.HTTPConnection.send.assert_call_count(req_body.tell())
 
     def test_get_connection_class_for_https(self):
         conn_class = self.client.get_connection_class('https')
diff --git a/tempest/tests/test_list_tests.py b/tempest/tests/test_list_tests.py
index 19e4c9c..38d4c5c 100644
--- a/tempest/tests/test_list_tests.py
+++ b/tempest/tests/test_list_tests.py
@@ -14,6 +14,7 @@
 
 import os
 import re
+import six
 import subprocess
 
 from tempest.tests import base
@@ -32,7 +33,7 @@
         self.assertEqual(0, p.returncode,
                          "test discovery failed, one or more files cause an "
                          "error on import %s" % ids)
-        ids = ids.split('\n')
+        ids = six.text_type(ids).split('\n')
         for test_id in ids:
             if re.match('(\w+\.){3}\w+', test_id):
                 if not test_id.startswith('tempest.'):
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 1eb33a4..47e6abd 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -196,6 +196,7 @@
         # Assert that the role creation is called with the 2 specified roles
         self.assertEqual(len(calls), 2)
         args = map(lambda x: x[1], calls)
+        args = list(args)
         self.assertIn(('1234', '1234', '1234'), args)
         self.assertIn(('1234', '1234', '12345'), args)
         self.assertEqual(role_creds.username, 'fake_role_user')
@@ -237,6 +238,7 @@
         calls = user_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('1234', args)
         self.assertIn('12345', args)
         self.assertIn('123456', args)
@@ -244,6 +246,7 @@
         calls = tenant_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('1234', args)
         self.assertIn('12345', args)
         self.assertIn('123456', args)
@@ -381,6 +384,7 @@
         calls = remove_secgroup_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('v2.0/security-groups/sg-1234', args)
         self.assertIn('v2.0/security-groups/sg-12345', args)
         self.assertIn('v2.0/security-groups/sg-123456', args)
@@ -388,6 +392,7 @@
         calls = remove_router_interface_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1], calls)
+        args = list(args)
         self.assertIn(('1234', '1234'), args)
         self.assertIn(('12345', '12345'), args)
         self.assertIn(('123456', '123456'), args)
@@ -395,6 +400,7 @@
         calls = net_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('1234', args)
         self.assertIn('12345', args)
         self.assertIn('123456', args)
@@ -402,6 +408,7 @@
         calls = subnet_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('1234', args)
         self.assertIn('12345', args)
         self.assertIn('123456', args)
@@ -409,6 +416,7 @@
         calls = router_mock.mock_calls
         self.assertEqual(len(calls), 3)
         args = map(lambda x: x[1][0], calls)
+        args = list(args)
         self.assertIn('1234', args)
         self.assertIn('12345', args)
         self.assertIn('123456', args)
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 4485972..1ff4dee 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -252,9 +252,9 @@
         except exception.BotoServerError as exc:
             error_msg = excMatcher.match(exc)
             if error_msg is not None:
-                raise self.failureException, error_msg
+                raise self.failureException(error_msg)
         else:
-            raise self.failureException, "BotoServerError not raised"
+            raise self.failureException("BotoServerError not raised")
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/test-requirements.txt b/test-requirements.txt
index 76ae521..32f33bc 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,9 +5,9 @@
 # needed for doc build
 sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
 python-subunit>=0.0.18
-oslosphinx>=2.5.0,<2.6.0  # Apache-2.0
+oslosphinx>=2.5.0  # Apache-2.0
 mox>=0.5.3
 mock>=1.0
 coverage>=3.6
-oslotest>=1.5.1,<1.6.0  # Apache-2.0
-stevedore>=1.3.0,<1.4.0  # Apache-2.0
+oslotest>=1.5.1  # Apache-2.0
+stevedore>=1.3.0  # Apache-2.0