Merge "Check IPv6 mupltiprefix feature"
diff --git a/.testr.conf b/.testr.conf
index 4f6e0b3..95a4fb4 100644
--- a/.testr.conf
+++ b/.testr.conf
@@ -3,7 +3,7 @@
              OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
              OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \
              OS_TEST_LOCK_PATH=${OS_TEST_LOCK_PATH:-${TMPDIR:-'/tmp'}} \
-             ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./tempest/test_discover} $LISTOPT $IDOPTION
+             ${PYTHON:-python} -m subunit.run discover -t ${OS_TOP_LEVEL:-./} ${OS_TEST_PATH:-./tempest/test_discover} $LISTOPT $IDOPTION
 test_id_option=--load-list $IDFILE
 test_list_option=--list
 group_regex=([^\.]*\.)*
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..eab7487 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
@@ -303,6 +310,12 @@
 will additionally be used as a fallback for server creation. However, unlike
 accounts.yaml this should never be triggered.
 
+However, there is an option *create_isolated_networks* to disable tenant
+isolation's automatic provisioning of network resources. If this option is
+used you will have to either rely on there only being a single/default network
+available for the server creation, or use *fixed_network_name* to inform
+Tempest which network to use.
+
 Configuring Available Services
 ------------------------------
 OpenStack is really a constellation of several different projects which
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index ccb64f5..56172f8 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -40,13 +40,15 @@
 #log_dir = <None>
 
 # Use syslog for logging. Existing syslog format is DEPRECATED during
-# I, and will change in J to honor RFC5424. (boolean value)
+# I, and changed in J to honor RFC5424. (boolean value)
 #use_syslog = false
 
 # (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 K, and
-# will be removed in L, along with this option. (boolean value)
+# will be removed in M, along with this option. (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
 #use_syslog_rfc_format = true
 
 # Syslog facility to receive log lines. (string value)
@@ -67,7 +69,7 @@
 
 # Prefix each line of exception output with this format. (string
 # value)
-#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
+#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s
 
 # List of logger=LEVEL pairs. (list value)
 #default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN
@@ -86,6 +88,9 @@
 # (string value)
 #instance_uuid_format = "[instance: %(uuid)s] "
 
+# Enables or disables fatal status of deprecations. (boolean value)
+#fatal_deprecations = false
+
 
 [auth]
 
@@ -117,6 +122,14 @@
 # the domain from theadmin user is used instead. (string value)
 #tenant_isolation_domain_name = <None>
 
+# If allow_tenant_isolation is set to True and Neutron is enabled
+# Tempest will try to create a useable network, subnet, and router
+# when needed for each tenant it  creates. However in some neutron
+# configurations, like with VLAN provider networks, this doesn't work.
+# So if set to False the isolated networks will not be created
+# (boolean value)
+#create_isolated_networks = true
+
 
 [baremetal]
 
@@ -148,8 +161,9 @@
 # Timeout for Ironic power transitions. (integer value)
 #power_timeout = 60
 
-# Timeout for unprovisioning an Ironic node. (integer value)
-#unprovision_timeout = 60
+# Timeout for unprovisioning an Ironic node. Takes longer since Kilo
+# as Ironic performs an extra step in Node cleaning. (integer value)
+#unprovision_timeout = 300
 
 
 [boto]
@@ -240,9 +254,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 +300,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)
@@ -574,6 +585,9 @@
 # applies to user and project (string value)
 #admin_domain_name = <None>
 
+# ID of the default domain (string value)
+#default_domain_id = default
+
 
 [identity-feature-enabled]
 
@@ -938,6 +952,10 @@
 # Image container format (string value)
 #img_container_format = bare
 
+# Glance image properties. Use for custom images which require them
+# (dict value)
+#img_properties = <None>
+
 # AMI image file name (string value)
 #ami_img_file = cirros-0.3.1-x86_64-blank.img
 
@@ -1071,6 +1089,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)
@@ -1169,3 +1192,7 @@
 
 # Is the v2 volume API enabled (boolean value)
 #api_v2 = true
+
+# Update bootable status of a volume Not implemented on icehouse
+# (boolean value)
+#bootable = false
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/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index d3b1f5e..a03439a 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -78,7 +78,7 @@
             return server_id
 
     def _volume_clean_up(self, server_id, volume_id):
-        body = self.volumes_client.get_volume(volume_id)
+        body = self.volumes_client.show_volume(volume_id)
         if body['status'] == 'in-use':
             self.servers_client.detach_volume(server_id, volume_id)
             self.volumes_client.wait_for_volume_status(volume_id, 'available')
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 26d6661..9aacfa5 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))
@@ -312,7 +303,7 @@
         if 'wait_until' in kwargs:
             cls.images_client.wait_for_image_status(image_id,
                                                     kwargs['wait_until'])
-            image = cls.images_client.get_image(image_id)
+            image = cls.images_client.show_image(image_id)
 
             if kwargs['wait_until'] == 'ACTIVE':
                 if kwargs.get('wait_for_server', True):
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index a92048f..3771a43 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -84,11 +84,11 @@
         self.client.wait_for_image_status(image_id, 'ACTIVE')
 
         # Verify the image was created correctly
-        image = self.client.get_image(image_id)
+        image = self.client.show_image(image_id)
         self.assertEqual(name, image['name'])
         self.assertEqual('test', image['metadata']['image_type'])
 
-        original_image = self.client.get_image(self.image_ref)
+        original_image = self.client.show_image(self.image_ref)
 
         # Verify minRAM is the same as the original image
         self.assertEqual(image['minRam'], original_image['minRam'])
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index aa12044..8a39d90 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -140,4 +140,4 @@
         self.client.delete_image(image_id)
         self.image_ids.remove(image_id)
 
-        self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
+        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index abe7be5..e2d4bd9 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -62,7 +62,7 @@
             image_file = six.StringIO(('*' * 1024))
             cls.glance_client.update_image(image_id, data=image_file)
             cls.client.wait_for_image_status(image_id, 'ACTIVE')
-            body = cls.client.get_image(image_id)
+            body = cls.client.show_image(image_id)
             return body
 
         # Create non-snapshot images via glance
@@ -249,7 +249,7 @@
         # The detailed list of servers should be filtered by image type
         params = {'type': 'snapshot'}
         images = self.client.list_images_with_detail(params)
-        self.client.get_image(self.image_ref)
+        self.client.show_image(self.image_ref)
 
         self.assertTrue(any([i for i in images
                              if i['id'] == self.snapshot1_id]))
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index 334516b..4110619 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -41,5 +41,5 @@
     def test_get_nonexistent_image(self):
         # Check raises a NotFound
         nonexistent_image = data_utils.rand_uuid()
-        self.assertRaises(lib_exc.NotFound, self.client.get_image,
+        self.assertRaises(lib_exc.NotFound, self.client.show_image,
                           nonexistent_image)
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index 95f49c9..5b80c72 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -37,7 +37,7 @@
     @test.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
     def test_get_image(self):
         # Returns the correct details for a single image
-        image = self.client.get_image(self.image_ref)
+        image = self.client.show_image(self.image_ref)
         self.assertEqual(self.image_ref, image['id'])
 
     @test.idempotent_id('fd51b7f4-d4a3-4331-9885-866658112a6f')
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index 2cf2e28..06e073d 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -89,15 +89,10 @@
     @test.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
-        # Negative test:Security Group should not be created with description
-        # as an empty string/with white spaces/chars more than 255
+        # Negative test: Security Group should not be created with description
+        # longer than 255 chars. Empty description is allowed by the API
+        # reference, however.
         s_name = data_utils.rand_name('securitygroup')
-        # Create Security Group with empty string as description
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name, "")
-        # Create Security Group with white space in description
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.create_security_group, s_name, " ")
         # Create Security Group with group description longer than 255 chars
         s_description = 'description-'.ljust(260, '0')
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 3b9e4b5..9012d3d 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -95,7 +95,7 @@
         self.assertTrue(found)
 
     @test.idempotent_id('cbc0f52f-05aa-492b-bdc1-84b575ca294b')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_vcpus(self):
         # Verify that the number of vcpus reported by the instance matches
@@ -106,7 +106,7 @@
         self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
 
     @test.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_host_name_is_same_as_server_name(self):
         # Verify the instance host name is the same as the server name
@@ -206,7 +206,7 @@
         cls.client = cls.servers_client
 
     @test.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
