Merge "To test bootable flag in a cinder volume"
diff --git a/README.rst b/README.rst
index 94a5352..af24569 100644
--- a/README.rst
+++ b/README.rst
@@ -117,8 +117,8 @@
 Tempest suite.
 
 Alternatively, you can use the run_tests.sh script which will create a venv and
-run the unit tests. There are also the py26, py27, or py33 tox jobs which will
-run the unit tests with the corresponding version of python.
+run the unit tests. There are also the py27 and py34 tox jobs which will run
+the unit tests with the corresponding version of python.
 
 Python 2.6
 ----------
@@ -131,3 +131,16 @@
 on an earlier release with python 2.6 you can easily run Tempest against it
 from a remote system running python 2.7. (or deploy a cloud guest in your cloud
 that has python 2.7)
+
+Python 3.4
+----------
+
+Starting during the Liberty release development cycle work began on enabling
+Tempest to run under both Python 2.7 and Python 3.4. Tempest strives to fully
+support running with Python 3.4. A gating unit test job was added to also run
+Tempest's unit tests under Python 3.4. This means that the Tempest code at
+least imports under Python 3.4 and things that have unit test coverage will
+work on Python 3.4. However, because large parts of Tempest are self verifying
+there might be uncaught issues running on Python 3.4. So until there is a gating
+job which does a full Tempest run using Python 3.4 there isn't any guarantee
+that running Tempest under Python 3.4 is bug free.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index b6e00ce..b434fdc 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -115,6 +115,8 @@
  #. Provide tempest with the location of you accounts.yaml file with the
     test_accounts_file option in the auth section
 
+ #. Set allow_tenant_isolation = False in the auth group
+
 It is worth pointing out that each set of credentials in the accounts.yaml
 should have a unique tenant. This is required to provide proper isolation
 to the tests using the credentials, and failure to do this will likely cause
@@ -140,6 +142,11 @@
  #. alt_password
  #. alt_tenant_name
 
+And in the auth secion:
+
+ #. allow_tenant_isolation = False
+ #. comment out 'test_accounts_file' or keep it as empty
+
 It only makes sense to use it if parallel execution isn't needed, since tempest
 won't be able to properly isolate tests using this. Additionally, using the
 traditional config options for credentials is not able to provide credentials to
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index d7dd5e1..5b15c5e 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/setup.cfg b/setup.cfg
index 2de9f34..3a14bba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -15,6 +15,8 @@
     Programming Language :: Python
     Programming Language :: Python :: 2
     Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.4
 
 [entry_points]
 console_scripts =
@@ -22,6 +24,7 @@
     javelin2 = tempest.cmd.javelin:main
     run-tempest-stress = tempest.cmd.run_stress:main
     tempest-cleanup = tempest.cmd.cleanup:main
+    tempest-account-generator = tempest.cmd.account_generator:main
 
 oslo.config.opts =
     tempest.config = tempest.config:list_opts
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/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 6555b64..54a82e9 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -108,7 +108,7 @@
     def test_delete_image_with_invalid_image_id(self):
         # An image should not be deleted with invalid image id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
-                          '!@$%^&*()')
+                          '!@$^&*()')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('137aef61-39f7-44a1-8ddf-0adf82511701')
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index c62ff89..9012d3d 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -43,6 +43,7 @@
 
     @classmethod
     def resource_setup(cls):
+        cls.set_validation_resources()
         super(ServersTestJSON, cls).resource_setup()
         cls.meta = {'hello': 'world'}
         cls.accessIPv4 = '1.1.1.1'
@@ -94,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
@@ -105,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
@@ -205,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/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index b333122..31078e3 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -64,6 +64,7 @@
 
         key_name = data_utils.rand_name('key')
         self.keypairs_client.create_keypair(key_name)
+        self.addCleanup(self.keypairs_client.delete_keypair, key_name)
         self.keypairs_client.list_keypairs()
         server = self.create_test_server(key_name=key_name)
         self.client.wait_for_server_status(server['id'], 'ACTIVE')
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/identity/base.py b/tempest/api/identity/base.py
index 5d66b9c..878ff6d 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -66,16 +66,9 @@
 
     credentials = ['primary']
 
-    @classmethod
-    def setup_credentials(cls):
-        super(BaseIdentityV2Test, cls).setup_credentials()
-        cls.os = cls.get_client_manager(identity_version='v2')
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseIdentityV2Test, cls).skip_checks()
-        if not CONF.identity_feature_enabled.api_v2:
-            raise cls.skipException("Identity api v2 is not enabled")
+    # identity v2 tests should obtain tokens and create accounts via v2
+    # regardless of the configured CONF.identity.auth_version
+    identity_version = 'v2'
 
     @classmethod
     def setup_clients(cls):
@@ -94,7 +87,7 @@
 
 class BaseIdentityV2AdminTest(BaseIdentityV2Test):
 
-    credentials = ['admin']
+    credentials = ['primary', 'admin']
 
     @classmethod
     def setup_clients(cls):
@@ -117,16 +110,9 @@
 
     credentials = ['primary']
 
-    @classmethod
-    def setup_credentials(cls):
-        super(BaseIdentityV3Test, cls).setup_credentials()
-        cls.os = cls.get_client_manager(identity_version='v3')
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseIdentityV3Test, cls).skip_checks()
-        if not CONF.identity_feature_enabled.api_v3:
-            raise cls.skipException("Identity api v3 is not enabled")
+    # identity v3 tests should obtain tokens and create accounts via v3
+    # regardless of the configured CONF.identity.auth_version
+    identity_version = 'v3'
 
     @classmethod
     def setup_clients(cls):
@@ -146,7 +132,7 @@
 
 class BaseIdentityV3AdminTest(BaseIdentityV3Test):
 
-    credentials = ['admin']
+    credentials = ['primary', 'admin']
 
     @classmethod
     def setup_clients(cls):
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 77defd6..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):
@@ -64,7 +62,6 @@
         for container_name in self.containers:
             self.assertIn(container_name, container_list)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('884ec421-fbad-4fcc-916b-0580f2699565')
     def test_list_no_containers(self):
         # List request to empty account
@@ -93,7 +90,6 @@
 
         self.assertEqual(len(container_list), 0)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('1c7efa35-e8a2-4b0b-b5ff-862c7fd83704')
     def test_list_containers_with_format_json(self):
         # list containers setting format parameter to 'json'