-    @testtools.skipUnless(CONF.compute.run_ssh,
+    @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_ephemeral_disk(self):
         # Verify that the ephemeral disk is created when creating server
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 5374af0..7a91cab 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest_lib.common.utils import data_utils
-from tempest_lib import decorators
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.compute import base
@@ -56,13 +55,13 @@
         # Do some sanity checks here. If one of the images does
         # not exist, fail early since the tests won't work...
         try:
-            cls.images_client.get_image(cls.image_ref)
+            cls.images_client.show_image(cls.image_ref)
         except lib_exc.NotFound:
             raise RuntimeError("Image %s (image_ref) was not found!" %
                                cls.image_ref)
 
         try:
-            cls.images_client.get_image(cls.image_ref_alt)
+            cls.images_client.show_image(cls.image_ref_alt)
         except lib_exc.NotFound:
             raise RuntimeError("Image %s (image_ref_alt) was not found!" %
                                cls.image_ref_alt)
@@ -275,8 +274,14 @@
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
         self.s1 = self.client.get_server(self.s1['id'])
-        ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
-        params = {'ip': ip}
+        for addr_spec in self.s1['addresses'][self.fixed_network_name]:
+            ip = addr_spec['addr']
+            if addr_spec['version'] == 4:
+                params = {'ip': ip}
+                break
+        else:
+            msg = "Skipped until bug 1450859 is resolved"
+            raise self.skipException(msg)
         body = self.client.list_servers(params)
         servers = body['servers']
 
@@ -284,8 +289,6 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @decorators.skip_because(bug="1182883",
-                             condition=CONF.service_available.neutron)
     @test.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
     def test_list_servers_filtered_by_ip_regex(self):
         # Filter servers by regex ip
@@ -295,8 +298,12 @@
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
         self.s1 = self.client.get_server(self.s1['id'])
-        ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
-        params = {'ip': ip}
+        addr_spec = self.s1['addresses'][self.fixed_network_name][0]
+        ip = addr_spec['addr'][0:-3]
+        if addr_spec['version'] == 4:
+            params = {'ip': ip}
+        else:
+            params = {'ip6': ip}
         body = self.client.list_servers(params)
         servers = body['servers']
 
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index eed3be8..11b457b 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -30,7 +30,9 @@
         This is the right way to create_multiple servers and manage to get the
         created servers into the servers list to be cleaned up after all.
         """
-        kwargs['name'] = kwargs.get('name', self._generate_name())
+        kwargs['name'] = name if name else self._generate_name()
+        if wait_until:
+            kwargs['wait_until'] = wait_until
         body = self.create_test_server(**kwargs)
 
         return body
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index dbfdbdb..ca016c0 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,
@@ -42,13 +42,15 @@
         # Check if the server is in a clean state after test
         try:
             self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        except lib_exc.NotFound:
+            # The server was deleted by previous test, create a new one
+            server = self.create_test_server(wait_until='ACTIVE')
+            self.__class__.server_id = server['id']
         except Exception:
             # Rebuild server if something happened to it during a test
             self.__class__.server_id = self.rebuild_server(self.server_id)
 
     def tearDown(self):
-        server = self.client.get_server(self.server_id)
-        self.assertEqual(self.image_ref, server['image']['id'])
         self.server_check_teardown()
         super(ServerActionsTestJSON, self).tearDown()
 
@@ -110,6 +112,14 @@
         # The server should be signaled to reboot gracefully
         self._test_reboot_server('SOFT')
 
+    def _rebuild_server_and_check(self, image_ref):
+        rebuilt_server = self.client.rebuild(self.server_id, image_ref)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        msg = ('Server was not rebuilt to the original image. '
+               'The original image: {0}. The current image: {1}'
+               .format(image_ref, rebuilt_server['image']['id']))
+        self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
+
     @test.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
     def test_rebuild_server(self):
         # The server should be rebuilt using the provided image and data
@@ -129,8 +139,7 @@
         # If the server was rebuilt on a different image, restore it to the
         # original image once the test ends
         if self.image_ref_alt != self.image_ref:
-            self.addCleanup(self.client.rebuild,
-                            (self.server_id, self.image_ref))
+            self.addCleanup(self._rebuild_server_and_check, self.image_ref)
 
         # Verify the properties in the initial response are correct
         self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -157,11 +166,15 @@
         # image and remain in SHUTOFF state
         server = self.client.get_server(self.server_id)
         old_image = server['image']['id']
-        new_image = self.image_ref_alt \
-            if old_image == self.image_ref else self.image_ref
+        new_image = (self.image_ref_alt
+                     if old_image == self.image_ref else self.image_ref)
         self.client.stop(self.server_id)
         self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
         rebuilt_server = self.client.rebuild(self.server_id, new_image)
+        # If the server was rebuilt on a different image, restore it to the
+        # original image once the test ends
+        if self.image_ref_alt != self.image_ref:
+            self.addCleanup(self._rebuild_server_and_check, old_image)
 
         # Verify the properties in the initial response are correct
         self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -175,10 +188,6 @@
         rebuilt_image_id = server['image']['id']
         self.assertEqual(new_image, rebuilt_image_id)
 
-        # Restore to the original image (The tearDown will test it again)
-        if self.image_ref_alt != self.image_ref:
-            self.client.rebuild(self.server_id, old_image)
-            self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
         self.client.start(self.server_id)
 
     def _test_resize_server_confirm(self, stop=False):
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..63b78a0 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -73,7 +73,7 @@
         image_file = six.StringIO(('*' * 1024))
         body = cls.glance_client.update_image(image_id, data=image_file)
         cls.glance_client.wait_for_image_status(image_id, 'active')
-        cls.image = cls.images_client.get_image(image_id)
+        cls.image = cls.images_client.show_image(image_id)
 
         cls.keypairname = data_utils.rand_name('keypair')
         cls.keypairs_client.create_keypair(cls.keypairname)
@@ -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()
 
@@ -231,7 +233,7 @@
     def test_get_image_for_alt_account_fails(self):
         # A GET request for an image on another user's account should fail
         self.assertRaises(lib_exc.NotFound,
-                          self.alt_images_client.get_image, self.image['id'])
+                          self.alt_images_client.show_image, self.image['id'])
 
     @test.idempotent_id('9facb962-f043-4a9d-b9ee-166a32dea098')
     def test_delete_image_for_alt_account_fails(self):
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/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index bcac853..8eac80c 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -50,7 +50,7 @@
                                        self.alt_email, enabled=False)
         self.data.users.append(user)
         self.assertEqual(name, user['name'])
-        self.assertEqual('false', str(user['enabled']).lower())
+        self.assertEqual(False, user['enabled'])
         self.assertEqual(self.alt_email, user['email'])
 
     @test.idempotent_id('39d05857-e8a5-4ed4-ba83-0b52d3ab97ee')
@@ -71,13 +71,13 @@
                                               enabled=False)
         self.assertEqual(u_name2, update_user['name'])
         self.assertEqual(u_email2, update_user['email'])
-        self.assertEqual('false', str(update_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
         # GET by id after updating
         updated_user = self.client.get_user(user['id'])
         # Assert response body of GET after updating
         self.assertEqual(u_name2, updated_user['name'])
         self.assertEqual(u_email2, updated_user['email'])
-        self.assertEqual('false', str(updated_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
 
     @test.idempotent_id('29ed26f4-a74e-4425-9a85-fdb49fa269d2')
     def test_delete_user(self):
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 79943bb..b1a9d3b 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -13,10 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.api.identity import base
+from tempest import config
+from tempest import test
+
 from tempest_lib.common.utils import data_utils
 
-from tempest.api.identity import base
-from tempest import test
+CONF = config.CONF
 
 
 class DomainsTestJSON(base.BaseIdentityV3AdminTest):
@@ -76,12 +79,12 @@
         self.assertIsNotNone(updated_domain['id'])
         self.assertEqual(new_name, updated_domain['name'])
         self.assertEqual(new_desc, updated_domain['description'])
-        self.assertEqual('true', str(updated_domain['enabled']).lower())
+        self.assertEqual(True, updated_domain['enabled'])
 
         fetched_domain = self.client.get_domain(domain['id'])
         self.assertEqual(new_name, fetched_domain['name'])
         self.assertEqual(new_desc, fetched_domain['description'])
-        self.assertEqual('true', str(fetched_domain['enabled']).lower())
+        self.assertEqual(True, fetched_domain['enabled'])
 
     @test.idempotent_id('036df86e-bb5d-42c0-a7c2-66b9db3a6046')
     def test_create_domain_with_disabled_status(self):
@@ -105,3 +108,18 @@
         expected_data = {'name': d_name, 'enabled': True}
         self.assertIsNone(domain['description'])
         self.assertDictContainsSubset(expected_data, domain)
+
+
+class DefaultDomainTestJSON(base.BaseIdentityV3AdminTest):
+
+    @classmethod
+    def resource_setup(cls):
+        cls.domain_id = CONF.identity.default_domain_id
+        super(DefaultDomainTestJSON, cls).resource_setup()
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('17a5de24-e6a0-4e4a-a9ee-d85b6e5612b5')
+    def test_default_domain_exists(self):
+        domain = self.client.get_domain(self.domain_id)
+
+        self.assertTrue(domain['enabled'])
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
new file mode 100644
index 0000000..e2f3ef5
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -0,0 +1,38 @@
+# Copyright 2015 Red Hat Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.identity import base
+from tempest import test
+
+from tempest_lib.common.utils import data_utils
+from tempest_lib import exceptions as lib_exc
+
+
+class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
+    _interface = 'json'
+
+    @test.attr(type=['negative', 'gate'])
+    @test.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
+    def test_delete_active_domain(self):
+        d_name = data_utils.rand_name('domain')
+        d_desc = data_utils.rand_name('domain-desc')
+        domain = self.client.create_domain(d_name, description=d_desc)
+        domain_id = domain['id']
+
+        self.addCleanup(self.delete_domain, domain_id)
+
+        # domain need to be disabled before deleting
+        self.assertRaises(lib_exc.Forbidden, self.client.delete_domain,
+                          domain_id)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 1672d47..9ca10a4 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -126,4 +126,4 @@
         self.assertEqual(interface2, endpoint['interface'])
         self.assertEqual(url2, endpoint['url'])
         self.assertEqual(region2, endpoint['region'])
-        self.assertEqual('false', str(endpoint['enabled']).lower())
+        self.assertEqual(False, endpoint['enabled'])
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 7fe369e..c2456c4 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -53,7 +53,7 @@
         self.assertEqual(project['id'],
                          update_user['project_id'])
         self.assertEqual(u_email2, update_user['email'])
-        self.assertEqual('false', str(update_user['enabled']).lower())
+        self.assertEqual(False, update_user['enabled'])
         # GET by id after updation
         new_user_get = self.client.get_user(user['id'])
         # Assert response body of GET after updation
@@ -62,7 +62,7 @@
         self.assertEqual(project['id'],
                          new_user_get['project_id'])
         self.assertEqual(u_email2, new_user_get['email'])
-        self.assertEqual('false', str(new_user_get['enabled']).lower())
+        self.assertEqual(False, new_user_get['enabled'])
 
     @test.idempotent_id('2d223a0e-e457-4a70-9fb1-febe027a0ff9')
     def test_update_user_password(self):
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 5d66b9c..913e807 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):
@@ -186,6 +172,12 @@
         if len(role) > 0:
             return role[0]
 
+    def delete_domain(self, domain_id):
+        # NOTE(mpavlase) It is necessary to disable the domain before deleting
+        # otherwise it raises Forbidden exception
+        self.client.update_domain(domain_id, enabled=False)
+        self.client.delete_domain(domain_id)
+
 
 class DataGenerator(object):
 
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index acf8272..00959d9 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -146,7 +146,7 @@
         cls.alt_tenant_id = cls.alt_img_client.tenant_id
 
     def _list_image_ids_as_alt(self):
-        image_list = self.alt_img_client.image_list()
+        image_list = self.alt_img_client.list_images()
         image_ids = map(lambda x: x['id'], image_list)
         return image_ids
 
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index d57cb93..4969858 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -23,12 +23,12 @@
     def test_add_image_member(self):
         image = self._create_image()
         self.client.add_member(self.alt_tenant_id, image)
-        body = self.client.get_image_membership(image)
+        body = self.client.list_image_members(image)
         members = body['members']
         members = map(lambda x: x['member_id'], members)
         self.assertIn(self.alt_tenant_id, members)
         # get image as alt user
-        self.alt_img_cli.get_image(image)
+        self.alt_img_cli.show_image(image)
 
     @test.idempotent_id('6a5328a5-80e8-4b82-bd32-6c061f128da9')
     def test_get_shared_images(self):
@@ -47,6 +47,6 @@
         image_id = self._create_image()
         self.client.add_member(self.alt_tenant_id, image_id)
         self.client.delete_member(self.alt_tenant_id, image_id)
-        body = self.client.get_image_membership(image_id)
+        body = self.client.list_image_members(image_id)
         members = body['members']
         self.assertEqual(0, len(members), str(members))
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
index b96cf71..df0e88a 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -52,5 +52,5 @@
         # Image is hidden from another tenants.
         image_id = self._create_image()
         self.assertRaises(lib_exc.NotFound,
-                          self.alt_img_cli.get_image,
+                          self.alt_img_cli.show_image,
                           image_id)
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index ea95059..6c25c93 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -77,7 +77,7 @@
         self.assertEqual('New Http Image', body.get('name'))
         self.assertFalse(body.get('is_public'))
         self.client.wait_for_image_status(image_id, 'active')
-        self.client.get_image(image_id)
+        self.client.show_image(image_id)
 
     @test.idempotent_id('05b19d55-140c-40d0-b36b-fafd774d421b')
     def test_register_image_with_min_ram(self):
@@ -168,14 +168,14 @@
     @test.idempotent_id('246178ab-3b33-4212-9a4b-a7fe8261794d')
     def test_index_no_params(self):
         # Simple test to see all fixture images returned
-        images_list = self.client.image_list()
+        images_list = self.client.list_images()
         image_list = map(lambda x: x['id'], images_list)
         for image_id in self.created_images:
             self.assertIn(image_id, image_list)
 
     @test.idempotent_id('f1755589-63d6-4468-b098-589820eb4031')
     def test_index_disk_format(self):
-        images_list = self.client.image_list(disk_format='ami')
+        images_list = self.client.list_images(disk_format='ami')
         for image in images_list:
             self.assertEqual(image['disk_format'], 'ami')
         result_set = set(map(lambda x: x['id'], images_list))
@@ -184,7 +184,7 @@
 
     @test.idempotent_id('2143655d-96d9-4bec-9188-8674206b4b3b')
     def test_index_container_format(self):
-        images_list = self.client.image_list(container_format='bare')
+        images_list = self.client.list_images(container_format='bare')
         for image in images_list:
             self.assertEqual(image['container_format'], 'bare')
         result_set = set(map(lambda x: x['id'], images_list))
@@ -193,7 +193,7 @@
 
     @test.idempotent_id('feb32ac6-22bb-4a16-afd8-9454bb714b14')
     def test_index_max_size(self):
-        images_list = self.client.image_list(size_max=42)
+        images_list = self.client.list_images(size_max=42)
         for image in images_list:
             self.assertTrue(image['size'] <= 42)
         result_set = set(map(lambda x: x['id'], images_list))
@@ -202,7 +202,7 @@
 
     @test.idempotent_id('6ffc16d0-4cbf-4401-95c8-4ac63eac34d8')
     def test_index_min_size(self):
-        images_list = self.client.image_list(size_min=142)
+        images_list = self.client.list_images(size_min=142)
         for image in images_list:
             self.assertTrue(image['size'] >= 142)
         result_set = set(map(lambda x: x['id'], images_list))
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 32f80a2..8cccddd 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -59,7 +59,7 @@
         self.client.store_image(image_id, image_file)
 
         # Now try to get image details
-        body = self.client.get_image(image_id)
+        body = self.client.show_image(image_id)
         self.assertEqual(image_id, body['id'])
         self.assertEqual(image_name, body['name'])
         self.assertEqual(uuid, body['ramdisk_id'])
@@ -88,7 +88,7 @@
         self.client.wait_for_resource_deletion(image_id)
 
         # Verifying deletion
-        images = self.client.image_list()
+        images = self.client.list_images()
         images_id = [item['id'] for item in images]
         self.assertNotIn(image_id, images_id)
 
@@ -118,7 +118,7 @@
 
         # Verifying updating
 
-        body = self.client.get_image(image_id)
+        body = self.client.show_image(image_id)
         self.assertEqual(image_id, body['id'])
         self.assertEqual(new_image_name, body['name'])
 
@@ -164,7 +164,7 @@
         """
         Perform list action with given params and validates result.
         """
-        images_list = self.client.image_list(params=params)
+        images_list = self.client.list_images(params=params)
         # Validating params of fetched images
         for image in images_list:
             for key in params:
@@ -174,7 +174,7 @@
     @test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
     def test_index_no_params(self):
         # Simple test to see all fixture images returned
-        images_list = self.client.image_list()
+        images_list = self.client.list_images()
         image_list = map(lambda x: x['id'], images_list)
 
         for image in self.created_images:
@@ -203,7 +203,7 @@
         # Test to get all images by size
         image_id = self.created_images[1]
         # Get image metadata
-        image = self.client.get_image(image_id)
+        image = self.client.show_image(image_id)
 
         params = {"size": image['size']}
         self._list_by_param_value_and_assert(params)
@@ -213,11 +213,11 @@
         # Test to get all images with size between 2000 to 3000
         image_id = self.created_images[1]
         # Get image metadata
-        image = self.client.get_image(image_id)
+        image = self.client.show_image(image_id)
 
         size = image['size']
         params = {"size_min": size - 500, "size_max": size + 500}
-        images_list = self.client.image_list(params=params)
+        images_list = self.client.list_images(params=params)
         image_size_list = map(lambda x: x['size'], images_list)
 
         for image_size in image_size_list:
@@ -235,7 +235,7 @@
     def test_list_images_param_limit(self):
         # Test to get images by limit
         params = {"limit": 2}
-        images_list = self.client.image_list(params=params)
+        images_list = self.client.list_images(params=params)
 
         self.assertEqual(len(images_list), params['limit'],
                          "Failed to get images by limit")
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index 26d4197..07c2073 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -29,7 +29,7 @@
                                                  self.alt_tenant_id,
                                                  'accepted')
         self.assertIn(image_id, self._list_image_ids_as_alt())
-        body = self.os_img_client.get_image_membership(image_id)
+        body = self.os_img_client.list_image_members(image_id)
         members = body['members']
         member = members[0]
         self.assertEqual(len(members), 1, str(members))
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 60a10a2..c5c5e8b 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -25,7 +25,7 @@
 class ImagesNegativeTest(base.BaseV2ImageTest):
 
     """
-    here we have -ve tests for get_image and delete_image api
+    here we have -ve tests for show_image and delete_image api
 
     Tests
         ** get non-existent image
@@ -41,7 +41,7 @@
     def test_get_non_existent_image(self):
         # get the non-existent image
         non_existent_id = str(uuid.uuid4())
-        self.assertRaises(lib_exc.NotFound, self.client.get_image,
+        self.assertRaises(lib_exc.NotFound, self.client.show_image,
                           non_existent_id)
 
     @test.attr(type=['negative'])
@@ -49,7 +49,7 @@
     def test_get_image_null_id(self):
         # get image with image_id = NULL
         image_id = ""
-        self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
+        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('e57fc127-7ba0-4693-92d7-1d8a05ebcba9')
@@ -64,7 +64,7 @@
         self.client.wait_for_resource_deletion(image_id)
 
         # get the deleted image
-        self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
+        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
 
         # delete the deleted image
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
diff --git a/tempest/api/image/v2/test_images_tags.py b/tempest/api/image/v2/test_images_tags.py
index 24688dc..e38136e 100644
--- a/tempest/api/image/v2/test_images_tags.py
+++ b/tempest/api/image/v2/test_images_tags.py
@@ -31,10 +31,10 @@
 
         # Creating image tag and verify it.
         self.client.add_image_tag(image_id, tag)
-        body = self.client.get_image(image_id)
+        body = self.client.show_image(image_id)
         self.assertIn(tag, body['tags'])
 
         # Deleting image tag and verify it.
         self.client.delete_image_tag(image_id, tag)
-        body = self.client.get_image(image_id)
+        body = self.client.show_image(image_id)
         self.assertNotIn(tag, body['tags'])
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/network/base.py b/tempest/api/network/base.py
index 1cd1386..f864f95 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -123,10 +123,6 @@
             for floating_ip in cls.floating_ips:
                 cls._try_delete_resource(cls.client.delete_floatingip,
                                          floating_ip['id'])
-            # Clean up routers
-            for router in cls.routers:
-                cls._try_delete_resource(cls.delete_router,
-                                         router)
 
             # Clean up health monitors
             for health_monitor in cls.health_monitors:
@@ -158,6 +154,10 @@
             for port in cls.ports:
                 cls._try_delete_resource(cls.client.delete_port,
                                          port['id'])
+            # Clean up routers
+            for router in cls.routers:
+                cls._try_delete_resource(cls.delete_router,
+                                         router)
             # Clean up subnets
             for subnet in cls.subnets:
                 cls._try_delete_resource(cls.client.delete_subnet,
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index ca08fbd..5d798e3 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -193,13 +193,10 @@
                         self.network, **kwargs_dhcp)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
                 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
                     subnet_slaac['cidr'],
                     port_mac
                 ).format()
-                # TODO(sergsh): remove this when 1219795 is fixed
-                dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
@@ -217,11 +214,10 @@
                                  'Real IP is {0}, but shall be {1}'.format(
                                      real_eui_ip,
                                      eui_ip))
-                self.assertIn(
-                    real_dhcp_ip, dhcp_ip,
-                    'Real IP is {0}, but shall be one from {1}'.format(
-                        real_dhcp_ip,
-                        str(dhcp_ip)))
+                msg = ('Real IP address is {0} and it is NOT on '
+                       'subnet {1}'.format(real_dhcp_ip, subnet_dhcp['cidr']))
+                self.assertIn(netaddr.IPAddress(real_dhcp_ip),
+                              netaddr.IPNetwork(subnet_dhcp['cidr']), msg)
 
     @test.idempotent_id('4256c61d-c538-41ea-9147-3c450c36669e')
     def test_dhcpv6_64_subnets(self):
@@ -246,13 +242,10 @@
                         self.network, ip_version=4)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                dhcp_ip = subnet_dhcp["allocation_pools"][0]["start"]
                 eui_ip = data_utils.get_ipv6_addr_by_EUI64(
                     subnet_slaac['cidr'],
                     port_mac
                 ).format()
-                # TODO(sergsh): remove this when 1219795 is fixed
-                dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
@@ -260,23 +253,20 @@
                                              for sub in [subnet_dhcp,
                                              subnet_slaac]]
                 self._clean_network()
-                self.assertTrue({real_eui_ip,
-                                 real_dhcp_ip}.issubset([eui_ip] + dhcp_ip))
                 self.assertEqual(real_eui_ip,
                                  eui_ip,
                                  'Real IP is {0}, but shall be {1}'.format(
                                      real_eui_ip,
                                      eui_ip))
-                self.assertIn(
-                    real_dhcp_ip, dhcp_ip,
-                    'Real IP is {0}, but shall be one from {1}'.format(
-                        real_dhcp_ip,
-                        str(dhcp_ip)))
+                msg = ('Real IP address is {0} and it is NOT on '
+                       'subnet {1}'.format(real_dhcp_ip, subnet_dhcp['cidr']))
+                self.assertIn(netaddr.IPAddress(real_dhcp_ip),
+                              netaddr.IPNetwork(subnet_dhcp['cidr']), msg)
 
     @test.idempotent_id('4ab211a0-276f-4552-9070-51e27f58fecf')
     def test_dhcp_stateful(self):