@@ -106,7 +102,6 @@
         self.assertTrue([c['count'] for c in container_list])
         self.assertTrue([c['bytes'] for c in container_list])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('4477b609-1ca6-4d4b-b25d-ad3f01086089')
     def test_list_containers_with_format_xml(self):
         # list containers setting format parameter to 'xml'
@@ -122,7 +117,6 @@
         self.assertEqual(container_list.find(".//count").tag, 'count')
         self.assertEqual(container_list.find(".//bytes").tag, 'bytes')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('6eb04a6a-4860-4e31-ba91-ea3347d76b58')
     @testtools.skipIf(
         not CONF.object_storage_feature_enabled.discoverability,
@@ -132,7 +126,6 @@
 
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5cfa4ab2-4373-48dd-a41f-a532b12b08b2')
     def test_list_containers_with_limit(self):
         # list containers one of them, half of them then all of them
@@ -144,7 +137,6 @@
 
             self.assertEqual(len(container_list), limit)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('638f876d-6a43-482a-bbb3-0840bca101c6')
     def test_list_containers_with_marker(self):
         # list containers using marker param
@@ -165,7 +157,6 @@
 
         self.assertEqual(len(container_list), self.containers_count / 2 - 1)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5ca164e4-7bde-43fa-bafb-913b53b9e786')
     def test_list_containers_with_end_marker(self):
         # list containers using end_marker param
@@ -184,7 +175,6 @@
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count / 2)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('ac8502c2-d4e4-4f68-85a6-40befea2ef5e')
     def test_list_containers_with_marker_and_end_marker(self):
         # list containers combining marker and end_marker param
@@ -195,7 +185,6 @@
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count - 2)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('f7064ae8-dbcc-48da-b594-82feef6ea5af')
     def test_list_containers_with_limit_and_marker(self):
         # list containers combining marker and limit param
@@ -210,7 +199,6 @@
 
             self.assertTrue(len(container_list) <= limit, str(container_list))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('888a3f0e-7214-4806-8e50-5e0c9a69bb5e')
     def test_list_containers_with_limit_and_end_marker(self):
         # list containers combining limit and end_marker param
@@ -223,7 +211,6 @@
         self.assertEqual(len(container_list),
                          min(limit, self.containers_count / 2))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8cf98d9c-e3a0-4e44-971b-c87656fdddbd')
     def test_list_containers_with_limit_and_marker_and_end_marker(self):
         # list containers combining limit, marker and end_marker param
@@ -253,7 +240,6 @@
         self.assertIn('x-account-meta-test-account-meta2', resp)
         self.account_client.delete_account_metadata(metadata)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('b904c2e3-24c2-4dba-ad7d-04e90a761be5')
     def test_list_no_account_metadata(self):
         # list no account metadata
@@ -261,7 +247,6 @@
         self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertNotIn('x-account-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('e2a08b5f-3115-4768-a3ee-d4287acd6c08')
     def test_update_account_metadata_with_create_metadata(self):
         # add metadata to account
@@ -276,7 +261,6 @@
 
         self.account_client.delete_account_metadata(metadata)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('9f60348d-c46f-4465-ae06-d51dbd470953')
     def test_update_account_metadata_with_delete_matadata(self):
         # delete metadata from account
@@ -288,7 +272,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('64fd53f3-adbd-4639-af54-436e4982dbfb')
     def test_update_account_metadata_with_create_matadata_key(self):
         # if the value of metadata is not set, the metadata is not
@@ -300,7 +283,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('d4d884d3-4696-4b85-bc98-4f57c4dd2bf1')
     def test_update_account_metadata_with_delete_matadata_key(self):
         # Although the value of metadata is not set, the feature of
@@ -314,7 +296,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8e5fc073-59b9-42ee-984a-29ed11b2c749')
     def test_update_account_metadata_with_create_and_delete_metadata(self):
         # Send a request adding and deleting metadata requests simultaneously
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 73a976d..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):
@@ -46,7 +44,6 @@
         self.delete_containers([self.container_name])
         super(ObjectTestACLs, self).tearDown()
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a3270f3f-7640-4944-8448-c7ea783ea5b6')
     def test_read_object_with_rights(self):
         # attempt to read object using authorized user
@@ -72,7 +69,6 @@
             self.container_name, object_name)
         self.assertHeaders(resp, 'Object', 'GET')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('aa58bfa5-40d9-4bc3-82b4-d07f4a9e392a')
     def test_write_object_with_rights(self):
         # attempt to write object using authorized user
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_services.py b/tempest/api/object_storage/test_container_services.py
index 9f2adfe..0f107f5 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -55,7 +55,6 @@
         self.containers.append(container_name)
         self.assertHeaders(resp, 'Container', 'PUT')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('49f866ed-d6af-4395-93e7-4187eb56d322')
     def test_create_container_overwrite(self):
         # overwrite container with the same name
@@ -66,7 +65,6 @@
         resp, _ = self.container_client.create_container(container_name)
         self.assertHeaders(resp, 'Container', 'PUT')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c2ac4d59-d0f5-40d5-ba19-0635056d48cd')
     def test_create_container_with_metadata_key(self):
         # create container with the blank value of metadata
@@ -84,7 +82,6 @@
         # in the server
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('e1e8df32-7b22-44e1-aa08-ccfd8d446b58')
     def test_create_container_with_metadata_value(self):
         # create container with metadata value