-        """With all options below, DHCPv6 shall allocate first
-        address from subnet pool to port.
+        """With all options below, DHCPv6 shall allocate address
+        from subnet pool to port.
         """
         for ra_mode, add_mode in (
                 ('dhcpv6-stateful', 'dhcpv6-stateful'),
@@ -289,15 +279,11 @@
             subnet = self.create_subnet(self.network, **kwargs)
             port = self.create_port(self.network)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
-            dhcp_ip = subnet["allocation_pools"][0]["start"]
-            # TODO(sergsh): remove this when 1219795 is fixed
-            dhcp_ip = [dhcp_ip, (netaddr.IPAddress(dhcp_ip) + 1).format()]
             self._clean_network()
-            self.assertIn(
-                port_ip, dhcp_ip,
-                'Real IP is {0}, but shall be one from {1}'.format(
-                    port_ip,
-                    str(dhcp_ip)))
+            msg = ('Real IP address is {0} and it is NOT on '
+                   'subnet {1}'.format(port_ip, subnet['cidr']))
+            self.assertIn(netaddr.IPAddress(port_ip),
+                          netaddr.IPNetwork(subnet['cidr']), msg)
 
     @test.idempotent_id('51a5e97f-f02e-4e4e-9a17-a69811d300e3')
     def test_dhcp_stateful_fixedips(self):
diff --git a/tempest/api/network/test_fwaas_extensions.py b/tempest/api/network/test_fwaas_extensions.py
index 0622e87..651b4ab 100644
--- a/tempest/api/network/test_fwaas_extensions.py
+++ b/tempest/api/network/test_fwaas_extensions.py
@@ -99,8 +99,13 @@
 
         if not test.call_until_true(_wait, CONF.network.build_timeout,
                                     CONF.network.build_interval):
-            m = ("Timed out waiting for firewall %s to reach %s state(s)" %
-                 (fw_id, target_states))
+            status = self.client.show_firewall(fw_id)['firewall']['status']
+            m = ("Timed out waiting for firewall %s to reach %s state(s) "
+                 "after %ss, currently in %s state." %
+                 (fw_id,
+                  target_states,
+                  CONF.network.build_interval,
+                  status))
             raise exceptions.TimeoutException(m)
 
     @test.idempotent_id('1b84cf01-9c09-4ce7-bc72-b15e39076468')
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 5e3e374..7a96f34 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -393,7 +393,9 @@
                                       " in filtered list (%s)." % nonexternal)
         self.assertIn(CONF.network.public_network_id, networks)
 
-        subnets_iter = (network['subnets'] for network in body['networks'])
+        subnets_iter = (network['subnets']
+                        for network in body['networks']
+                        if not network['shared'])
         # subnets_iter is a list (iterator) of lists. This flattens it to a
         # list of UUIDs
         public_subnets_iter = itertools.chain(*subnets_iter)
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 7b6b25b..29600c5 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -150,6 +150,34 @@
                  if port['id'] == self.port['id']]
         self.assertNotEmpty(ports, "Created port not found in the list")
 
+    @test.idempotent_id('e7fe260b-1e79-4dd3-86d9-bec6a7959fc5')
+    def test_port_list_filter_by_ip(self):
+        # Create network and subnet
+        network = self.create_network()
+        subnet = self.create_subnet(network)
+        self.addCleanup(self.client.delete_subnet, subnet['id'])
+        # Create two ports specifying a fixed_ips
+        address = self._get_ipaddress_from_tempest_conf()
+        _fixed_ip_1 = str(address + 3)
+        _fixed_ip_2 = str(address + 4)
+        fixed_ips_1 = [{'ip_address': _fixed_ip_1}]
+        port_1 = self.client.create_port(network_id=network['id'],
+                                         fixed_ips=fixed_ips_1)
+        self.addCleanup(self.client.delete_port, port_1['port']['id'])
+        fixed_ips_2 = [{'ip_address': _fixed_ip_2}]
+        port_2 = self.client.create_port(network_id=network['id'],
+                                         fixed_ips=fixed_ips_2)
+        self.addCleanup(self.client.delete_port, port_2['port']['id'])
+        # List ports filtered by fixed_ips
+        fixed_ips = 'ip_address=' + _fixed_ip_1
+        port_list = self.client.list_ports(fixed_ips=fixed_ips)
+        ports = port_list['ports']
+        self.assertEqual(len(ports), 1)
+        self.assertEqual(ports[0]['id'], port_1['port']['id'])
+        self.assertEqual(ports[0]['fixed_ips'][0]['ip_address'],
+                         _fixed_ip_1)
+        self.assertEqual(ports[0]['network_id'], network['id'])
+
     @test.idempotent_id('5ad01ed0-0e6e-4c5d-8194-232801b15c72')
     def test_port_list_filter_by_router_id(self):
         # Create a router
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 8bc9b12..41a7d65 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
@@ -26,6 +24,8 @@
 
 class BaseObjectTest(tempest.test.BaseTestCase):
 
+    credentials = [['operator', CONF.object_storage.operator_role]]
+
     @classmethod
     def skip_checks(cls):
         super(BaseObjectTest, cls).skip_checks()
@@ -37,20 +37,9 @@
     def setup_credentials(cls):
         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]))
+        # credentials may be overwritten by children classes
+        if hasattr(cls, 'os_roles_operator'):
+            cls.os = cls.os_roles_operator
 
     @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..bbdf367 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
 
@@ -24,19 +23,14 @@
 
 class AccountQuotasTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['reseller', CONF.object_storage.reseller_admin_role]]
+
     @classmethod
     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 = cls.os_roles_operator
+        cls.os_reselleradmin = cls.os_roles_reseller
 
     @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..e945e1e 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
 
@@ -26,19 +25,14 @@
 
 class AccountQuotasNegativeTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['reseller', CONF.object_storage.reseller_admin_role]]
+
     @classmethod
     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 = cls.os_roles_operator
+        cls.os_reselleradmin = cls.os_roles_reseller
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 918bd5a..ac41148 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
@@ -30,14 +29,15 @@
 
 class AccountTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
     containers = []
 
     @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 = cls.os_roles_operator
+        cls.os_operator = cls.os_roles_operator_alt
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index feccf18..998c2bd 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
 
@@ -24,12 +23,14 @@
 
 class AccountNegativeTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
+
     @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 = cls.os_roles_operator
+        cls.os_operator = cls.os_roles_operator_alt
 
     @test.attr(type=['negative'])
     @test.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 1003f82..4df813d 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
 
@@ -25,12 +24,14 @@
 
 class ObjectTestACLs(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
+
     @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 = cls.os_roles_operator
+        cls.os_operator = cls.os_roles_operator_alt
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 2c6d3cc..1c42e97 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
 
@@ -25,12 +24,14 @@
 
 class ObjectACLsNegativeTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
+
     @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 = cls.os_roles_operator
+        cls.os_operator = cls.os_roles_operator_alt
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 53bcfa6..06e700b 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
 
@@ -38,11 +37,14 @@
 class ContainerSyncTest(base.BaseObjectTest):
     clients = {}
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
+
     @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 = cls.os_roles_operator
+        cls.os_alt = cls.os_roles_operator_alt
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 8075e91..627895e 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
@@ -990,12 +989,14 @@
 
 class PublicObjectTest(base.BaseObjectTest):
 
+    credentials = [['operator', CONF.object_storage.operator_role],
+                   ['operator_alt', CONF.object_storage.operator_role]]
+
     @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 = cls.os_roles_operator
+        cls.os_alt = cls.os_roles_operator_alt
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 7df0dde..6fc7821 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -110,6 +110,7 @@
         self.assertHeaders(resp, 'Object', method)
 
     @test.idempotent_id('2c3f24a6-36e8-4711-9aa2-800ee1fc7b5b')
+    @test.requires_ext(extension='slo', service='object')
     def test_upload_manifest(self):
         # create static large object from multipart manifest
         manifest = self._create_manifest()
@@ -124,6 +125,7 @@
         self._assertHeadersSLO(resp, 'PUT')
 
     @test.idempotent_id('e69ad766-e1aa-44a2-bdd2-bf62c09c1456')
+    @test.requires_ext(extension='slo', service='object')
     def test_list_large_object_metadata(self):
         # list static large object metadata using multipart manifest
         object_name = self._create_large_object()
@@ -135,6 +137,7 @@
         self._assertHeadersSLO(resp, 'HEAD')
 
     @test.idempotent_id('49bc49bc-dd1b-4c0f-904e-d9f10b830ee8')
+    @test.requires_ext(extension='slo', service='object')
     def test_retrieve_large_object(self):
         # list static large object using multipart manifest
         object_name = self._create_large_object()
@@ -149,6 +152,7 @@
         self.assertEqual(body, sum_data)
 
     @test.idempotent_id('87b6dfa1-abe9-404d-8bf0-6c3751e6aa77')
+    @test.requires_ext(extension='slo', service='object')
     def test_delete_large_object(self):
         # delete static large object using multipart manifest
         object_name = self._create_large_object()
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/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index d4fd3f9..dadabfa 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -31,6 +31,14 @@
             raise cls.skipException("Swift support is required")
 
     @classmethod
+    def setup_credentials(cls):
+        super(SwiftResourcesTestJSON, cls).setup_credentials()
+        stack_owner_role = CONF.orchestration.stack_owner_role
+        operator_role = CONF.object_storage.operator_role
+        cls.os = cls.get_client_manager(
+            roles=[stack_owner_role, operator_role])
+
+    @classmethod
     def setup_clients(cls):
         super(SwiftResourcesTestJSON, cls).setup_clients()
         cls.account_client = cls.os.account_client
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index b8e87f0..641317a 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from testtools import matchers
+
 from tempest.api.volume import base
 from tempest import test
 
@@ -50,12 +52,14 @@
                                                     metadata)
         # Get the metadata of the snapshot
         body = self.client.show_snapshot_metadata(self.snapshot_id)
-        self.assertEqual(metadata, body)
+        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
+
         # Delete one item metadata of the snapshot
         self.client.delete_snapshot_metadata_item(
             self.snapshot_id, "key1")
         body = self.client.show_snapshot_metadata(self.snapshot_id)
-        self.assertEqual(expected, body)
+        self.assertThat(body.items(), matchers.ContainsAll(expected.items()))
+        self.assertNotIn("key1", body)
 
     @test.idempotent_id('bd2363bc-de92-48a4-bc98-28943c6e4be1')
     def test_update_snapshot_metadata(self):
@@ -70,7 +74,8 @@
                                                     metadata)
         # Get the metadata of the snapshot
         body = self.client.show_snapshot_metadata(self.snapshot_id)
-        self.assertEqual(metadata, body)
+        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
+
         # Update metadata item
         body = self.client.update_snapshot_metadata(
             self.snapshot_id, update)
@@ -93,13 +98,13 @@
                                                     metadata)
         # Get the metadata of the snapshot
         body = self.client.show_snapshot_metadata(self.snapshot_id)
-        self.assertEqual(metadata, body)
+        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
         # Update metadata item
         body = self.client.update_snapshot_metadata_item(
             self.snapshot_id, "key3", update_item)
         # Get the metadata of the snapshot
         body = self.client.show_snapshot_metadata(self.snapshot_id)
-        self.assertEqual(expect, body)
+        self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
 
 
 class SnapshotV1MetadataTestJSON(SnapshotV2MetadataTestJSON):
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index e89ff9a..8529cfc 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -75,7 +75,7 @@
             self.volume_id, update)
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(self.volume_id)
-        self.assertThat(body.items(), matchers.ContainsAll(update.items()))
+        self.assertEqual(update, body)
 
     @test.idempotent_id('862261c5-8df4-475a-8c21-946e50e36a20')
     def test_update_volume_metadata_item(self):
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index f571f2d..375d34a 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -18,6 +18,7 @@
 from tempest.api.volume import base
 from tempest import config
 from tempest import test
+import testtools
 
 CONF = config.CONF
 
@@ -69,6 +70,18 @@
         self.client.detach_volume(self.volume['id'])
         self.client.wait_for_volume_status(self.volume['id'], 'available')
 
+    @test.idempotent_id('63e21b4c-0a0c-41f6-bfc3-7c2816815599')
+    @testtools.skipUnless(CONF.volume_feature_enabled.bootable,
+                          'Update bootable status of a volume is not enabled.')
+    def test_volume_bootable(self):
+        # Verify that a volume bootable flag is retrieved
+        for bool_bootable in [True, False]:
+            self.client.set_bootable_volume(self.volume['id'], bool_bootable)
+            fetched_volume = self.client.show_volume(self.volume['id'])
+            # Get Volume information
+            bool_flag = self._is_true(fetched_volume['bootable'])
+            self.assertEqual(bool_bootable, bool_flag)
+
     @test.idempotent_id('9516a2c8-9135-488c-8dd6-5677a7e5f371')
     @test.stresstest(class_setup_per='process')
     @test.services('compute')
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
similarity index 100%
rename from tempest/api_schema/response/compute/baremetal_nodes.py
rename to tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
diff --git a/tempest/api_schema/response/compute/v2_1/flavors.py b/tempest/api_schema/response/compute/v2_1/flavors.py
index 725d17a..26760ac 100644
--- a/tempest/api_schema/response/compute/v2_1/flavors.py
+++ b/tempest/api_schema/response/compute/v2_1/flavors.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 list_flavors = {
     'status_code': [200],
diff --git a/tempest/api_schema/response/compute/flavors_access.py b/tempest/api_schema/response/compute/v2_1/flavors_access.py
similarity index 100%
rename from tempest/api_schema/response/compute/flavors_access.py
rename to tempest/api_schema/response/compute/v2_1/flavors_access.py
diff --git a/tempest/api_schema/response/compute/flavors_extra_specs.py b/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
similarity index 94%
rename from tempest/api_schema/response/compute/flavors_extra_specs.py
rename to tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
index 4003d36..faa25d0 100644
--- a/tempest/api_schema/response/compute/flavors_extra_specs.py
+++ b/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-flavor_extra_specs = {
+set_get_flavor_extra_specs = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -28,7 +28,7 @@
     }
 }
 
-flavor_extra_specs_key = {
+set_get_flavor_extra_specs_key = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/v2_1/floating_ips.py b/tempest/api_schema/response/compute/v2_1/floating_ips.py
index 7369bec..ad1c531 100644
--- a/tempest/api_schema/response/compute/v2_1/floating_ips.py
+++ b/tempest/api_schema/response/compute/v2_1/floating_ips.py
@@ -48,7 +48,7 @@
     }
 }
 
-floating_ip = {
+create_get_floating_ip = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -59,7 +59,7 @@
     }
 }
 
-floating_ip_pools = {
+list_floating_ip_pools = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/v2_1/images.py b/tempest/api_schema/response/compute/v2_1/images.py
index 3c0b80e..e6f8db6 100644
--- a/tempest/api_schema/response/compute/v2_1/images.py
+++ b/tempest/api_schema/response/compute/v2_1/images.py
@@ -14,7 +14,7 @@
 
 import copy
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 image_links = copy.deepcopy(parameter_types.links)
 image_links['items']['properties'].update({'type': {'type': 'string'}})
diff --git a/tempest/api_schema/response/compute/v2_1/interfaces.py b/tempest/api_schema/response/compute/v2_1/interfaces.py
index 4de3309..033f816 100644
--- a/tempest/api_schema/response/compute/v2_1/interfaces.py
+++ b/tempest/api_schema/response/compute/v2_1/interfaces.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 interface_common_info = {
     'type': 'object',
diff --git a/tempest/api_schema/response/compute/migrations.py b/tempest/api_schema/response/compute/v2_1/migrations.py
similarity index 100%
rename from tempest/api_schema/response/compute/migrations.py
rename to tempest/api_schema/response/compute/v2_1/migrations.py
diff --git a/tempest/api_schema/response/compute/parameter_types.py b/tempest/api_schema/response/compute/v2_1/parameter_types.py
similarity index 100%
rename from tempest/api_schema/response/compute/parameter_types.py
rename to tempest/api_schema/response/compute/v2_1/parameter_types.py
diff --git a/tempest/api_schema/response/compute/v2_1/servers.py b/tempest/api_schema/response/compute/v2_1/servers.py
index 726f9b1..875f607 100644
--- a/tempest/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/api_schema/response/compute/v2_1/servers.py
@@ -14,7 +14,7 @@
 
 import copy
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 create_server = {
     'status_code': [202],
diff --git a/tempest/api_schema/response/compute/services.py b/tempest/api_schema/response/compute/v2_1/services.py
similarity index 100%
rename from tempest/api_schema/response/compute/services.py
rename to tempest/api_schema/response/compute/v2_1/services.py
diff --git a/tempest/api_schema/response/compute/v2_1/tenant_usages.py b/tempest/api_schema/response/compute/v2_1/tenant_usages.py
index 0b824a1..d51ef12 100644
--- a/tempest/api_schema/response/compute/v2_1/tenant_usages.py
+++ b/tempest/api_schema/response/compute/v2_1/tenant_usages.py
@@ -66,7 +66,7 @@
                                  'total_hours', 'total_local_gb_usage',
                                  'total_memory_mb_usage', 'total_vcpus_usage']
 
-list_tenant = {
+list_tenant_usage = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -80,7 +80,7 @@
     }
 }
 
-get_tenant = {
+get_tenant_usage = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/version.py b/tempest/api_schema/response/compute/v2_1/version.py
similarity index 100%
rename from tempest/api_schema/response/compute/version.py
rename to tempest/api_schema/response/compute/v2_1/version.py
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/javelin.py b/tempest/cmd/javelin.py
index 4e2af76..d3426c6 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -617,7 +617,7 @@
 
 
 def _get_image_by_name(client, name):
-    body = client.images.image_list()
+    body = client.images.list_images()
     for image in body:
         if name == image['name']:
             return image
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 70a8594..f51d9aa 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -94,7 +94,7 @@
         versions = map(lambda x: x['id'], body['versions']['values'])
     else:
         versions = map(lambda x: x['id'], body['versions'])
-    return versions
+    return list(versions)
 
 
 def verify_keystone_api_versions(os, update):
@@ -175,6 +175,7 @@
 
     else:
         extensions = map(lambda x: x['alias'], resp)
+    extensions = list(extensions)
     if not results.get(service):
         results[service] = {}
     extensions_opt = get_enabled_extensions(service)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 1f85872..5ded3ee 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -311,7 +311,8 @@
             LOG.info("Acquired isolated creds:\n credentials: %s"
                      % credentials)
             if (CONF.service_available.neutron and
-                not CONF.baremetal.driver_enabled):
+                not CONF.baremetal.driver_enabled and
+                CONF.auth.create_isolated_networks):
                 network, subnet, router = self._create_network_resources(
                     credentials.tenant_id)
                 credentials.set_resources(network=network, subnet=subnet,
@@ -413,7 +414,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/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index bedff1f..4b3995b 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -46,6 +46,9 @@
                                      channel_timeout=ssh_channel_timeout)
 
     def exec_command(self, cmd):
+        # Shell options below add more clearness on failures,
+        # path is extended for some non-cirros guest oses (centos7)
+        cmd = "set -eu -o pipefail; PATH=$PATH:/sbin; " + cmd
         return self.ssh_client.exec_command(cmd)
 
     def validate_authentication(self):
@@ -95,26 +98,26 @@
         return self.exec_command(cmd)
 
     def get_mac_address(self):
-        cmd = "/bin/ip addr | awk '/ether/ {print $2}'"
+        cmd = "ip addr | awk '/ether/ {print $2}'"
         return self.exec_command(cmd)
 
     def get_nic_name(self, address):
-        cmd = "/bin/ip -o addr | awk '/%s/ {print $2}'" % address
+        cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
         return self.exec_command(cmd)
 
     def get_ip_list(self):
-        cmd = "/bin/ip address"
+        cmd = "ip address"
         return self.exec_command(cmd)
 
     def assign_static_ip(self, nic, addr):
-        cmd = "sudo /bin/ip addr add {ip}/{mask} dev {nic}".format(
+        cmd = "sudo ip addr add {ip}/{mask} dev {nic}".format(
             ip=addr, mask=CONF.network.tenant_network_mask_bits,
             nic=nic
         )
         return self.exec_command(cmd)
 
     def turn_nic_on(self, nic):
-        cmd = "sudo /bin/ip link set {nic} up".format(nic=nic)
+        cmd = "sudo ip link set {nic} up".format(nic=nic)
         return self.exec_command(cmd)
 
     def get_pids(self, pr_name):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 64ff7f2..249bac9 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -99,15 +99,15 @@
 def wait_for_image_status(client, image_id, status):
     """Waits for an image to reach a given status.
 
-    The client should have a get_image(image_id) method to get the image.
+    The client should have a show_image(image_id) method to get the image.
     The client should also have build_interval and build_timeout attributes.
     """
-    image = client.get_image(image_id)
+    image = client.show_image(image_id)
     start = int(time.time())
 
     while image['status'] != status:
         time.sleep(client.build_interval)
-        image = client.get_image(image_id)
+        image = client.show_image(image_id)
         status_curr = image['status']
         if status_curr == 'ERROR':
             raise exceptions.AddImageException(image_id=image_id)
diff --git a/tempest/config.py b/tempest/config.py
index a711b33..bbd6772 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -69,7 +69,15 @@
                help="Only applicable when identity.auth_version is v3."
                     "Domain within which isolated credentials are provisioned."
                     "The default \"None\" means that the domain from the"
-                    "admin user is used instead.")
+                    "admin user is used instead."),
+    cfg.BoolOpt('create_isolated_networks',
+                default=True,
+                help="If allow_tenant_isolation is set to True and Neutron is "
+                     "enabled Tempest will try to create a useable network, "
+                     "subnet, and router when needed for each tenant it  "
+                     "creates. However in some neutron configurations, like "
+                     "with VLAN provider networks, this doesn't work. So if "
+                     "set to False the isolated networks will not be created"),
 ]
 
 identity_group = cfg.OptGroup(name='identity',
@@ -142,6 +150,9 @@
     cfg.StrOpt('admin_domain_name',
                help="Admin domain name for authentication (Keystone V3)."
                     "The same domain applies to user and project"),
+    cfg.StrOpt('default_domain_id',
+               default='default',
+               help="ID of the default domain"),
 ]
 
 identity_feature_group = cfg.OptGroup(name='identity-feature-enabled',
@@ -195,9 +206,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 +257,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 +566,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'],
@@ -654,6 +668,10 @@
     cfg.BoolOpt('api_v2',
                 default=True,
                 help="Is the v2 volume API enabled"),
+    cfg.BoolOpt('bootable',
+                default=False,
+                help='Update bootable status of a volume '
+                     'Not implemented on icehouse ')
 ]
 
 
@@ -940,6 +958,8 @@
     cfg.StrOpt('img_container_format',
                default='bare',
                help='Image container format'),
+    cfg.DictOpt('img_properties', help='Glance image properties. '
+                'Use for custom images which require them'),
     cfg.StrOpt('ami_img_file',
                default='cirros-0.3.1-x86_64-blank.img',
                help='AMI image file name'),
@@ -1094,8 +1114,10 @@
                default=60,
                help="Timeout for Ironic power transitions."),
     cfg.IntOpt('unprovision_timeout',
-               default=60,
-               help="Timeout for unprovisioning an Ironic node.")
+               default=300,
+               help="Timeout for unprovisioning an Ironic node. "
+                    "Takes longer since Kilo as Ironic performs an extra "
+                    "step in Node cleaning.")
 ]
 
 negative_group = cfg.OptGroup(name='negative', title="Negative Test Options")
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7e0c3b3..5f8d605 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -20,9 +20,9 @@
 from oslo_log import log
 import six
 from tempest_lib.common.utils import data_utils
+from tempest_lib.common.utils import misc as misc_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
@@ -308,8 +308,13 @@
                                                   password=password)
         try:
             linux_client.validate_authentication()
-        except Exception:
-            LOG.exception('Initializing SSH connection to %s failed' % ip)
+        except Exception as e:
+            message = ('Initializing SSH connection to %(ip)s failed. '
+                       'Error: %(error)s' % {'ip': ip, 'error': e})
+            caller = misc_utils.find_test_caller()
+            if caller:
+                message = '(%s) %s' % (caller, message)
+            LOG.exception(message)
             # If we don't explicitly set for which servers we want to
             # log the console output then all the servers will be logged.
             # See the definition of _log_console_output()
@@ -318,7 +323,8 @@
 
         return linux_client
 
-    def _image_create(self, name, fmt, path, properties=None):
+    def _image_create(self, name, fmt, path,
+                      disk_format=None, properties=None):
         if properties is None:
             properties = {}
         name = data_utils.rand_name('%s-' % name)
@@ -327,10 +333,10 @@
         params = {
             'name': name,
             'container_format': fmt,
-            'disk_format': fmt,
+            'disk_format': disk_format or fmt,
             'is_public': 'False',
         }
-        params.update(properties)
+        params['properties'] = properties
         image = self.image_client.create_image(**params)
         self.addCleanup(self.image_client.delete_image, image['id'])
         self.assertEqual("queued", image['status'])
@@ -344,23 +350,22 @@
         ami_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ami_img_file
         img_container_format = CONF.scenario.img_container_format
         img_disk_format = CONF.scenario.img_disk_format
+        img_properties = CONF.scenario.img_properties
         LOG.debug("paths: img: %s, container_fomat: %s, disk_format: %s, "
-                  "ami: %s, ari: %s, aki: %s" %
+                  "properties: %s, ami: %s, ari: %s, aki: %s" %
                   (img_path, img_container_format, img_disk_format,
-                   ami_img_path, ari_img_path, aki_img_path))
+                   img_properties, ami_img_path, ari_img_path, aki_img_path))
         try:
             self.image = self._image_create('scenario-img',
                                             img_container_format,
                                             img_path,
-                                            properties={'disk_format':
-                                                        img_disk_format})
+                                            disk_format=img_disk_format,
+                                            properties=img_properties)
         except IOError:
             LOG.debug("A qcow2 image was not found. Try to get a uec image.")
             kernel = self._image_create('scenario-aki', 'aki', aki_img_path)
             ramdisk = self._image_create('scenario-ari', 'ari', ari_img_path)
-            properties = {
-                'properties': {'kernel_id': kernel, 'ramdisk_id': ramdisk}
-            }
+            properties = {'kernel_id': kernel, 'ramdisk_id': ramdisk}
             self.image = self._image_create('scenario-ami', 'ami',
                                             path=ami_img_path,
                                             properties=properties)
@@ -408,9 +413,9 @@
         return snapshot_image
 
     def nova_volume_attach(self):
-        # TODO(andreaf) Device should be here CONF.compute.volume_device_name
         volume = self.servers_client.attach_volume(
-            self.server['id'], self.volume['id'], '/dev/vdb')
+            self.server['id'], self.volume['id'], '/dev/%s'
+            % CONF.compute.volume_device_name)
         self.assertEqual(self.volume['id'], volume['id'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
         # Refresh the volume after the attachment
@@ -986,7 +991,7 @@
         router_id = CONF.network.public_router_id
         network_id = CONF.network.public_network_id
         if router_id:
-            resp, body = client.show_router(router_id)
+            body = client.show_router(router_id)
             return net_resources.AttributeDict(**body['router'])
         elif network_id:
             router = self._create_router(client, tenant_id)
@@ -1341,15 +1346,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_large_ops.py b/tempest/scenario/test_large_ops.py
index 0789c21..56d4c7d 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -17,6 +17,7 @@
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
+from tempest.common import fixed_network
 from tempest import config
 from tempest.scenario import manager
 from tempest import test
@@ -87,13 +88,18 @@
             'secgroup-%s' % name, 'secgroup-desc-%s' % name)
         self.addCleanupClass(self.security_groups_client.delete_security_group,
                              secgroup['id'])
-
+        create_kwargs = {
+            'min_count': CONF.scenario.large_ops_number,
+            'security_groups': [{'name': secgroup['name']}]
+            }
+        network = self.get_tenant_network()
+        create_kwargs = fixed_network.set_networks_kwarg(network,
+                                                         create_kwargs)
         self.servers_client.create_server(
             name,
             self.image,
             flavor_id,
-            min_count=CONF.scenario.large_ops_number,
-            security_groups=[{'name': secgroup['name']}])
+            **create_kwargs)
         # needed because of bug 1199788
         params = {'name': name}
         server_list = self.servers_client.list_servers(params)
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..d9918f3 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -48,7 +48,7 @@
             self.image_ref = CONF.compute.image_ref
         if not hasattr(self, 'flavor_ref'):
             self.flavor_ref = CONF.compute.flavor_ref
-        self.image_utils = test_utils.ImageUtils()
+        self.image_utils = test_utils.ImageUtils(self.manager)
         if not self.image_utils.is_flavor_enough(self.flavor_ref,
                                                  self.image_ref):
             raise self.skipException(
@@ -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/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 53b471a..51c4c59 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -103,9 +103,9 @@
         return self.create_volume(snapshot_id=snapshot_id)
 
     def _attach_volume(self, server, volume):
-        # TODO(andreaf) we should use device from config instead if vdb
         attached_volume = self.servers_client.attach_volume(
-            server['id'], volume['id'], device='/dev/vdb')
+            server['id'], volume['id'], device='/dev/%s'
+            % CONF.compute.volume_device_name)
         self.assertEqual(volume['id'], attached_volume['id'])
         self._wait_for_volume_status(attached_volume, 'in-use')
 
@@ -119,7 +119,7 @@
         def _func():
             part = ssh.get_partitions()
             LOG.debug("Partitions:%s" % part)
-            return 'vdb' in part
+            return CONF.compute.volume_device_name in part
 
         if not tempest.test.call_until_true(_func,
                                             CONF.compute.build_timeout,
@@ -128,15 +128,18 @@
 
     def _create_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
-        ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/vdb')
-        ssh_client.exec_command('sudo mount /dev/vdb /mnt')
+        ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/%s'
+                                % CONF.compute.volume_device_name)
+        ssh_client.exec_command('sudo mount /dev/%s /mnt'
+                                % CONF.compute.volume_device_name)
         ssh_client.exec_command('sudo sh -c "date > /mnt/timestamp;sync"')
         self.timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         ssh_client.exec_command('sudo umount /mnt')
 
     def _check_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
-        ssh_client.exec_command('sudo mount /dev/vdb /mnt')
+        ssh_client.exec_command('sudo mount /dev/%s /mnt'
+                                % CONF.compute.volume_device_name)
         got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         self.assertEqual(self.timestamp, got_timestamp)
 
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 177697b..1731c48 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -41,8 +41,6 @@
         super(TestVolumeBootPattern, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
-        if CONF.volume.storage_protocol == 'ceph':
-            raise cls.skipException('Skip until bug 1439371 is fixed.')
 
     def _create_volume_from_image(self):
         img_uuid = CONF.compute.image_ref
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 60eb1c3..f8d9dd4 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -30,26 +30,21 @@
 CONF = config.CONF
 
 
-@misc.singleton
 class ImageUtils(object):
 
     default_ssh_user = 'root'
 
-    def __init__(self):
+    def __init__(self, os):
         # Load configuration items
         self.ssh_users = json.loads(CONF.input_scenario.ssh_user_regex)
         self.non_ssh_image_pattern = \
             CONF.input_scenario.non_ssh_image_regex
         # Setup clients
-        self.isolated_creds = credentials.get_isolated_credentials(
-            name='ScenarioImageUtils',
-            identity_version=CONF.identity.auth_version)
-        os = clients.Manager(self.isolated_creds.get_primary_creds())
         self.images_client = os.images_client
         self.flavors_client = os.flavors_client
 
     def ssh_user(self, image_id):
-        _image = self.images_client.get_image(image_id)
+        _image = self.images_client.show_image(image_id)
         for regex, user in self.ssh_users:
             # First match wins
             if re.match(regex, _image['name']) is not None:
@@ -62,14 +57,14 @@
                              string=str(image['name']))
 
     def is_sshable_image(self, image_id):
-        _image = self.images_client.get_image(image_id)
+        _image = self.images_client.show_image(image_id)
         return self._is_sshable_image(_image)
 
     def _is_flavor_enough(self, flavor, image):
         return image['minDisk'] <= flavor['disk']
 
     def is_flavor_enough(self, flavor_id, image_id):
-        _image = self.images_client.get_image(image_id)
+        _image = self.images_client.show_image(image_id)
         _flavor = self.flavors_client.get_flavor_details(flavor_id)
         return self._is_flavor_enough(_flavor, _image)
 
@@ -103,9 +98,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
@@ -117,6 +119,9 @@
         nname = ''.join(c for c in nname if c in self.validchars)
         return nname
 
+    def clear_creds(self):
+        self.isolated_creds.clear_isolated_creds()
+
     @property
     def scenario_images(self):
         """