@@ -103,7 +100,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta'],
                          metadata['test-container-meta'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('24d16451-1c0c-4e4f-b59c-9840a3aba40e')
     def test_create_container_with_remove_metadata_key(self):
         # create container with the blank value of remove metadata
@@ -124,7 +120,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8a21ebad-a5c7-4e29-b428-384edc8cd156')
     def test_create_container_with_remove_metadata_value(self):
         # create container with remove metadata
@@ -143,7 +138,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('95d3a249-b702-4082-a2c4-14bb860cf06a')
     def test_delete_container(self):
         # create a container
@@ -165,7 +159,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('4646ac2d-9bfb-4c7d-a3c5-0f527402b3df')
     def test_list_container_contents_with_no_object(self):
         # get empty container contents list
@@ -176,7 +169,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual('', object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('fe323a32-57b9-4704-a996-2e68f83b09bc')
     def test_list_container_contents_with_delimiter(self):
         # get container contents list using delimiter param
@@ -191,7 +183,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name.split('/')[0], object_list.strip('/\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('55b4fa5c-e12e-4ca9-8fcf-a79afe118522')
     def test_list_container_contents_with_end_marker(self):
         # get container contents list using end_marker param
@@ -205,7 +196,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('196f5034-6ab0-4032-9da9-a937bbb9fba9')
     def test_list_container_contents_with_format_json(self):
         # get container contents list using format_json param
@@ -225,7 +215,6 @@
         self.assertTrue([c['content_type'] for c in object_list])
         self.assertTrue([c['last_modified'] for c in object_list])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('655a53ca-4d15-408c-a377-f4c6dbd0a1fa')
     def test_list_container_contents_with_format_xml(self):
         # get container contents list using format_xml param
@@ -250,7 +239,6 @@
         self.assertEqual(object_list.find(".//last_modified").tag,
                          'last_modified')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('297ec38b-2b61-4ff4-bcd1-7fa055e97b61')
     def test_list_container_contents_with_limit(self):
         # get container contents list using limit param
@@ -264,7 +252,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c31ddc63-2a58-4f6b-b25c-94d2937e6867')
     def test_list_container_contents_with_marker(self):
         # get container contents list using marker param
@@ -278,7 +265,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('58ca6cc9-6af0-408d-aaec-2a6a7b2f0df9')
     def test_list_container_contents_with_path(self):
         # get container contents list using path param
@@ -293,7 +279,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('77e742c7-caf2-4ec9-8aa4-f7d509a3344c')
     def test_list_container_contents_with_prefix(self):
         # get container contents list using prefix param
@@ -325,7 +310,6 @@
         self.assertIn('x-container-meta-name', resp)
         self.assertEqual(resp['x-container-meta-name'], metadata['name'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a2faf936-6b13-4f8d-92a2-c2278355821e')
     def test_list_no_container_metadata(self):
         # HEAD container without metadata
@@ -336,7 +320,6 @@
         self.assertHeaders(resp, 'Container', 'HEAD')
         self.assertNotIn('x-container-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('cf19bc0b-7e16-4a5a-aaed-cb0c2fe8deef')
     def test_update_container_metadata_with_create_and_delete_matadata(self):
         # Send one request of adding and deleting metadata
@@ -360,7 +343,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta2'],
                          metadata_2['test-container-meta2'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('2ae5f295-4bf1-4e04-bfad-21e54b62cec5')
     def test_update_container_metadata_with_create_metadata(self):
         # update container metadata using add metadata
@@ -378,7 +360,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta1'],
                          metadata['test-container-meta1'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('3a5ce7d4-6e4b-47d0-9d87-7cd42c325094')
     def test_update_container_metadata_with_delete_metadata(self):
         # update container metadata using delete metadata
@@ -397,7 +378,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('31f40a5f-6a52-4314-8794-cd89baed3040')
     def test_update_container_metadata_with_create_matadata_key(self):
         # update container metadata with a blenk value of metadata
@@ -413,7 +393,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a2e36378-6f1f-43f4-840a-ffd9cfd61914')
     def test_update_container_metadata_with_delete_metadata_key(self):
         # update container metadata with a blank value of matadata
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 6acd0f2..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
@@ -89,6 +88,7 @@
             for meta_key in not_in_meta:
                 self.assertNotIn('x-object-meta-' + meta_key, resp)
 
+    @test.attr(type='smoke')
     @test.idempotent_id('5b4ce26f-3545-46c9-a2ba-5754358a4c62')
     def test_create_object(self):
         # create object
@@ -385,7 +385,6 @@
             object_name)
         self.assertNotIn('x-object-meta-test-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('f726174b-2ded-4708-bff7-729d12ce1f84')
     def test_update_object_metadata_with_create_and_remove_metadata(self):
         # creation and deletion of metadata with one request
@@ -413,7 +412,6 @@
         self.assertIn('x-object-meta-test-meta2', resp)
         self.assertEqual(resp['x-object-meta-test-meta2'], 'Meta2')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('08854588-6449-4bb7-8cca-f2e1040f5e6f')
     def test_update_object_metadata_with_x_object_manifest(self):
         # update object metadata with x_object_manifest
@@ -460,7 +458,6 @@
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], '')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('9a88dca4-b684-425b-806f-306cd0e57e42')
     def test_update_object_metadata_with_x_remove_object_metakey(self):
         # update object metadata with a blank value of remove metadata
@@ -504,7 +501,6 @@
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('170fb90e-f5c3-4b1f-ae1b-a18810821172')
     def test_list_no_object_metadata(self):
         # get empty list of object metadata
@@ -516,7 +512,6 @@
         self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertNotIn('x-object-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('23a3674c-d6de-46c3-86af-ff92bfc8a3da')
     def test_list_object_metadata_with_x_object_manifest(self):
         # get object metadata with x_object_manifest
@@ -571,7 +566,6 @@
 
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('005f9bf6-e06d-41ec-968e-96c78e0b1d82')
     def test_get_object_with_metadata(self):
         # get object with metadata
@@ -591,7 +585,6 @@
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('05a1890e-7db9-4a6c-90a8-ce998a2bddfa')
     def test_get_object_with_range(self):
         # get object with range
@@ -610,7 +603,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data[rand_num - 3: rand_num])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('11b4515b-7ba7-4ca8-8838-357ded86fc10')
     def test_get_object_with_x_object_manifest(self):
         # get object with x_object_manifest
@@ -654,7 +646,6 @@
 
         self.assertEqual(''.join(data_segments), body)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c05b4013-e4de-47af-be84-e598062b16fc')
     def test_get_object_with_if_match(self):
         # get object with if_match
@@ -675,7 +666,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('be133639-e5d2-4313-9b1f-2d59fc054a16')
     def test_get_object_with_if_modified_since(self):
         # get object with if_modified_since
@@ -718,7 +708,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('0aa1201c-10aa-467a-bee7-63cbdd463152')
     def test_get_object_with_if_unmodified_since(self):
         # get object with if_unmodified_since
@@ -734,7 +723,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('94587078-475f-48f9-a40f-389c246e31cd')
     def test_get_object_with_x_newest(self):
         # get object with x_newest
@@ -748,7 +736,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('1a9ab572-1b66-4981-8c21-416e2a5e6011')
     def test_copy_object_in_same_container(self):
         # create source object
@@ -775,7 +762,6 @@
                                                    dst_object_name)
         self.assertEqual(body, src_data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('2248abba-415d-410b-9c30-22dff9cd6e67')
     def test_copy_object_to_itself(self):
         # change the content type of an existing object
@@ -797,7 +783,6 @@
                                                           object_name)
         self.assertEqual(resp['content-type'], metadata['content-type'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('06f90388-2d0e-40aa-934c-e9a8833e958a')
     def test_copy_object_2d_way(self):
         # create source object
@@ -824,7 +809,6 @@
         # check data
         self._check_copied_obj(dst_object_name, src_data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('aa467252-44f3-472a-b5ae-5b57c3c9c147')
     def test_copy_object_across_containers(self):
         # create a container to use as  asource container
@@ -865,7 +849,6 @@
         self.assertIn(actual_meta_key, resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5a9e2cc6-85b6-46fc-916d-0cbb7a88e5fd')
     def test_copy_object_with_x_fresh_metadata(self):
         # create source object
@@ -886,7 +869,6 @@
         # check that destination object does NOT have any object-meta
         self._check_copied_obj(dst_object_name, data, not_in_meta=["src"])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a28a8b99-e701-4d7e-9d84-3b66f121460b')
     def test_copy_object_with_x_object_metakey(self):
         # create source object
@@ -909,7 +891,6 @@
         # check destination object
         self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('edabedca-24c3-4322-9b70-d6d9f942a074')
     def test_copy_object_with_x_object_meta(self):
         # create source object
@@ -1011,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):
@@ -1029,7 +1009,6 @@
         self.delete_containers([self.container_name])
         super(PublicObjectTest, self).tearDown()
 
-    @test.attr(type='smoke')
     @test.idempotent_id('07c9cf95-c0d4-4b49-b9c8-0ef2c9b27193')
     def test_access_public_container_object_without_using_creds(self):
         # make container public-readable and access an object in it object
@@ -1068,7 +1047,6 @@
 
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('54e2a2fe-42dc-491b-8270-8e4217dd4cdc')
     def test_access_public_object_with_another_user_creds(self):
         # make container public-readable and access an object in it using
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index cd2d3c3..923166a 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -45,7 +45,6 @@
         header_value = resp.get('x-versions-location', 'Missing Header')
         self.assertEqual(header_value, versioned)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a151e158-dcbf-4a1f-a1e7-46cd65895a6f')
     @testtools.skipIf(
         not CONF.object_storage_feature_enabled.object_versioning,
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/clients.py b/tempest/clients.py
index a0c9471..9f6a9bb 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -22,6 +22,7 @@
 from tempest.common import cred_provider
 from tempest.common import negative_rest_client
 from tempest import config
+from tempest import exceptions
 from tempest import manager
 from tempest.services.baremetal.v1.json.baremetal_client import \
     BaremetalClientJSON
@@ -343,11 +344,22 @@
         self.credentials_client = CredentialsClientJSON(self.auth_provider,
                                                         **params)
         # Token clients do not use the catalog. They only need default_params.
-        self.token_client = TokenClientJSON(CONF.identity.uri,
-                                            **self.default_params)
+        # They read auth_url, so they should only be set if the corresponding
+        # API version is marked as enabled
+        if CONF.identity_feature_enabled.api_v2:
+            if CONF.identity.uri:
+                self.token_client = TokenClientJSON(
+                    CONF.identity.uri, **self.default_params)
+            else:
+                msg = 'Identity v2 API enabled, but no identity.uri set'
+                raise exceptions.InvalidConfiguration(msg)
         if CONF.identity_feature_enabled.api_v3:
-            self.token_v3_client = V3TokenClientJSON(CONF.identity.uri_v3,
-                                                     **self.default_params)
+            if CONF.identity.uri_v3:
+                self.token_v3_client = V3TokenClientJSON(
+                    CONF.identity.uri_v3, **self.default_params)
+            else:
+                msg = 'Identity v3 API enabled, but no identity.uri_v3 set'
+                raise exceptions.InvalidConfiguration(msg)
 
     def _set_volume_clients(self):
         params = {
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
new file mode 100755
index 0000000..0a48b8d
--- /dev/null
+++ b/tempest/cmd/account_generator.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+
+# Copyright 2015 Mirantis, Inc.
+#
+# 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 argparse
+import os
+
+from oslo_log import log as logging
+import yaml
+
+from tempest import config
+from tempest import exceptions
+from tempest.services.identity.v2.json import identity_client
+import tempest_lib.auth
+from tempest_lib.common.utils import data_utils
+import tempest_lib.exceptions
+
+LOG = None
+CONF = config.CONF
+
+
+def setup_logging():
+    global LOG
+    logging.setup(CONF, __name__)
+    LOG = logging.getLogger(__name__)
+
+
+def keystone_admin(opts):
+    _creds = tempest_lib.auth.KeystoneV2Credentials(
+        username=opts.os_username,
+        password=opts.os_password,
+        tenant_name=opts.os_tenant_name)
+    auth_params = {
+        'disable_ssl_certificate_validation':
+            CONF.identity.disable_ssl_certificate_validation,
+        'ca_certs': CONF.identity.ca_certificates_file,
+        'trace_requests': CONF.debug.trace_requests
+    }
+    _auth = tempest_lib.auth.KeystoneV2AuthProvider(
+        _creds, CONF.identity.uri, **auth_params)
+    params = {
+        'disable_ssl_certificate_validation':
+            CONF.identity.disable_ssl_certificate_validation,
+        'ca_certs': CONF.identity.ca_certificates_file,
+        'trace_requests': CONF.debug.trace_requests,
+        'build_interval': CONF.compute.build_interval,
+        'build_timeout': CONF.compute.build_timeout
+    }
+    return identity_client.IdentityClientJSON(
+        _auth,
+        CONF.identity.catalog_type,
+        CONF.identity.region,
+        endpoint_type='adminURL',
+        **params
+    )
+
+
+def create_resources(opts, resources):
+    admin = keystone_admin(opts)
+    roles = admin.list_roles()
+    for u in resources['users']:
+        u['role_ids'] = []
+        for r in u.get('roles', ()):
+            try:
+                role = filter(lambda r_: r_['name'] == r, roles)[0]
+                u['role_ids'] += [role['id']]
+            except IndexError:
+                raise exceptions.TempestException(
+                    "Role: %s - doesn't exist" % r
+                )
+    existing = [x['name'] for x in admin.list_tenants()]
+    for tenant in resources['tenants']:
+        if tenant not in existing:
+            admin.create_tenant(tenant)
+        else:
+            LOG.warn("Tenant '%s' already exists in this environment" % tenant)
+    LOG.info('Tenants created')
+    for u in resources['users']:
+        try:
+            tenant = admin.get_tenant_by_name(u['tenant'])
+        except tempest_lib.exceptions.NotFound:
+            LOG.error("Tenant: %s - not found" % u['tenant'])
+            continue
+        while True:
+            try:
+                admin.get_user_by_username(tenant['id'], u['name'])
+            except tempest_lib.exceptions.NotFound:
+                admin.create_user(
+                    u['name'], u['pass'], tenant['id'],
+                    "%s@%s" % (u['name'], tenant['id']),
+                    enabled=True)
+                break
+            else:
+                LOG.warn("User '%s' already exists in this environment. "
+                         "New name generated" % u['name'])
+                u['name'] = random_user_name(opts.tag, u['prefix'])
+
+    LOG.info('Users created')
+    for u in resources['users']:
+        try:
+            tenant = admin.get_tenant_by_name(u['tenant'])
+        except tempest_lib.exceptions.NotFound:
+            LOG.error("Tenant: %s - not found" % u['tenant'])
+            continue
+        try:
+            user = admin.get_user_by_username(tenant['id'],
+                                              u['name'])
+        except tempest_lib.exceptions.NotFound:
+            LOG.error("User: %s - not found" % u['user'])
+            continue
+        for r in u['role_ids']:
+            try:
+                admin.assign_user_role(tenant['id'], user['id'], r)
+            except tempest_lib.exceptions.Conflict:
+                # don't care if it's already assigned
+                pass
+    LOG.info('Roles assigned')
+    LOG.info('Resources deployed successfully!')
+
+
+def random_user_name(tag, prefix):
+    if tag:
+        return data_utils.rand_name('-'.join((tag, prefix)))
+    else:
+        return data_utils.rand_name(prefix)
+
+
+def generate_resources(opts):
+    spec = [{'number': 1,
+             'prefix': 'primary',
+             'roles': (CONF.auth.tempest_roles +
+                       [CONF.object_storage.operator_role])},
+            {'number': 1,
+             'prefix': 'alt',
+             'roles': (CONF.auth.tempest_roles +
+                       [CONF.object_storage.operator_role])},
+            {'number': 1,
+             'prefix': 'swift_admin',
+             'roles': (CONF.auth.tempest_roles +
+                       [CONF.object_storage.operator_role,
+                        CONF.object_storage.reseller_admin_role])},
+            {'number': 1,
+             'prefix': 'stack_owner',
+             'roles': (CONF.auth.tempest_roles +
+                       [CONF.orchestration.stack_owner_role])},
+            ]
+    if opts.admin:
+        spec.append({
+            'number': 1,
+            'prefix': 'admin',
+            'roles': (CONF.auth.tempest_roles +
+                      [CONF.identity.admin_role])
+        })
+    resources = {'tenants': [],
+                 'users': []}
+    for count in range(opts.concurrency):
+        for user_group in spec:
+            users = [random_user_name(opts.tag, user_group['prefix'])
+                     for _ in range(user_group['number'])]
+            for user in users:
+                tenant = '-'.join((user, 'tenant'))
+                resources['tenants'].append(tenant)
+                resources['users'].append({
+                    'tenant': tenant,
+                    'name': user,
+                    'pass': data_utils.rand_name(),
+                    'prefix': user_group['prefix'],
+                    'roles': user_group['roles']
+                })
+    return resources
+
+
+def dump_accounts(opts, resources):
+    accounts = []
+    for user in resources['users']:
+        accounts.append({
+            'username': user['name'],
+            'tenant_name': user['tenant'],
+            'password': user['pass'],
+            'roles': user['roles']
+        })
+    if os.path.exists(opts.accounts):
+        os.rename(opts.accounts, '.'.join((opts.accounts, 'bak')))
+    with open(opts.accounts, 'w') as f:
+        yaml.dump(accounts, f, default_flow_style=False)
+    LOG.info('%s generated successfully!' % opts.accounts)
+
+
+def get_options():
+    usage_string = ('account_generator [-h] <ARG> ...\n\n'
+                    'To see help on specific argument, do:\n'
+                    'account_generator <ARG> -h')
+    parser = argparse.ArgumentParser(
+        description='Create accounts.yaml file for concurrent test runs. '
+                    'One primary user, one alt user, '
+                    'one swift admin, one stack owner '
+                    'and one admin (optionally) will be created '
+                    'for each concurrent thread.',
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+        usage=usage_string
+    )
+
+    parser.add_argument('-c', '--config-file',
+                        metavar='/etc/tempest.conf',
+                        help='path to tempest config file')
+    parser.add_argument('--os-username',
+                        metavar='<auth-user-name>',
+                        default=os.environ.get('OS_USERNAME'),
+                        help='User should have permitions '
+                             'to create new user accounts and '
+                             'tenants. Defaults to env[OS_USERNAME].')
+    parser.add_argument('--os-password',
+                        metavar='<auth-password>',
+                        default=os.environ.get('OS_PASSWORD'),
+                        help='Defaults to env[OS_PASSWORD].')
+    parser.add_argument('--os-tenant-name',
+                        metavar='<auth-tenant-name>',
+                        default=os.environ.get('OS_TENANT_NAME'),
+                        help='Defaults to env[OS_TENANT_NAME].')
+    parser.add_argument('--tag',
+                        default='',
+                        required=False,
+                        dest='tag',
+                        help='Resources tag')
+    parser.add_argument('-r', '--concurrency',
+                        default=1,
+                        type=int,
+                        required=True,
+                        dest='concurrency',
+                        help='Concurrency count')
+    parser.add_argument('--with-admin',
+                        action='store_true',
+                        dest='admin',
+                        help='Create admin in every tenant')
+    parser.add_argument('accounts',
+                        metavar='accounts_file.yaml',
+                        help='Output accounts yaml file')
+
+    opts = parser.parse_args()
+    if opts.config_file:
+        config.CONF.set_config_path(opts.config_file)
+    return opts
+
+
+def main(opts=None):
+    if not opts:
+        opts = get_options()
+    setup_logging()
+    resources = generate_resources(opts)
+    create_resources(opts, resources)
+    dump_accounts(opts, resources)
+
+if __name__ == "__main__":
+    main()
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 1ad12eb..eb6f143 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -343,6 +343,44 @@
         self.data['volumes'] = vols
 
 
+class VolumeQuotaService(BaseService):
+    def __init__(self, manager, **kwargs):
+        super(VolumeQuotaService, self).__init__(kwargs)
+        self.client = manager.volume_quotas_client
+
+    def delete(self):
+        client = self.client
+        try:
+            client.delete_quota_set(self.tenant_id)
+        except Exception as e:
+            LOG.exception("Delete Volume Quotas exception: %s" % e)
+            pass
+
+    def dry_run(self):
+        quotas = self.client.show_quota_usage(self.tenant_id)
+        self.data['volume_quotas'] = quotas
+
+
+class NovaQuotaService(BaseService):
+    def __init__(self, manager, **kwargs):
+        super(NovaQuotaService, self).__init__(kwargs)
+        self.client = manager.quotas_client
+        self.limits_client = manager.limits_client
+
+    def delete(self):
+        client = self.client
+        try:
+            client.delete_quota_set(self.tenant_id)
+        except Exception as e:
+            LOG.exception("Delete Quotas exception: %s" % e)
+            pass
+
+    def dry_run(self):
+        client = self.limits_client
+        quotas = client.get_absolute_limits()
+        self.data['compute_quotas'] = quotas
+
+
 # Begin network service classes
 class NetworkService(BaseService):
     def __init__(self, manager, **kwargs):
@@ -667,7 +705,7 @@
         self.data['pools'] = pools
 
 
-class NetworMeteringLabelRuleService(NetworkService):
+class NetworkMeteringLabelRuleService(NetworkService):
 
     def list(self):
         client = self.client
@@ -692,7 +730,7 @@
         self.data['rules'] = rules
 
 
-class NetworMeteringLabelService(NetworkService):
+class NetworkMeteringLabelService(NetworkService):
 
     def list(self):
         client = self.client
@@ -1052,6 +1090,7 @@
         tenant_services.append(ServerGroupService)
         if not IS_NEUTRON:
             tenant_services.append(FloatingIpService)
+        tenant_services.append(NovaQuotaService)
     if IS_HEAT:
         tenant_services.append(StackService)
     if IS_NEUTRON:
@@ -1068,8 +1107,8 @@
             tenant_services.append(NetworkVipService)
             tenant_services.append(NetworkPoolService)
         if test.is_extension_enabled('metering', 'network'):
-            tenant_services.append(NetworMeteringLabelRuleService)
-            tenant_services.append(NetworMeteringLabelService)
+            tenant_services.append(NetworkMeteringLabelRuleService)
+            tenant_services.append(NetworkMeteringLabelService)
         tenant_services.append(NetworkRouterService)
         tenant_services.append(NetworkFloatingIpService)
         tenant_services.append(NetworkPortService)
@@ -1078,6 +1117,7 @@
     if IS_CINDER:
         tenant_services.append(SnapshotService)
         tenant_services.append(VolumeService)
+        tenant_services.append(VolumeQuotaService)
     return tenant_services
 
 
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index f1965bc..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)
@@ -335,25 +336,28 @@
         CONF_PARSER.optionxform = str
         CONF_PARSER.readfp(conf_file)
     icreds = credentials.get_isolated_credentials('verify_tempest_config')
-    os = clients.Manager(icreds.get_primary_creds())
-    services = check_service_availability(os, update)
-    results = {}
-    for service in ['nova', 'cinder', 'neutron', 'swift']:
-        if service not in services:
-            continue
-        results = verify_extensions(os, service, results)
+    try:
+        os = clients.Manager(icreds.get_primary_creds())
+        services = check_service_availability(os, update)
+        results = {}
+        for service in ['nova', 'cinder', 'neutron', 'swift']:
+            if service not in services:
+                continue
+            results = verify_extensions(os, service, results)
 
-    # Verify API versions of all services in the keystone catalog and keystone
-    # itself.
-    services.append('keystone')
-    for service in services:
-        verify_api_versions(os, service, update)
+        # Verify API versions of all services in the keystone catalog and
+        # keystone itself.
+        services.append('keystone')
+        for service in services:
+            verify_api_versions(os, service, update)
 
-    display_results(results, update, replace)
-    if update:
-        conf_file.close()
-        CONF_PARSER.write(outfile)
-    outfile.close()
+        display_results(results, update, replace)
+        if update:
+            conf_file.close()
+            CONF_PARSER.write(outfile)
+        outfile.close()
+    finally:
+        icreds.clear_isolated_creds()
 
 
 if __name__ == "__main__":
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 7d69541..650faf1 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -286,8 +286,11 @@
         net_clients = clients.Manager(credentials=credential)
         compute_network_client = net_clients.networks_client
         net_name = self.hash_dict['networks'].get(hash, None)
-        network = fixed_network.get_network_from_name(
-            net_name, compute_network_client)
+        try:
+            network = fixed_network.get_network_from_name(
+                net_name, compute_network_client)
+        except exceptions.InvalidConfiguration:
+            network = {}
         net_creds.set_resources(network=network)
         return net_creds
 
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index 1557474..2c6e334 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -17,6 +17,7 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -29,51 +30,59 @@
     :param str name: the name of the network to use
     :param NetworksClientJSON compute_networks_client: The network client
         object to use for making the network lists api request
-    :return: The full dictionary for the network in question, unless the
-        network for the supplied name can not be found. In which case a dict
-        with just the name will be returned.
+    :return: The full dictionary for the network in question
     :rtype: dict
+    :raises InvalidConfiguration: If the name provided is invalid, the networks
+        list returns a 404, there are no found networks, or the found network
+        is invalid
     """
     caller = misc_utils.find_test_caller()
+
     if not name:
-        network = {'name': name}
+        raise exceptions.InvalidConfiguration()
+
+    try:
+        networks = compute_networks_client.list_networks(name=name)
+    except lib_exc.NotFound:
+        # In case of nova network, if the fixed_network_name is not
+        # owned by the tenant, and the network client is not an admin
+        # one, list_networks will not find it
+        msg = ('Unable to find network %s. '
+               'Starting instance without specifying a network.' %
+               name)
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.info(msg)
+        raise exceptions.InvalidConfiguration()
+
+    # Check that a network exists, else raise an InvalidConfigurationException
+    if len(networks) == 1:
+        network = sorted(networks)[0]
+    elif len(networks) > 1:
+        msg = ("Network with name: %s had multiple matching networks in the "
+               "list response: %s\n Unable to specify a single network" % (
+                   name, networks))
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
     else:
-        try:
-            resp = compute_networks_client.list_networks(name=name)
-            if isinstance(resp, list):
-                networks = resp
-            elif isinstance(resp, dict):
-                networks = resp['networks']
-            else:
-                raise lib_exc.NotFound()
-            if len(networks) > 0:
-                network = networks[0]
-            else:
-                msg = "Network with name: %s not found" % name
-                if caller:
-                    LOG.warn('(%s) %s' % (caller, msg))
-                else:
-                    LOG.warn(msg)
-                raise lib_exc.NotFound()
-            # To be consistent with network isolation, add name is only
-            # label is available
-            name = network.get('name', network.get('label'))
-            if name:
-                network['name'] = name
-            else:
-                raise lib_exc.NotFound()
-        except lib_exc.NotFound:
-            # In case of nova network, if the fixed_network_name is not
-            # owned by the tenant, and the network client is not an admin
-            # one, list_networks will not find it
-            msg = ('Unable to find network %s. '
-                   'Starting instance without specifying a network.' %
-                   name)
-            if caller:
-                LOG.info('(%s) %s' % (caller, msg))
-            else:
-                LOG.info(msg)
-            network = {'name': name}
+        msg = "Network with name: %s not found" % name
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
+    # To be consistent between neutron and nova network always use name even
+    # if label is used in the api response. If neither is present than then
+    # the returned network is invalid.
+    name = network.get('name') or network.get('label')
+    if not name:
+        msg = "Network found from list doesn't contain a valid name or label"
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
+    network['name'] = name
     return network
 
 
@@ -97,16 +106,17 @@
             msg = ('No valid network provided or created, defaulting to '
                    'fixed_network_name')
             if caller:
-                LOG.debug('(%s) %s' % (caller, msg))
-            else:
-                LOG.debug(msg)
-            network = get_network_from_name(fixed_network_name,
-                                            compute_networks_client)
+                msg = '(%s) %s' % (caller, msg)
+            LOG.debug(msg)
+            try:
+                network = get_network_from_name(fixed_network_name,
+                                                compute_networks_client)
+            except exceptions.InvalidConfiguration:
+                network = {}
     msg = ('Found network %s available for tenant' % network)
     if caller:
-        LOG.info('(%s) %s' % (caller, msg))
-    else:
-        LOG.info(msg)
+        msg = '(%s) %s' % (caller, msg)
+    LOG.info(msg)
     return network
 
 
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/common/validation_resources.py b/tempest/common/validation_resources.py
new file mode 100644
index 0000000..d370ebc
--- /dev/null
+++ b/tempest/common/validation_resources.py
@@ -0,0 +1,113 @@
+# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
+#    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 oslo_log import log as logging
+
+from tempest import config
+from tempest_lib.common.utils import data_utils
+from tempest_lib import exceptions as lib_exc
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+def create_ssh_security_group(os, add_rule=False):
+    security_group_client = os.security_groups_client
+    sg_name = data_utils.rand_name('securitygroup-')
+    sg_description = data_utils.rand_name('description-')
+    security_group = \
+        security_group_client.create_security_group(sg_name, sg_description)
+    if add_rule:
+        security_group_client.create_security_group_rule(security_group['id'],
+                                                         'tcp', 22, 22)
+        security_group_client.create_security_group_rule(security_group['id'],
+                                                         'icmp', -1, -1)
+    LOG.debug("SSH Validation resource security group with tcp and icmp "
+              "rules %s created"
+              % sg_name)
+    return security_group
+
+
+def create_validation_resources(os, validation_resources=None):
+    # Create and Return the validation resources required to validate a VM
+    validation_data = {}
+    if validation_resources:
+        if validation_resources['keypair']:
+            keypair_name = data_utils.rand_name('keypair')
+            validation_data['keypair'] = \
+                os.keypairs_client.create_keypair(keypair_name)
+            LOG.debug("Validation resource key %s created" % keypair_name)
+        add_rule = False
+        if validation_resources['security_group']:
+            if validation_resources['security_group_rules']:
+                add_rule = True
+            validation_data['security_group'] = \
+                create_ssh_security_group(os, add_rule)
+        if validation_resources['floating_ip']:
+            floating_client = os.floating_ips_client
+            validation_data['floating_ip'] = \
+                floating_client.create_floating_ip()
+    return validation_data
+
+
+def clear_validation_resources(os, validation_data=None):
+    # Cleanup the vm validation resources
+    has_exception = None
+    if validation_data:
+        if 'keypair' in validation_data:
+            keypair_client = os.keypairs_client
+            keypair_name = validation_data['keypair']['name']
+            try:
+                keypair_client.delete_keypair(keypair_name)
+            except lib_exc.NotFound:
+                LOG.warn("Keypair %s is not found when attempting to delete"
+                         % keypair_name)
+            except Exception as exc:
+                LOG.exception('Exception raised while deleting key %s'
+                              % keypair_name)
+                if not has_exception:
+                    has_exception = exc
+        if 'security_group' in validation_data:
+            security_group_client = os.security_groups_client
+            sec_id = validation_data['security_group']['id']
+            try:
+                security_group_client.delete_security_group(sec_id)
+                security_group_client.wait_for_resource_deletion(sec_id)
+            except lib_exc.NotFound:
+                LOG.warn("Security group %s is not found when attempting to "
+                         " delete" % sec_id)
+            except lib_exc.Conflict as exc:
+                LOG.exception('Conflict while deleting security '
+                              'group %s VM might not be deleted ' % sec_id)
+                if not has_exception:
+                    has_exception = exc
+            except Exception as exc:
+                LOG.exception('Exception raised while deleting security '
+                              'group %s ' % sec_id)
+                if not has_exception:
+                    has_exception = exc
+        if 'floating_ip' in validation_data:
+            floating_client = os.floating_ips_client
+            fip_id = validation_data['floating_ip']['id']
+            try:
+                floating_client.delete_floating_ip(fip_id)
+            except lib_exc.NotFound:
+                LOG.warn('Floating ip %s not found while attempting to delete'
+                         % fip_id)
+            except Exception as exc:
+                LOG.exception('Exception raised while deleting ip %s '
+                              % fip_id)
+                if not has_exception:
+                    has_exception = exc
+    if has_exception:
+        raise has_exception
diff --git a/tempest/config.py b/tempest/config.py
index a57d95f..bdbf942 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/scenario/utils.py b/tempest/scenario/utils.py
index 60eb1c3..e5613d6 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -41,9 +41,16 @@
         self.non_ssh_image_pattern = \
             CONF.input_scenario.non_ssh_image_regex
         # Setup clients
+        network_resources = {
+            'network': False,
+            'router': False,
+            'subnet': False,
+            'dhcp': False,
+        }
         self.isolated_creds = credentials.get_isolated_credentials(
             name='ScenarioImageUtils',
-            identity_version=CONF.identity.auth_version)
+            identity_version=CONF.identity.auth_version,
+            network_resources=network_resources)
         os = clients.Manager(self.isolated_creds.get_primary_creds())
         self.images_client = os.images_client
         self.flavors_client = os.flavors_client
@@ -103,9 +110,16 @@
                                             digit=string.digits)
 
     def __init__(self):
+        network_resources = {
+            'network': False,
+            'router': False,
+            'subnet': False,
+            'dhcp': False,
+        }
         self.isolated_creds = credentials.get_isolated_credentials(
             name='InputScenarioUtils',
-            identity_version=CONF.identity.auth_version)
+            identity_version=CONF.identity.auth_version,
+            network_resources=network_resources)
         os = clients.Manager(self.isolated_creds.get_primary_creds())
         self.images_client = os.images_client
         self.flavors_client = os.flavors_client
diff --git a/tempest/test.py b/tempest/test.py
index ae77284..ab5a353 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -34,6 +34,7 @@
 from tempest.common import credentials
 from tempest.common import fixed_network
 import tempest.common.generator.valid_generator as valid
+import tempest.common.validation_resources as vresources
 from tempest import config
 from tempest import exceptions
 
@@ -231,6 +232,8 @@
     # NOTE(andreaf) credentials holds a list of the credentials to be allocated
     # at class setup time. Credential types can be 'primary', 'alt' or 'admin'
     credentials = []
+    # Resources required to validate a server using ssh
+    validation_resources = {}
     network_resources = {}
 
     # NOTE(sdague): log_format is defined inline here instead of using the oslo
@@ -264,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
 
@@ -302,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
 
@@ -322,6 +325,13 @@
         if 'alt' is cls.credentials and not credentials.is_alt_available():
             msg = "Missing a 2nd set of API credentials in configuration."
             raise cls.skipException(msg)
+        if hasattr(cls, 'identity_version'):
+            if cls.identity_version == 'v2':
+                if not CONF.identity_feature_enabled.api_v2:
+                    raise cls.skipException("Identity api v2 is not enabled")
+            elif cls.identity_version == 'v3':
+                if not CONF.identity_feature_enabled.api_v3:
+                    raise cls.skipException("Identity api v3 is not enabled")
 
     @classmethod
     def setup_credentials(cls):
@@ -360,7 +370,12 @@
     def resource_setup(cls):
         """Class level resource setup for test cases.
         """
-        pass
+        if hasattr(cls, "os"):
+            cls.validation_resources = vresources.create_validation_resources(
+                cls.os, cls.validation_resources)
+        else:
+            LOG.warn("Client manager not found, validation resources not"
+                     " created")
 
     @classmethod
     def resource_cleanup(cls):
@@ -368,7 +383,14 @@
         Resource cleanup must be able to handle the case of partially setup
         resources, in case a failure during `resource_setup` should happen.
         """
-        pass
+        if cls.validation_resources:
+            if hasattr(cls, "os"):
+                vresources.clear_validation_resources(cls.os,
+                                                      cls.validation_resources)
+                cls.validation_resources = {}
+            else:
+                LOG.warn("Client manager not found, validation resources not"
+                         " deleted")
 
     def setUp(self):
         super(BaseTestCase, self).setUp()
@@ -399,39 +421,117 @@
                                                    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, 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 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'
+        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, '_creds_provider'):
+            cls._creds_provider.clear_isolated_creds()
+
+    @classmethod
+    def set_validation_resources(cls, keypair=None, floating_ip=None,
+                                 security_group=None,
+                                 security_group_rules=None):
+        """Specify which ssh server validation resources should be created.
+        Each of the argument must be set to either None, True or False, with
+        None - use default from config (security groups and security group
+               rules get created when set to None)
+        False - Do not create the validation resource
+        True - create the validation resource
+
+        @param keypair
+        @param security_group
+        @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
+            else:
+                keypair = False
+        if floating_ip is None:
+            if CONF.validation.connect_method.lower() == "floating":
+                floating_ip = True
+            else:
+                floating_ip = False
+        if security_group is None:
+            security_group = True
+        if security_group_rules is None:
+            security_group_rules = True
+        if not cls.validation_resources:
+            cls.validation_resources = {
+                'keypair': keypair,
+                'security_group': security_group,
+                'security_group_rules': security_group_rules,
+                'floating_ip': floating_ip}
 
     @classmethod
     def set_network_resources(cls, network=False, router=False, subnet=False,
@@ -462,16 +562,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):
@@ -621,7 +721,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
diff --git a/tox.ini b/tox.ini
index 88d1302..2d2ed38 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = pep8,py27
+envlist = pep8,py27,py34
 minversion = 1.6
 skipsdist = True