@@ -163,12 +168,19 @@
         loader, standard_tests, pattern = args
     else:
         standard_tests, module, loader = args
+    output = None
+    scenario_utils = None
     try:
         scenario_utils = InputScenarioUtils()
         scenario_flavor = scenario_utils.scenario_flavors
         scenario_image = scenario_utils.scenario_images
     except (exceptions.InvalidConfiguration, TypeError):
-        return standard_tests
+        output = standard_tests
+    finally:
+        if scenario_utils:
+            scenario_utils.clear_creds()
+    if output is not None:
+        return output
     for test in testtools.iterate_tests(standard_tests):
         setattr(test, 'scenarios', testscenarios.multiply_scenarios(
             scenario_image,
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
index fa2d7f4..d8f13c4 100644
--- a/tempest/services/compute/json/baremetal_nodes_client.py
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -16,7 +16,8 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import baremetal_nodes as schema
+from tempest.api_schema.response.compute.v2_1 import baremetal_nodes \
+    as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 80cbe4d..7938d8e 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -17,10 +17,11 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import flavors_access as schema_access
-from tempest.api_schema.response.compute import flavors_extra_specs \
-    as schema_extra_specs
 from tempest.api_schema.response.compute.v2_1 import flavors as schema
+from tempest.api_schema.response.compute.v2_1 import flavors_access \
+    as schema_access
+from tempest.api_schema.response.compute.v2_1 import flavors_extra_specs \
+    as schema_extra_specs
 from tempest.common import service_client
 
 
@@ -103,7 +104,7 @@
         resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
                                post_body)
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs,
+        self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
@@ -111,7 +112,7 @@
         """Gets extra Specs details of the mentioned flavor."""
         resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs,
+        self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
@@ -120,8 +121,9 @@
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                               key))
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs_key,
-                               resp, body)
+        self.validate_response(
+            schema_extra_specs.set_get_flavor_extra_specs_key,
+            resp, body)
         return service_client.ResponseBody(resp, body)
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
@@ -129,8 +131,9 @@
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key), json.dumps(kwargs))
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs_key,
-                               resp, body)
+        self.validate_response(
+            schema_extra_specs.set_get_flavor_extra_specs_key,
+            resp, body)
         return service_client.ResponseBody(resp, body)
 
     def unset_flavor_extra_spec(self, flavor_id, key):
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 9568a5e..f30bfdb 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -40,7 +40,7 @@
         url = "os-floating-ips/%s" % str(floating_ip_id)
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip, resp, body)
+        self.validate_response(schema.create_get_floating_ip, resp, body)
         return service_client.ResponseBody(resp, body['floating_ip'])
 
     def create_floating_ip(self, pool_name=None):
@@ -50,7 +50,7 @@
         post_body = json.dumps(post_body)
         resp, body = self.post(url, post_body)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip, resp, body)
+        self.validate_response(schema.create_get_floating_ip, resp, body)
         return service_client.ResponseBody(resp, body['floating_ip'])
 
     def delete_floating_ip(self, floating_ip_id):
@@ -108,7 +108,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip_pools, resp, body)
+        self.validate_response(schema.list_floating_ip_pools, resp, body)
         return service_client.ResponseBodyList(resp, body['floating_ip_pools'])
 
     def create_floating_ips_bulk(self, ip_range, pool, interface):
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index 5462efc..30aa962 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -65,7 +65,7 @@
         self.validate_response(schema.list_images_details, resp, body)
         return service_client.ResponseBodyList(resp, body['images'])
 
-    def get_image(self, image_id):
+    def show_image(self, image_id):
         """Returns the details of a single image."""
         resp, body = self.get("images/%s" % str(image_id))
         self.expected_success(200, resp.status)
@@ -131,7 +131,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_image(id)
+            self.show_image(id)
         except lib_exc.NotFound:
             return True
         return False
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index 009992c..f708a07 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -16,7 +16,7 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import migrations as schema
+from tempest.api_schema.response.compute.v2_1 import migrations as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index e2d959b..156ad8d 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -18,7 +18,7 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import services as schema
+from tempest.api_schema.response.compute.v2_1 import services as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index b7e2b2a..52f46e2 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -30,7 +30,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.list_tenant, resp, body)
+        self.validate_response(schema.list_tenant_usage, resp, body)
         return service_client.ResponseBodyList(resp, body['tenant_usages'][0])
 
     def get_tenant_usage(self, tenant_id, params=None):
@@ -40,5 +40,5 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.get_tenant, resp, body)
+        self.validate_response(schema.get_tenant_usage, resp, body)
         return service_client.ResponseBodyList(resp, body['tenant_usage'])
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index 5e442fa..7c58f01 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -201,7 +201,7 @@
         self.expected_success(200, resp.status)
         return service_client.ResponseBody(resp, body)
 
-    def image_list(self, **kwargs):
+    def list_images(self, **kwargs):
         url = 'v1/images'
 
         if len(kwargs) > 0:
@@ -240,7 +240,7 @@
         body = self._image_meta_from_headers(resp)
         return service_client.ResponseBody(resp, body)
 
-    def get_image(self, image_id):
+    def show_image(self, image_id):
         url = 'v1/images/%s' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
@@ -258,7 +258,7 @@
         """Returns the primary type of resource this client works with."""
         return 'image_meta'
 
-    def get_image_membership(self, image_id):
+    def list_image_members(self, image_id):
         url = 'v1/images/%s/members' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index aff8e85..a4cb48c 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -102,7 +102,7 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp)
 
-    def image_list(self, params=None):
+    def list_images(self, params=None):
         url = 'v2/images'
 
         if params:
@@ -114,7 +114,7 @@
         self._validate_schema(body, type='images')
         return service_client.ResponseBodyList(resp, body['images'])
 
-    def get_image(self, image_id):
+    def show_image(self, image_id):
         url = 'v2/images/%s' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
@@ -123,7 +123,7 @@
 
     def is_resource_deleted(self, id):
         try:
-            self.get_image(id)
+            self.show_image(id)
         except lib_exc.NotFound:
             return True
         return False
@@ -159,7 +159,7 @@
         self.expected_success(204, resp.status)
         return service_client.ResponseBody(resp)
 
-    def get_image_membership(self, image_id):
+    def list_image_members(self, image_id):
         url = 'v2/images/%s/members' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 9a08bbd..65aa0f4 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -123,6 +123,15 @@
         self.expected_success(202, resp.status)
         return service_client.ResponseBody(resp, body)
 
+    def set_bootable_volume(self, volume_id, bootable):
+        """set a bootable flag for a volume - true or false."""
+        post_body = {"bootable": bootable}
+        post_body = json.dumps({'os-set_bootable': post_body})
+        url = 'volumes/%s/action' % (volume_id)
+        resp, body = self.post(url, post_body)
+        self.expected_success(200, resp.status)
+        return service_client.ResponseBody(resp, body)
+
     def detach_volume(self, volume_id):
         """Detaches a volume from an instance."""
         post_body = {}
diff --git a/tempest/test.py b/tempest/test.py
index 2d5e94a..0d709f6c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -230,7 +230,9 @@
     _service = None
 
     # NOTE(andreaf) credentials holds a list of the credentials to be allocated
-    # at class setup time. Credential types can be 'primary', 'alt' or 'admin'
+    # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
+    # a list of roles - the first element of the list being a label, and the
+    # rest the actual roles
     credentials = []
     # Resources required to validate a server using ssh
     validation_resources = {}
@@ -267,7 +269,7 @@
                      etype, cls.__name__))
             cls.tearDownClass()
             try:
-                raise etype, value, trace
+                six.reraise(etype, value, trace)
             finally:
                 del trace  # to avoid circular refs
 
@@ -305,7 +307,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,9 +324,16 @@
         if 'admin' in cls.credentials and not credentials.is_admin_available():
             msg = "Missing Identity Admin API credentials in configuration."
             raise cls.skipException(msg)
-        if 'alt' is cls.credentials and not credentials.is_alt_available():
+        if 'alt' in 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):
@@ -337,19 +346,24 @@
             # This may raise an exception in case credentials are not available
             # In that case we want to let the exception through and the test
             # fail accordingly
-            manager = cls.get_client_manager(
-                credential_type=credentials_type)
-            setattr(cls, 'os_%s' % credentials_type, manager)
-            # Setup some common aliases
-            # TODO(andreaf) The aliases below are a temporary hack
-            # to avoid changing too much code in one patch. They should
-            # be removed eventually
-            if credentials_type == 'primary':
-                cls.os = cls.manager = cls.os_primary
-            if credentials_type == 'admin':
-                cls.os_adm = cls.admin_manager = cls.os_admin
-            if credentials_type == 'alt':
-                cls.alt_manager = cls.os_alt
+            if isinstance(credentials_type, six.string_types):
+                manager = cls.get_client_manager(
+                    credential_type=credentials_type)
+                setattr(cls, 'os_%s' % credentials_type, manager)
+                # Setup some common aliases
+                # TODO(andreaf) The aliases below are a temporary hack
+                # to avoid changing too much code in one patch. They should
+                # be removed eventually
+                if credentials_type == 'primary':
+                    cls.os = cls.manager = cls.os_primary
+                if credentials_type == 'admin':
+                    cls.os_adm = cls.admin_manager = cls.os_admin
+                if credentials_type == 'alt':
+                    cls.alt_manager = cls.os_alt
+            elif isinstance(credentials_type, list):
+                manager = cls.get_client_manager(roles=credentials_type[1:],
+                                                 force_new=True)
+                setattr(cls, 'os_roles_%s' % credentials_type[0], manager)
 
     @classmethod
     def setup_clients(cls):
@@ -414,39 +428,78 @@
                                                    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,
@@ -464,6 +517,8 @@
         @param security_group_rules
         @param floating_ip
         """
+        if not CONF.validation.run_validation:
+            return
         if keypair is None:
             if CONF.validation.auth_method.lower() == "keypair":
                 keypair = True
@@ -514,16 +569,16 @@
         """
         # Make sure isolated_creds exists and get a network client
         networks_client = cls.get_client_manager().networks_client
-        isolated_creds = getattr(cls, 'isolated_creds', None)
+        cred_provider = cls._get_credentials_provider()
         # In case of nova network, isolated tenants are not able to list the
         # network configured in fixed_network_name, even if the can use it
         # for their servers, so using an admin network client to validate
         # the network name
         if (not CONF.service_available.neutron and
                 credentials.is_admin_available()):
-            admin_creds = isolated_creds.get_admin_creds()
+            admin_creds = cred_provider.get_admin_creds()
             networks_client = clients.Manager(admin_creds).networks_client
-        return fixed_network.get_tenant_network(isolated_creds,
+        return fixed_network.get_tenant_network(cred_provider,
                                                 networks_client)
 
     def assertEmpty(self, list, msg=None):
@@ -673,7 +728,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/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
new file mode 100644
index 0000000..f98f8ba
--- /dev/null
+++ b/tempest/tests/cmd/test_javelin.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+#
+#    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 mock
+from oslotest import mockpatch
+from tempest_lib import exceptions as lib_exc
+
+from tempest.cmd import javelin
+from tempest.tests import base
+
+
+class JavelinUnitTest(base.TestCase):
+
+    def setUp(self):
+        super(JavelinUnitTest, self).setUp()
+        javelin.setup_logging()
+        self.fake_client = mock.MagicMock()
+        self.fake_object = mock.MagicMock()
+
+    def test_load_resources(self):
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True) as open_mock:
+            with mock.patch('yaml.load', mock.MagicMock(),
+                            create=True) as load_mock:
+                javelin.load_resources(self.fake_object)
+                load_mock.assert_called_once_with(open_mock(self.fake_object))
+
+    def test_keystone_admin(self):
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.OPTS = self.fake_object
+        javelin.keystone_admin()
+        javelin.OSClient.assert_called_once_with(
+            self.fake_object.os_username,
+            self.fake_object.os_password,
+            self.fake_object.os_tenant_name)
+
+    def test_client_for_user(self):
+        fake_user = mock.MagicMock()
+        javelin.USERS = {fake_user['name']: fake_user}
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.client_for_user(fake_user['name'])
+        javelin.OSClient.assert_called_once_with(
+            fake_user['name'], fake_user['pass'], fake_user['tenant'])
+
+    def test_client_for_non_existing_user(self):
+        fake_non_existing_user = self.fake_object
+        fake_user = mock.MagicMock()
+        javelin.USERS = {fake_user['name']: fake_user}
+        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
+        javelin.client_for_user(fake_non_existing_user['name'])
+        self.assertFalse(javelin.OSClient.called)
+
+
+class TestCreateResources(JavelinUnitTest):
+    def test_create_tenants(self):
+
+        self.fake_client.identity.list_tenants.return_value = []
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=self.fake_client))
+
+        javelin.create_tenants([self.fake_object['name']])
+
+        mocked_function = self.fake_client.identity.create_tenant
+        mocked_function.assert_called_once_with(self.fake_object['name'])
+
+    def test_create_duplicate_tenant(self):
+        self.fake_client.identity.list_tenants.return_value = [
+            {'name': self.fake_object['name']}]
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=self.fake_client))
+
+        javelin.create_tenants([self.fake_object['name']])
+
+        mocked_function = self.fake_client.identity.create_tenant
+        self.assertFalse(mocked_function.called)
+
+    def test_create_users(self):
+        self.fake_client.identity.get_tenant_by_name.return_value = \
+            self.fake_object['tenant']
+        self.fake_client.identity.get_user_by_username.side_effect = \
+            lib_exc.NotFound()
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=self.fake_client))
+
+        javelin.create_users([self.fake_object])
+
+        fake_tenant_id = self.fake_object['tenant']['id']
+        fake_email = "%s@%s" % (self.fake_object['user'], fake_tenant_id)
+        mocked_function = self.fake_client.identity.create_user
+        mocked_function.assert_called_once_with(self.fake_object['name'],
+                                                self.fake_object['password'],
+                                                fake_tenant_id,
+                                                fake_email,
+                                                enabled=True)
+
+    def test_create_user_missing_tenant(self):
+        self.fake_client.identity.get_tenant_by_name.side_effect = \
+            lib_exc.NotFound()
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=self.fake_client))
+
+        javelin.create_users([self.fake_object])
+
+        mocked_function = self.fake_client.identity.create_user
+        self.assertFalse(mocked_function.called)
+
+    def test_create_objects(self):
+
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=self.fake_client))
+        self.useFixture(mockpatch.PatchObject(javelin, "_assign_swift_role"))
+        self.useFixture(mockpatch.PatchObject(javelin, "_file_contents",
+                        return_value=self.fake_object.content))
+
+        javelin.create_objects([self.fake_object])
+
+        mocked_function = self.fake_client.containers.create_container
+        mocked_function.assert_called_once_with(self.fake_object['container'])
+        mocked_function = self.fake_client.objects.create_object
+        mocked_function.assert_called_once_with(self.fake_object['container'],
+                                                self.fake_object['name'],
+                                                self.fake_object.content)
+
+    def test_create_images(self):
+        self.fake_client.images.create_image.return_value = \
+            self.fake_object['body']
+
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=self.fake_client))
+        self.useFixture(mockpatch.PatchObject(javelin, "_get_image_by_name",
+                                              return_value=[]))
+        self.useFixture(mockpatch.PatchObject(javelin, "_resolve_image",
+                                              return_value=(None, None)))
+
+        with mock.patch('six.moves.builtins.open', mock.mock_open(),
+                        create=True) as open_mock:
+            javelin.create_images([self.fake_object])
+
+        mocked_function = self.fake_client.images.create_image
+        mocked_function.assert_called_once_with(self.fake_object['name'],
+                                                self.fake_object['format'],
+                                                self.fake_object['format'])
+
+        mocked_function = self.fake_client.images.store_image
+        fake_image_id = self.fake_object['body'].get('id')
+        mocked_function.assert_called_once_with(fake_image_id, open_mock())
+
+    def test_create_networks(self):
+        self.fake_client.networks.list_networks.return_value = {
+            'networks': []}
+
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=self.fake_client))
+
+        javelin.create_networks([self.fake_object])
+
+        mocked_function = self.fake_client.networks.create_network
+        mocked_function.assert_called_once_with(name=self.fake_object['name'])
+
+    def test_create_subnet(self):
+
+        fake_network = self.fake_object['network']
+
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=self.fake_client))
+        self.useFixture(mockpatch.PatchObject(javelin, "_get_resource_by_name",
+                                              return_value=fake_network))
+
+        fake_netaddr = mock.MagicMock()
+        self.useFixture(mockpatch.PatchObject(javelin, "netaddr",
+                                              return_value=fake_netaddr))
+        fake_version = javelin.netaddr.IPNetwork().version
+
+        javelin.create_subnets([self.fake_object])
+
+        mocked_function = self.fake_client.networks.create_subnet
+        mocked_function.assert_called_once_with(network_id=fake_network['id'],
+                                                cidr=self.fake_object['range'],
+                                                name=self.fake_object['name'],
+                                                ip_version=fake_version)
+
+
+class TestDestroyResources(JavelinUnitTest):
+
+    def test_destroy_tenants(self):
+
+        fake_tenant = self.fake_object['tenant']
+
+        fake_auth = mock.MagicMock()
+        fake_auth.identity.get_tenant_by_name.return_value = fake_tenant
+
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=fake_auth))
+        javelin.destroy_tenants([fake_tenant])
+
+        mocked_function = fake_auth.identity.delete_tenant
+        mocked_function.assert_called_once_with(fake_tenant['id'])
+
+    def test_destroy_users(self):
+
+        fake_user = self.fake_object['user']
+        fake_tenant = self.fake_object['tenant']
+
+        fake_auth = mock.MagicMock()
+        fake_auth.identity.get_tenant_by_name.return_value = fake_tenant
+        fake_auth.identity.get_user_by_username.return_value = fake_user
+
+        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
+                                              return_value=fake_auth))
+
+        javelin.destroy_users([fake_user])
+
+        mocked_function = fake_auth.identity.delete_user
+        mocked_function.assert_called_once_with(fake_user['id'])
+
+    def test_destroy_objects(self):
+
+        fake_client = mock.MagicMock()
+        fake_client.objects.delete_object.return_value = {'status': "200"}, ""
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=fake_client))
+        javelin.destroy_objects([self.fake_object])
+
+        mocked_function = fake_client.objects.delete_object
+        mocked_function.asswert_called_once(self.fake_object['container'],
+                                            self.fake_object['name'])
+
+    def test_destroy_images(self):
+
+        fake_client = mock.MagicMock()
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=fake_client))
+        self.useFixture(mockpatch.PatchObject(javelin, "_get_image_by_name",
+                        return_value=self.fake_object['image']))
+
+        javelin.destroy_images([self.fake_object])
+
+        mocked_function = fake_client.images.delete_image
+        mocked_function.assert_called_once_with(
+            self.fake_object['image']['id'])
+
+    def test_destroy_networks(self):
+
+        fake_client = mock.MagicMock()
+        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
+                                              return_value=fake_client))
+        self.useFixture(mockpatch.PatchObject(
+            javelin, "_get_resource_by_name",
+            return_value=self.fake_object['resource']))
+
+        javelin.destroy_networks([self.fake_object])
+
+        mocked_function = fake_client.networks.delete_network
+        mocked_function.assert_called_once_with(
+            self.fake_object['resource']['id'])
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/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index d6377e6..3506856 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -73,6 +73,7 @@
     # the information using gnu/linux tools.
 
     def _assert_exec_called_with(self, cmd):
+        cmd = "set -eu -o pipefail; PATH=$PATH:/sbin; " + cmd
         self.ssh_mock.mock.exec_command.assert_called_with(cmd)
 
     def test_get_number_of_vcpus(self):
@@ -119,7 +120,7 @@
 
         self.assertEqual(self.conn.get_mac_address(), macs)
         self._assert_exec_called_with(
-            "/bin/ip addr | awk '/ether/ {print $2}'")
+            "ip addr | awk '/ether/ {print $2}'")
 
     def test_get_ip_list(self):
         ips = """1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
@@ -136,7 +137,7 @@
        valid_lft forever preferred_lft forever"""
         self.ssh_mock.mock.exec_command.return_value = ips
         self.assertEqual(self.conn.get_ip_list(), ips)
-        self._assert_exec_called_with('/bin/ip address')
+        self._assert_exec_called_with('ip address')
 
     def test_assign_static_ip(self):
         self.ssh_mock.mock.exec_command.return_value = ''
@@ -144,9 +145,10 @@
         nic = 'eth0'
         self.assertEqual(self.conn.assign_static_ip(nic, ip), '')
         self._assert_exec_called_with(
-            "sudo /bin/ip addr add %s/%s dev %s" % (ip, '28', nic))
+            "sudo ip addr add %s/%s dev %s" % (ip, '28', nic))
 
     def test_turn_nic_on(self):
         nic = 'eth0'
         self.conn.turn_nic_on(nic)
-        self._assert_exec_called_with('sudo /bin/ip link set %s up' % nic)
+        self._assert_exec_called_with(
+            'sudo ip link set %s up' % nic)
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..72a63c3 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)
@@ -265,6 +268,36 @@
         self.assertEqual(alt_creds.user_id, '1234')
 
     @mock.patch('tempest_lib.common.rest_client.RestClient')
+    def test_no_network_creation_with_config_set(self, MockRestClient):
+        cfg.CONF.set_default('create_isolated_networks', False, group='auth')
+        iso_creds = isolated_creds.IsolatedCreds(name='test class',
+                                                 password='fake_password')
+        self._mock_assign_user_role()
+        self._mock_list_role()
+        self._mock_user_create('1234', 'fake_prim_user')
+        self._mock_tenant_create('1234', 'fake_prim_tenant')
+        net = mock.patch.object(iso_creds.network_admin_client,
+                                'delete_network')
+        net_mock = net.start()
+        subnet = mock.patch.object(iso_creds.network_admin_client,
+                                   'delete_subnet')
+        subnet_mock = subnet.start()
+        router = mock.patch.object(iso_creds.network_admin_client,
+                                   'delete_router')
+        router_mock = router.start()
+
+        primary_creds = iso_creds.get_primary_creds()
+        self.assertEqual(net_mock.mock_calls, [])
+        self.assertEqual(subnet_mock.mock_calls, [])
+        self.assertEqual(router_mock.mock_calls, [])
+        network = primary_creds.network
+        subnet = primary_creds.subnet
+        router = primary_creds.router
+        self.assertIsNone(network)
+        self.assertIsNone(subnet)
+        self.assertIsNone(router)
+
+    @mock.patch('tempest_lib.common.rest_client.RestClient')
     def test_network_creation(self, MockRestClient):
         iso_creds = isolated_creds.IsolatedCreds(name='test class',
                                                  password='fake_password')
@@ -381,6 +414,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 +422,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 +430,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 +438,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 +446,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/tests/test_waiters.py b/tempest/tests/test_waiters.py
index cdf5362..329d610 100644
--- a/tempest/tests/test_waiters.py
+++ b/tempest/tests/test_waiters.py
@@ -29,7 +29,7 @@
         self.client.build_interval = 1
 
     def test_wait_for_image_status(self):
-        self.client.get_image.return_value = ({'status': 'active'})
+        self.client.show_image.return_value = ({'status': 'active'})
         start_time = int(time.time())
         waiters.wait_for_image_status(self.client, 'fake_image_id', 'active')
         end_time = int(time.time())
@@ -37,13 +37,13 @@
         self.assertTrue((end_time - start_time) < 10)
 
     def test_wait_for_image_status_timeout(self):
-        self.client.get_image.return_value = ({'status': 'saving'})
+        self.client.show_image.return_value = ({'status': 'saving'})
         self.assertRaises(exceptions.TimeoutException,
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
 
     def test_wait_for_image_status_error_on_image_create(self):
-        self.client.get_image.return_value = ({'status': 'ERROR'})
+        self.client.show_image.return_value = ({'status': 'ERROR'})
         self.assertRaises(exceptions.AddImageException,
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
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/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 19a77dc..b7f0e81 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -283,7 +283,17 @@
                                          CONF.compute.ssh_user,
                                          pkey=self.keypair.material)
         text = data_utils.rand_name("Pattern text for console output")
-        resp = ssh.write_to_console(text)
+        try:
+            resp = ssh.write_to_console(text)
+        except Exception:
+            if not CONF.compute_feature_enabled.console_output:
+                LOG.debug('Console output not supported, cannot log')
+            else:
+                console_output = instance.get_console_output().output
+                LOG.debug('Console output for %s\nbody=\n%s',
+                          instance.id, console_output)
+            raise
+
         self.assertFalse(resp)
 
         def _output():
diff --git a/tox.ini b/tox.ini
index 88d1302..4bb5df6 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = pep8,py27
+envlist = pep8,py27,py34
 minversion = 1.6
 skipsdist = True
 
@@ -59,16 +59,6 @@
   find . -type f -name "*.pyc" -delete
   bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
 
-[testenv:heat-slow]
-sitepackages = {[tempestenv]sitepackages}
-setenv = {[tempestenv]setenv}
-         OS_TEST_TIMEOUT=1200
-deps = {[tempestenv]deps}
-# The regex below is used to select heat api/scenario tests tagged as slow.
-commands =
-  find . -type f -name "*.pyc" -delete
-  bash tools/pretty_tox.sh '(?=.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)\.orchestration) {posargs}'
-
 [testenv:large-ops]
 sitepackages = {[tempestenv]sitepackages}
 setenv = {[tempestenv]setenv}