Merge "Count volumes vs partitions and remove hard-coded expected result"
diff --git a/README.rst b/README.rst
index 13f4f61..3c0463b 100644
--- a/README.rst
+++ b/README.rst
@@ -124,6 +124,9 @@
 
 Release Versioning
 ------------------
+`Tempest Release Notes <http://docs.openstack.org/releasenotes/tempest>`_
+shows what changes have been released on each version.
+
 Tempest's released versions are broken into 2 sets of information. Depending on
 how you intend to consume tempest you might need
 
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 127613d..2edaddb 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -14,6 +14,7 @@
 import sys
 import os
 import subprocess
+import warnings
 
 # Build the plugin registry
 def build_plugin_registry(app):
@@ -140,9 +141,13 @@
 # using the given strftime format.
 git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
    "-n1"]
-html_last_updated_fmt = subprocess.Popen(git_cmd,
-                                         stdout=subprocess.PIPE).\
-                                         communicate()[0]
+try:
+    html_last_updated_fmt = subprocess.Popen(git_cmd,
+                                             stdout=subprocess.PIPE).\
+                                             communicate()[0]
+except Exception:
+    warnings.warn('Cannot get last updated time from git repository. '
+                  'Not setting "html_last_updated_fmt".')
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index e4b104f..6c55015 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -135,7 +135,10 @@
 It is worth pointing out that each set of credentials in the accounts.yaml
 should have a unique project. This is required to provide proper isolation
 to the tests using the credentials, and failure to do this will likely cause
-unexpected failures in some tests.
+unexpected failures in some tests. Also, ensure that these projects and users
+used do not have any pre-existing resources created. Tempest assumes all
+tenants it's using are empty and may sporadically fail if there are unexpected
+resources present.
 
 When the keystone in the target cloud requires domain scoped tokens to
 perform admin actions, all pre-provisioned admin users must have a role
diff --git a/doc/source/library.rst b/doc/source/library.rst
index 6a2fb83..29248d1 100644
--- a/doc/source/library.rst
+++ b/doc/source/library.rst
@@ -67,3 +67,4 @@
    library/utils
    library/api_microversion_testing
    library/auth
+   library/clients
diff --git a/doc/source/library/clients.rst b/doc/source/library/clients.rst
new file mode 100644
index 0000000..086cfc9
--- /dev/null
+++ b/doc/source/library/clients.rst
@@ -0,0 +1,24 @@
+.. _clients:
+
+Service Clients Usage
+=====================
+
+Tests make requests against APIs using service clients. Service clients are
+specializations of the ``RestClient`` class. The service clients that cover the
+APIs exposed by a service should be grouped in a service clients module.
+A service clients module is python module where all service clients are
+defined. If major API versions are available, submodules should be defined,
+one for each version.
+
+The ``ClientsFactory`` class helps initializing all clients of a specific
+service client module from a set of shared parameters.
+
+The ``ServiceClients`` class provides a convenient way to get access to all
+available service clients initialized with a provided set of credentials.
+
+------------------
+The clients module
+------------------
+
+.. automodule:: tempest.lib.services.clients
+   :members:
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 5263fdd..bff18f8 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -221,3 +221,7 @@
  * `2.25`_
 
  .. _2.25: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-mitaka
+
+ * `2.37`_
+
+ .. _2.37: http://docs.openstack.org/developer/nova/api_microversion_history.html#id34
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index 9640469..d34023f 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -111,8 +111,9 @@
 
   class MyPlugin(plugins.TempestPlugin):
 
-Then you need to ensure you locally define all of the methods in the abstract
-class, you can refer to the api doc below for a reference of what that entails.
+Then you need to ensure you locally define all of the mandatory methods in the
+abstract class, you can refer to the api doc below for a reference of what that
+entails.
 
 Abstract Plugin Class
 ---------------------
@@ -164,6 +165,142 @@
 CONF object from tempest. This enables the plugin to add options to both
 existing sections and also create new configuration sections for new options.
 
+Service Clients
+---------------
+
+If a plugin defines a service client, it is beneficial for it to implement the
+``get_service_clients`` method in the plugin class. All service clients which
+are exposed via this interface will be automatically configured and be
+available in any instance of the service clients class, defined in
+``tempest.lib.services.clients.ServiceClients``. In case multiple plugins are
+installed, all service clients from all plugins will be registered, making it
+easy to write tests which rely on multiple APIs whose service clients are in
+different plugins.
+
+Example implementation of ``get_service_clients``::
+
+    def get_service_clients(self):
+        # Example implementation with two service clients
+        my_service1_config = config.service_client_config('my_service')
+        params_my_service1 = {
+            'name': 'my_service_v1',
+            'service_version': 'my_service.v1',
+            'module_path': 'plugin_tempest_tests.services.my_service.v1',
+            'client_names': ['API1Client', 'API2Client'],
+        }
+        params_my_service1.update(my_service_config)
+        my_service2_config = config.service_client_config('my_service')
+        params_my_service2 = {
+            'name': 'my_service_v2',
+            'service_version': 'my_service.v2',
+            'module_path': 'plugin_tempest_tests.services.my_service.v2',
+            'client_names': ['API1Client', 'API2Client'],
+        }
+        params_my_service2.update(my_service2_config)
+        return [params_my_service1, params_my_service2]
+
+Parameters:
+
+* **name**: Name of the attribute used to access the ``ClientsFactory`` from
+  the ``ServiceClients`` instance. See example below.
+* **service_version**: Tempest enforces a single implementation for each
+  service client. Available service clients are held in a ``ClientsRegistry``
+  singleton, and registered with ``service_version``, which means that
+  ``service_version`` must be unique and it should represent the service API
+  and version implemented by the service client.
+* **module_path**: Relative to the service client module, from the root of the
+  plugin.
+* **client_names**: Name of the classes that implement service clients in the
+  service clients module.
+
+Example usage of the the service clients in tests::
+
+   # my_creds is instance of tempest.lib.auth.Credentials
+   # identity_uri is v2 or v3 depending on the configuration
+   from tempest.lib.services import clients
+
+   my_clients = clients.ServiceClients(my_creds, identity_uri)
+   my_service1_api1_client = my_clients.my_service_v1.API1Client()
+   my_service2_api1_client = my_clients.my_service_v2.API1Client(my_args='any')
+
+Automatic configuration and registration of service clients imposes some extra
+constraints on the structure of the configuration options exposed by the
+plugin.
+
+First ``service_version`` should be in the format `service_config[.version]`.
+The `.version` part is optional, and should only be used if there are multiple
+versions of the same API available. The `service_config` must match the name of
+a configuration options group defined by the plugin. Different versions of one
+API must share the same configuration group.
+
+Second the configuration options group `service_config` must contain the
+following options:
+
+* `catalog_type`: corresponds to `service` in the catalog
+* `endpoint_type`
+
+The following options will be honoured if defined, but they are not mandatory,
+as they do not necessarily apply to all service clients.
+
+* `region`: default to identity.region
+* `build_timeout` : default to compute.build_timeout
+* `build_interval`: default to compute.build_interval
+
+Third the service client classes should inherit from ``RestClient``, should
+accept generic keyword arguments, and should pass those arguments to the
+``__init__`` method of ``RestClient``. Extra arguments can be added. For
+instance::
+
+   class MyAPIClient(rest_client.RestClient):
+
+    def __init__(self, auth_provider, service, region,
+                 my_arg, my_arg2=True, **kwargs):
+        super(MyAPIClient, self).__init__(
+            auth_provider, service, region, **kwargs)
+        self.my_arg = my_arg
+        self.my_args2 = my_arg
+
+Finally the service client should be structured in a python module, so that all
+service client classes are importable from it. Each major API version should
+have its own module.
+
+The following folder and module structure is recommended for a single major
+API version::
+
+    plugin_dir/
+      services/
+        __init__.py
+        client_api_1.py
+        client_api_2.py
+
+The content of __init__.py module should be::
+
+   from client_api_1.py import API1Client
+   from client_api_2.py import API2Client
+
+   __all__ = ['API1Client', 'API2Client']
+
+The following folder and module structure is recommended for multiple major
+API version::
+
+    plugin_dir/
+      services/
+        v1/
+           __init__.py
+           client_api_1.py
+           client_api_2.py
+        v2/
+           __init__.py
+           client_api_1.py
+           client_api_2.py
+
+The content each of __init__.py module under vN should be::
+
+   from client_api_1.py import API1Client
+   from client_api_2.py import API2Client
+
+   __all__ = ['API1Client', 'API2Client']
+
 Using Plugins
 =============
 
diff --git a/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml b/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
index b8dcfce..3ec8b56 100644
--- a/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
+++ b/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
@@ -1,10 +1,13 @@
 ---
 features:
   - |
-    Define identity service clients as libraries
+    Define identity service clients as libraries.
     The following identity service clients are defined as library interface,
     so the other projects can use these modules as stable libraries without
     any maintenance changes.
 
      * endpoints_client(v3)
      * policies_client (v3)
+     * regions_client(v3)
+     * services_client(v3)
+     * projects_client(v3)
diff --git a/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml b/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
new file mode 100644
index 0000000..b8a8491
--- /dev/null
+++ b/releasenotes/notes/add-new-identity-clients-as-library-5f7ndha733nwdsn9.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    Define identity service clients as libraries
+    Add new service clients to the library interface so the other projects can use these modules as stable libraries without
+    any maintenance changes.
+
+      * identity_client(v2)
diff --git a/releasenotes/notes/clients_module-16f3025f515bf9ec.yaml b/releasenotes/notes/clients_module-16f3025f515bf9ec.yaml
new file mode 100644
index 0000000..53741da
--- /dev/null
+++ b/releasenotes/notes/clients_module-16f3025f515bf9ec.yaml
@@ -0,0 +1,18 @@
+---
+features:
+  - The Tempest plugin interface contains a new optional method, which allows
+    plugins to declare and automatically register any service client defined
+    in the plugin.
+  - tempest.lib exposes a new stable interface, the clients module and
+    ServiceClients class, which provides a convinient way for plugin tests to
+    access service clients defined in Tempest as well as service clients
+    defined in all loaded plugins.
+    The new ServiceClients class only exposes for now the service clients
+    which are in tempest.lib, i.e. compute, network and image. The remaing
+    service clients (identity, volume and object-storage) will be added in
+    future updates.
+deprecations:
+  - The new clients module provides a stable alternative to tempest classes
+    manager.Manager and clients.Manager. manager.Manager only exists now
+    to smoothen the transition of plugins to the new interface, but it will
+    be removed shortly without further notice.
diff --git a/releasenotes/notes/move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml b/releasenotes/notes/move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
new file mode 100644
index 0000000..543cf7b
--- /dev/null
+++ b/releasenotes/notes/move-call-until-true-to-tempest-lib-c9ea70dd6fe9bd15.yaml
@@ -0,0 +1,5 @@
+---
+deprecations:
+  - The ``call_until_true`` function is moved from the ``tempest.test`` module
+   to the ``tempest.lib.common.utils.test_utils`` module. Backward
+   compatibilty is preserved until Ocata.
diff --git a/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml b/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml
new file mode 100644
index 0000000..cfe97c5
--- /dev/null
+++ b/releasenotes/notes/nova_cert_default-90eb7c1e3cde624a.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+
+  - The ``nova_cert`` option default is changed to ``False``. The nova
+    certification management APIs were a hold over from ec2, and are
+    not used by any other parts of nova. They are deprecated for
+    removal in nova after the newton release. This makes false a more
+    sensible default going forward.
\ No newline at end of file
diff --git a/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml b/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
new file mode 100644
index 0000000..cf504ad
--- /dev/null
+++ b/releasenotes/notes/volume-clients-as-library-9a3444dd63c134b3.yaml
@@ -0,0 +1,18 @@
+---
+features:
+  - |
+    Define volume service clients as libraries
+    The following volume service clients are defined as library interface,
+    so the other projects can use these modules as stable libraries
+    without any maintenance changes.
+
+      * availability_zone_client(v1)
+      * availability_zone_client(v2)
+      * extensions_client(v1)
+      * extensions_client(v2)
+      * hosts_client(v1)
+      * hosts_client(v2)
+      * quotas_client(v1)
+      * quotas_client(v2)
+      * services_client(v1)
+      * services_client(v2)
diff --git a/requirements.txt b/requirements.txt
index 0f8e94d..a773d16 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,7 +9,7 @@
 netaddr!=0.7.16,>=0.7.12 # BSD
 testrepository>=0.0.18 # Apache-2.0/BSD
 oslo.concurrency>=3.8.0 # Apache-2.0
-oslo.config>=3.12.0 # Apache-2.0
+oslo.config>=3.14.0 # Apache-2.0
 oslo.i18n>=2.1.0 # Apache-2.0
 oslo.log>=1.14.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
@@ -22,3 +22,4 @@
 PrettyTable<0.8,>=0.7 # BSD
 os-testr>=0.7.0 # Apache-2.0
 urllib3>=1.15.1 # MIT
+debtcollector>=1.2.0 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index 91ede20..50bf891 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,6 +17,7 @@
     Programming Language :: Python :: 2.7
     Programming Language :: Python :: 3
     Programming Language :: Python :: 3.4
+    Programming Language :: Python :: 3.5
 
 [files]
 packages =
diff --git a/tempest/README.rst b/tempest/README.rst
index 113b191..c9a0491 100644
--- a/tempest/README.rst
+++ b/tempest/README.rst
@@ -26,10 +26,9 @@
 
 API tests are validation tests for the OpenStack API. They should not
 use the existing python clients for OpenStack, but should instead use
-the tempest implementations of clients. This allows us to test both
-XML and JSON. Having raw clients also lets us pass invalid JSON and
-XML to the APIs and see the results, something we could not get with
-the native clients.
+the tempest implementations of clients. Having raw clients let us
+pass invalid JSON to the APIs and see the results, something we could
+not get with the native clients.
 
 When it makes sense, API testing should be moved closer to the
 projects themselves, possibly as functional tests in their unit test
diff --git a/tempest/api/baremetal/admin/base.py b/tempest/api/baremetal/admin/base.py
index 2d3f190..ac5986c 100644
--- a/tempest/api/baremetal/admin/base.py
+++ b/tempest/api/baremetal/admin/base.py
@@ -99,7 +99,7 @@
     def create_chassis(cls, description=None):
         """Wrapper utility for creating test chassis.
 
-        :param description: A description of the chassis. if not supplied,
+        :param description: A description of the chassis. If not supplied,
             a random value will be generated.
         :return: Created chassis.
 
@@ -114,6 +114,7 @@
                     memory_mb=4096):
         """Wrapper utility for creating test baremetal nodes.
 
+        :param chassis_id: The unique identifier of the chassis.
         :param cpu_arch: CPU architecture of the node. Default: x86.
         :param cpus: Number of CPUs. Default: 8.
         :param local_gb: Disk size. Default: 10.
@@ -133,6 +134,7 @@
     def create_port(cls, node_id, address, extra=None, uuid=None):
         """Wrapper utility for creating test ports.
 
+        :param node_id: The unique identifier of the node.
         :param address: MAC address of the port.
         :param extra: Meta data of the port. If not supplied, an empty
             dictionary will be created.
@@ -150,7 +152,7 @@
     def delete_chassis(cls, chassis_id):
         """Deletes a chassis having the specified UUID.
 
-        :param uuid: The unique identifier of the chassis.
+        :param chassis_id: The unique identifier of the chassis.
         :return: Server response.
 
         """
@@ -166,7 +168,7 @@
     def delete_node(cls, node_id):
         """Deletes a node having the specified UUID.
 
-        :param uuid: The unique identifier of the node.
+        :param node_id: The unique identifier of the node.
         :return: Server response.
 
         """
@@ -182,7 +184,7 @@
     def delete_port(cls, port_id):
         """Deletes a port having the specified UUID.
 
-        :param uuid: The unique identifier of the port.
+        :param port_id: The unique identifier of the port.
         :return: Server response.
 
         """
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index ac1bfee..fbcc1d1 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -25,8 +25,6 @@
 class AggregatesAdminTestJSON(base.BaseV2ComputeAdminTest):
     """Tests Aggregates API that require admin privileges"""
 
-    _host_key = 'OS-EXT-SRV-ATTR:host'
-
     @classmethod
     def setup_clients(cls):
         super(AggregatesAdminTestJSON, cls).setup_clients()
@@ -223,4 +221,4 @@
                                          availability_zone=az_name,
                                          wait_until='ACTIVE')
         body = admin_servers_client.show_server(server['id'])['server']
-        self.assertEqual(self.host, body[self._host_key])
+        self.assertEqual(self.host, body['OS-EXT-SRV-ATTR:host'])
diff --git a/tempest/api/compute/admin/test_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
new file mode 100644
index 0000000..ee8ed14
--- /dev/null
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -0,0 +1,211 @@
+# Copyright 2016 IBM Corp.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_log import log
+
+from tempest.api.compute import base
+from tempest.common import compute
+from tempest.common import credentials_factory as credentials
+from tempest.common import waiters
+from tempest import config
+from tempest import exceptions
+from tempest.lib.common.utils import test_utils
+from tempest import test
+
+CONF = config.CONF
+LOG = log.getLogger(__name__)
+
+
+# NOTE(mriedem): This is in the admin directory only because it requires
+# force_tenant_isolation=True, but doesn't extend BaseV2ComputeAdminTest
+# because it doesn't actually use any admin credentials in the tests.
+class AutoAllocateNetworkTest(base.BaseV2ComputeTest):
+    """Tests auto-allocating networks with the v2.37 microversion.
+
+    These tests rely on Neutron being enabled. Also, the tenant must not have
+    any network resources available to it so we can make sure that Nova
+    calls to Neutron to automatically allocate the network topology.
+    """
+
+    force_tenant_isolation = True
+
+    min_microversion = '2.37'
+    max_microversion = 'latest'
+
+    @classmethod
+    def skip_checks(cls):
+        super(AutoAllocateNetworkTest, cls).skip_checks()
+        identity_version = cls.get_identity_version()
+        if not credentials.is_admin_available(
+                identity_version=identity_version):
+            msg = "Missing Identity Admin API credentials in configuration."
+            raise cls.skipException(msg)
+        if not CONF.service_available.neutron:
+            raise cls.skipException('Neutron is required')
+        if not test.is_extension_enabled('auto-allocated-topology', 'network'):
+            raise cls.skipException(
+                'auto-allocated-topology extension is not available')
+
+    @classmethod
+    def setup_credentials(cls):
+        # Do not create network resources for these tests.
+        cls.set_network_resources()
+        super(AutoAllocateNetworkTest, cls).setup_credentials()
+
+    @classmethod
+    def setup_clients(cls):
+        super(AutoAllocateNetworkTest, cls).setup_clients()
+        cls.servers_client = cls.servers_client
+        cls.networks_client = cls.os.networks_client
+        cls.routers_client = cls.os.routers_client
+        cls.subnets_client = cls.os.subnets_client
+        cls.ports_client = cls.os.ports_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(AutoAllocateNetworkTest, cls).resource_setup()
+        # Sanity check that there are no networks available to the tenant.
+        # This is essentially what Nova does for getting available networks.
+        tenant_id = cls.networks_client.tenant_id
+        # (1) Retrieve non-public network list owned by the tenant.
+        search_opts = {'tenant_id': tenant_id, 'shared': False}
+        nets = cls.networks_client.list_networks(
+            **search_opts).get('networks', [])
+        if nets:
+            raise exceptions.TempestException(
+                'Found tenant networks: %s' % nets)
+        # (2) Retrieve shared network list.
+        search_opts = {'shared': True}
+        nets = cls.networks_client.list_networks(
+            **search_opts).get('networks', [])
+        if nets:
+            raise exceptions.TempestException(
+                'Found shared networks: %s' % nets)
+
+    @classmethod
+    def resource_cleanup(cls):
+        """Deletes any auto_allocated_network and it's associated resources."""
+
+        # Find the auto-allocated router for the tenant.
+        # This is a bit hacky since we don't have a great way to find the
+        # auto-allocated router given the private tenant network we have.
+        routers = cls.routers_client.list_routers().get('routers', [])
+        if len(routers) > 1:
+            # This indicates a race where nova is concurrently calling the
+            # neutron auto-allocated-topology API for multiple server builds
+            # at the same time (it's called from nova-compute when setting up
+            # networking for a server). Neutron will detect duplicates and
+            # automatically clean them up, but there is a window where the API
+            # can return multiple and we don't have a good way to filter those
+            # out right now, so we'll just handle them.
+            LOG.info('(%s) Found more than one router for tenant.',
+                     test_utils.find_test_caller())
+
+        # Let's just blindly remove any networks, duplicate or otherwise, that
+        # the test might have created even though Neutron will cleanup
+        # duplicate resources automatically (so ignore 404s).
+        networks = cls.networks_client.list_networks().get('networks', [])
+
+        for router in routers:
+            # Disassociate the subnets from the router. Because of the race
+            # mentioned above the subnets might not be associated with the
+            # router so ignore any 404.
+            for network in networks:
+                for subnet_id in network['subnets']:
+                    test_utils.call_and_ignore_notfound_exc(
+                        cls.routers_client.remove_router_interface,
+                        router['id'], subnet_id=subnet_id)
+
+            # Delete the router.
+            cls.routers_client.delete_router(router['id'])
+
+        for network in networks:
+            # Get and delete the ports for the given network.
+            ports = cls.ports_client.list_ports(
+                network_id=network['id']).get('ports', [])
+            for port in ports:
+                test_utils.call_and_ignore_notfound_exc(
+                    cls.ports_client.delete_port, port['id'])
+
+            # Delete the subnets.
+            for subnet_id in network['subnets']:
+                test_utils.call_and_ignore_notfound_exc(
+                    cls.subnets_client.delete_subnet, subnet_id)
+
+            # Delete the network.
+            test_utils.call_and_ignore_notfound_exc(
+                cls.networks_client.delete_network, network['id'])
+
+    @test.idempotent_id('5eb7b8fa-9c23-47a2-9d7d-02ed5809dd34')
+    def test_server_create_no_allocate(self):
+        """Tests that no networking is allocated for the server."""
+        # create the server with no networking
+        server, _ = compute.create_test_server(
+            self.os, networks='none', wait_until='ACTIVE')
+        self.addCleanup(waiters.wait_for_server_termination,
+                        self.servers_client, server['id'])
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+        # get the server ips
+        addresses = self.servers_client.list_addresses(
+            server['id'])['addresses']
+        # assert that there is no networking
+        self.assertEqual({}, addresses)
+
+    @test.idempotent_id('2e6cf129-9e28-4e8a-aaaa-045ea826b2a6')
+    def test_server_multi_create_auto_allocate(self):
+        """Tests that networking is auto-allocated for multiple servers."""
+
+        # Create multiple servers with auto networking to make sure the
+        # automatic network allocation is atomic. Using a minimum of three
+        # servers is essential for this scenario because:
+        #
+        # - First request sees no networks for the tenant so it auto-allocates
+        #   one from Neutron, let's call that net1.
+        # - Second request sees no networks for the tenant so it auto-allocates
+        #   one from Neutron. Neutron creates net2 but sees it's a duplicate
+        #   so it queues net2 for deletion and returns net1 from the API and
+        #   Nova uses that for the second server request.
+        # - Third request sees net1 and net2 for the tenant and fails with a
+        #   NetworkAmbiguous 400 error.
+        _, servers = compute.create_test_server(
+            self.os, networks='auto', wait_until='ACTIVE',
+            min_count=3)
+        server_nets = set()
+        for server in servers:
+            self.addCleanup(waiters.wait_for_server_termination,
+                            self.servers_client, server['id'])
+            self.addCleanup(self.servers_client.delete_server, server['id'])
+            # get the server ips
+            addresses = self.servers_client.list_addresses(
+                server['id'])['addresses']
+            # assert that there is networking (should only be one)
+            self.assertEqual(1, len(addresses))
+            server_nets.add(list(addresses.keys())[0])
+        # all servers should be on the same network
+        self.assertEqual(1, len(server_nets))
+
+        # List the networks for the tenant; we filter on admin_state_up=True
+        # because the auto-allocated-topology code in Neutron won't set that
+        # to True until the network is ready and is returned from the API.
+        # Duplicate networks created from a race should have
+        # admin_state_up=False.
+        search_opts = {'tenant_id': self.networks_client.tenant_id,
+                       'shared': False,
+                       'admin_state_up': True}
+        nets = self.networks_client.list_networks(
+            **search_opts).get('networks', [])
+        self.assertEqual(1, len(nets))
+        # verify the single private tenant network is the one that the servers
+        # are using also
+        self.assertIn(nets[0]['name'], server_nets)
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index dd7beaa..18a6afc 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -26,7 +26,6 @@
 
 
 class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
-    _host_key = 'OS-EXT-SRV-ATTR:host'
     max_microversion = '2.24'
     block_migration = None
 
@@ -63,7 +62,7 @@
         return body
 
     def _get_host_for_server(self, server_id):
-        return self._get_server_details(server_id)[self._host_key]
+        return self._get_server_details(server_id)['OS-EXT-SRV-ATTR:host']
 
     def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
         kwargs = dict()
@@ -157,7 +156,7 @@
         target_host = self._get_host_other_than(actual_host)
 
         volume = self.volumes_client.create_volume(
-            display_name='test')['volume']
+            size=CONF.volume.volume_size, display_name='test')['volume']
 
         waiters.wait_for_volume_status(self.volumes_client,
                                        volume['id'], 'available')
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 58da8b9..e329869 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -15,11 +15,8 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest):
 
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
old mode 100644
new mode 100755
index 09253b0..aabb40c
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -24,8 +24,6 @@
 class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
     """Tests Servers API using admin privileges"""
 
-    _host_key = 'OS-EXT-SRV-ATTR:host'
-
     @classmethod
     def setup_clients(cls):
         super(ServersAdminTestJSON, cls).setup_clients()
@@ -37,23 +35,16 @@
     def resource_setup(cls):
         super(ServersAdminTestJSON, cls).resource_setup()
 
-        cls.s1_name = data_utils.rand_name('server')
+        cls.s1_name = data_utils.rand_name(cls.__name__ + '-server')
         server = cls.create_test_server(name=cls.s1_name,
                                         wait_until='ACTIVE')
         cls.s1_id = server['id']
 
-        cls.s2_name = data_utils.rand_name('server')
+        cls.s2_name = data_utils.rand_name(cls.__name__ + '-server')
         server = cls.create_test_server(name=cls.s2_name,
                                         wait_until='ACTIVE')
         cls.s2_id = server['id']
 
-    @test.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
-    def test_list_servers_by_admin(self):
-        # Listing servers by admin user returns empty list by default
-        body = self.client.list_servers(detail=True)
-        servers = body['servers']
-        self.assertEqual([], servers)
-
     @test.idempotent_id('06f960bb-15bb-48dc-873d-f96e89be7870')
     def test_list_servers_filter_by_error_status(self):
         # Filter the list of servers by server error status
@@ -70,6 +61,26 @@
         self.assertIn(self.s1_id, map(lambda x: x['id'], servers))
         self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
 
+    @test.idempotent_id('d56e9540-73ed-45e0-9b88-98fc419087eb')
+    def test_list_servers_detailed_filter_by_invalid_status(self):
+        params = {'status': 'invalid_status'}
+        body = self.client.list_servers(detail=True, **params)
+        servers = body['servers']
+        self.assertEqual([], servers)
+
+    @test.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
+    def test_list_servers_by_admin(self):
+        # Listing servers by admin user returns a list which doesn't
+        # contain the other tenants' server by default
+        body = self.client.list_servers(detail=True)
+        servers = body['servers']
+
+        # This case is for the test environments which contain
+        # the existing servers before testing
+        servers_name = [server['name'] for server in servers]
+        self.assertNotIn(self.s1_name, servers_name)
+        self.assertNotIn(self.s2_name, servers_name)
+
     @test.idempotent_id('9f5579ae-19b4-4985-a091-2a5d56106580')
     def test_list_servers_by_admin_with_all_tenants(self):
         # Listing servers by admin user with all tenants parameter
@@ -103,7 +114,7 @@
     @test.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
     def test_list_servers_filter_by_exist_host(self):
         # Filter the list of servers by existent host
-        name = data_utils.rand_name('server')
+        name = data_utils.rand_name(self.__class__.__name__ + '-server')
         network = self.get_tenant_network()
         network_kwargs = fixed_network.set_networks_kwarg(network)
         # We need to create the server as an admin, so we can't use
@@ -114,7 +125,7 @@
         self.addCleanup(self.client.delete_server, test_server['id'])
         server = self.client.show_server(test_server['id'])['server']
         self.assertEqual(server['status'], 'ACTIVE')
-        hostname = server[self._host_key]
+        hostname = server['OS-EXT-SRV-ATTR:host']
         params = {'host': hostname}
         body = self.client.list_servers(**params)
         servers = body['servers']
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
old mode 100644
new mode 100755
index 7437c14..db6e682
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -34,13 +34,14 @@
         cls.client = cls.os_adm.servers_client
         cls.non_adm_client = cls.servers_client
         cls.flavors_client = cls.os_adm.flavors_client
+        cls.quotas_client = cls.os_adm.quotas_client
 
     @classmethod
     def resource_setup(cls):
         super(ServersAdminNegativeTestJSON, cls).resource_setup()
         cls.tenant_id = cls.client.tenant_id
 
-        cls.s1_name = data_utils.rand_name('server')
+        cls.s1_name = data_utils.rand_name(cls.__name__ + '-server')
         server = cls.create_test_server(name=cls.s1_name,
                                         wait_until='ACTIVE')
         cls.s1_id = server['id']
@@ -64,8 +65,8 @@
         self.useFixture(fixtures.LockFixture('compute_quotas'))
         flavor_name = data_utils.rand_name("flavor")
         flavor_id = self._get_unused_flavor_id()
-        quota_set = (self.quotas_client.show_default_quota_set(self.tenant_id)
-                     ['quota_set'])
+        quota_set = self.quotas_client.show_quota_set(
+            self.tenant_id)['quota_set']
         ram = int(quota_set['ram'])
         if ram == -1:
             raise self.skipException("default ram quota set is -1,"
@@ -93,8 +94,8 @@
         flavor_name = data_utils.rand_name("flavor")
         flavor_id = self._get_unused_flavor_id()
         ram = 512
-        quota_set = (self.quotas_client.show_default_quota_set(self.tenant_id)
-                     ['quota_set'])
+        quota_set = self.quotas_client.show_quota_set(
+            self.tenant_id)['quota_set']
         vcpus = int(quota_set['cores'])
         if vcpus == -1:
             raise self.skipException("default cores quota set is -1,"
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index a4ed8dc..dbc22e0 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -16,6 +16,7 @@
 import datetime
 
 from tempest.api.compute import base
+from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as e
 from tempest import test
 
@@ -59,8 +60,8 @@
                 return True
             except e.InvalidHTTPResponseBody:
                 return False
-        self.assertEqual(test.call_until_true(is_valid, duration, 1), True,
-                         "%s not return valid response in %s secs" % (
+        self.assertEqual(test_utils.call_until_true(is_valid, duration, 1),
+                         True, "%s not return valid response in %s secs" % (
                              func.__name__, duration))
         return self.resp
 
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 150e8af..3754637 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -49,6 +49,9 @@
                                               name=snapshot_name,
                                               wait_until='SAVING')
         self.client.delete_image(image['id'])
+        msg = ('The image with ID {image_id} failed to be deleted'
+               .format(image_id=image['id']))
+        self.assertTrue(self.client.is_resource_deleted(image['id']), msg)
 
     @test.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
     def test_create_image_from_stopped_server(self):
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
old mode 100644
new mode 100755
index 9017461..c0caa52
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -60,7 +60,7 @@
 
         def _create_image():
             params = {
-                'name': data_utils.rand_name('image'),
+                'name': data_utils.rand_name(cls.__name__ + '-image'),
                 'container_format': 'bare',
                 'disk_format': 'raw'
             }
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
old mode 100644
new mode 100755
index da9d548..78f0db4
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -48,7 +48,7 @@
         cls.meta = {'hello': 'world'}
         cls.accessIPv4 = '1.1.1.1'
         cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
-        cls.name = data_utils.rand_name('server')
+        cls.name = data_utils.rand_name(cls.__name__ + '-server')
         cls.password = data_utils.rand_password()
         disk_config = cls.disk_config
         cls.server_initial = cls.create_test_server(
@@ -139,7 +139,7 @@
         hostname = linux_client.get_hostname()
         msg = ('Failed while verifying servername equals hostname. Expected '
                'hostname "%s" but got "%s".' % (self.name, hostname))
-        self.assertEqual(self.name, hostname, msg)
+        self.assertEqual(self.name.lower(), hostname, msg)
 
     @test.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
     def test_create_server_with_scheduler_hint_group(self):
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index c1fbb12..26cbb090 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -17,13 +17,10 @@
 from tempest.common import fixed_network
 from tempest.common.utils import data_utils
 from tempest.common import waiters
-from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
-CONF = config.CONF
-
 
 class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
 
@@ -274,14 +271,9 @@
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
         self.s1 = self.client.show_server(self.s1['id'])['server']
-        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)
+        # Get first ip address inspite of v4 or v6
+        addr_spec = self.s1['addresses'][self.fixed_network_name][0]
+        params = {'ip': addr_spec['addr']}
         body = self.client.list_servers(**params)
         servers = body['servers']
 
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
old mode 100644
new mode 100755
index 21e7d10..062e920
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -155,7 +155,7 @@
     def test_rebuild_server(self):
         # The server should be rebuilt using the provided image and data
         meta = {'rebuild': 'server'}
-        new_name = data_utils.rand_name('server')
+        new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
         password = 'rebuildPassw0rd'
         rebuilt_server = self.client.rebuild_server(
             self.server_id,
@@ -270,6 +270,9 @@
                                            'SHUTOFF')
 
         self.client.resize_server(self.server_id, self.flavor_ref_alt)
+        # NOTE(jlk): Explicitly delete the server to get a new one for later
+        # tests. Avoids resize down race issues.
+        self.addCleanup(self.delete_server, self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id,
                                        'VERIFY_RESIZE')
 
@@ -285,10 +288,6 @@
             # NOTE(mriedem): tearDown requires the server to be started.
             self.client.start_server(self.server_id)
 
-        # NOTE(jlk): Explicitly delete the server to get a new one for later
-        # tests. Avoids resize down race issues.
-        self.addCleanup(self.delete_server, self.server_id)
-
     @test.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
@@ -309,6 +308,9 @@
         # values after a resize is reverted
 
         self.client.resize_server(self.server_id, self.flavor_ref_alt)
+        # NOTE(zhufl): Explicitly delete the server to get a new one for later
+        # tests. Avoids resize down race issues.
+        self.addCleanup(self.delete_server, self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id,
                                        'VERIFY_RESIZE')
 
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
old mode 100644
new mode 100755
index e91857a..5aeba4e
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -52,7 +52,8 @@
         # Creating a server with a name that already exists is allowed
 
         # TODO(sdague): clear out try, we do cleanup one layer up
-        server_name = data_utils.rand_name('server')
+        server_name = data_utils.rand_name(
+            self.__class__.__name__ + '-server')
         server = self.create_test_server(name=server_name,
                                          wait_until='ACTIVE')
         id1 = server['id']
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
old mode 100644
new mode 100755
index 10ea31d..2304cb7
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -253,7 +253,8 @@
         # Update name of a non-existent server
 
         nonexistent_server = data_utils.rand_uuid()
-        new_name = data_utils.rand_name('server') + '_updated'
+        new_name = data_utils.rand_name(
+            self.__class__.__name__ + '-server') + '_updated'
 
         self.assertRaises(lib_exc.NotFound, self.client.update_server,
                           nonexistent_server, name=new_name)
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index dc57396..ffd274f 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -24,8 +24,6 @@
 
 
 class LiveBlockMigrationNegativeTestJSON(base.BaseV2ComputeAdminTest):
-    _host_key = 'OS-EXT-SRV-ATTR:host'
-
     @classmethod
     def skip_checks(cls):
         super(LiveBlockMigrationNegativeTestJSON, cls).skip_checks()
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
old mode 100644
new mode 100755
index f42d153..e96982d
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -40,14 +40,14 @@
 
     @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
     def test_volume_snapshot_create_get_list_delete(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         volume = self.volumes_client.create_volume(
             size=CONF.volume.volume_size,
             display_name=v_name)['volume']
         self.addCleanup(self.delete_volume, volume['id'])
         waiters.wait_for_volume_status(self.volumes_client, volume['id'],
                                        'available')
-        s_name = data_utils.rand_name('Snapshot')
+        s_name = data_utils.rand_name(self.__class__.__name__ + '-Snapshot')
         # Create snapshot
         snapshot = self.snapshots_client.create_snapshot(
             volume_id=volume['id'],
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
old mode 100644
new mode 100755
index 6074054..d599431
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -42,15 +42,14 @@
     @test.idempotent_id('f10f25eb-9775-4d9d-9cbe-1cf54dae9d5f')
     def test_volume_create_get_delete(self):
         # CREATE, GET, DELETE Volume
-        volume = None
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         # Create volume
         volume = self.client.create_volume(size=CONF.volume.volume_size,
                                            display_name=v_name,
                                            metadata=metadata)['volume']
-        self.addCleanup(self.delete_volume, volume['id'])
         self.assertIn('id', volume)
+        self.addCleanup(self.delete_volume, volume['id'])
         self.assertIn('displayName', volume)
         self.assertEqual(volume['displayName'], v_name,
                          "The created volume name is not equal "
@@ -66,6 +65,10 @@
                          fetched_volume['displayName'],
                          'The fetched Volume is different '
                          'from the created Volume')
+        self.assertEqual(CONF.volume.volume_size,
+                         fetched_volume['size'],
+                         'The fetched volume size is different '
+                         'from the created Volume')
         self.assertEqual(volume['id'],
                          fetched_volume['id'],
                          'The fetched Volume is different '
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
old mode 100644
new mode 100755
index f709c91..c60fcca
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -48,7 +48,7 @@
         cls.volume_list = []
         cls.volume_id_list = []
         for i in range(3):
-            v_name = data_utils.rand_name('volume')
+            v_name = data_utils.rand_name(cls.__name__ + '-volume')
             metadata = {'Type': 'work'}
             try:
                 volume = cls.client.create_volume(size=CONF.volume.volume_size,
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
old mode 100644
new mode 100755
index 92f5ea8..7ecad12
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -59,7 +59,7 @@
     def test_create_volume_with_invalid_size(self):
         # Negative: Should not be able to create volume with invalid size
         # in request
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
@@ -69,7 +69,7 @@
     def test_create_volume_with_out_passing_size(self):
         # Negative: Should not be able to create volume without passing size
         # in request
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
@@ -78,7 +78,7 @@
     @test.idempotent_id('8cce995e-0a83-479a-b94d-e1e40b8a09d1')
     def test_create_volume_with_size_zero(self):
         # Negative: Should not be able to create volume with size zero
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index d5ba76c..c8506ae 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from collections import OrderedDict
+import collections
 import copy
 
 import six
@@ -112,7 +112,7 @@
 
 
 DEFAULT_TEMPLATES = {
-    'vanilla': OrderedDict([
+    'vanilla': collections.OrderedDict([
         ('2.6.0', copy.deepcopy(BASE_VANILLA_DESC)),
         ('2.7.1', copy.deepcopy(BASE_VANILLA_DESC)),
         ('1.2.1', {
@@ -148,7 +148,7 @@
             }
         })
     ]),
-    'hdp': OrderedDict([
+    'hdp': collections.OrderedDict([
         ('2.0.6', {
             'NODES': {
                 'master1': {
@@ -174,11 +174,11 @@
             }
         })
     ]),
-    'spark': OrderedDict([
+    'spark': collections.OrderedDict([
         ('1.0.0', copy.deepcopy(BASE_SPARK_DESC)),
         ('1.3.1', copy.deepcopy(BASE_SPARK_DESC))
     ]),
-    'cdh': OrderedDict([
+    'cdh': collections.OrderedDict([
         ('5.4.0', copy.deepcopy(BASE_CDH_DESC)),
         ('5.3.0', copy.deepcopy(BASE_CDH_DESC)),
         ('5', copy.deepcopy(BASE_CDH_DESC))
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 7c2e8e0..12b236f 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -37,7 +37,7 @@
             cls.projects.append(cls.project['id'])
 
         cls.user_body = cls.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.projects[0])['user']
 
     @classmethod
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index a540da7..3616e77 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -54,7 +54,7 @@
         # default project
         user_name = data_utils.rand_name('user')
         user_body = self.users_client.create_user(
-            user_name,
+            name=user_name,
             password=user_name,
             domain_id=dom_id,
             default_project_id=proj_id)['user']
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 24a7a4e..cbf1439 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -44,11 +44,11 @@
         super(DomainsTestJSON, cls).resource_cleanup()
 
     @classmethod
-    def _delete_domain(self, domain_id):
+    def _delete_domain(cls, domain_id):
         # It is necessary to disable the domain before deleting,
         # or else it would result in unauthorized error
-        self.domains_client.update_domain(domain_id, enabled=False)
-        self.domains_client.delete_domain(domain_id)
+        cls.domains_client.update_domain(domain_id, enabled=False)
+        cls.domains_client.delete_domain(domain_id)
 
     @test.idempotent_id('8cf516ef-2114-48f1-907b-d32726c734d4')
     def test_list_domains(self):
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 59fcec6..48e5f02 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -83,7 +83,8 @@
         for i in range(3):
             name = data_utils.rand_name('User')
             password = data_utils.rand_password()
-            user = self.users_client.create_user(name, password)['user']
+            user = self.users_client.create_user(name=name,
+                                                 password=password)['user']
             users.append(user)
             self.addCleanup(self.users_client.delete_user, user['id'])
             self.groups_client.add_group_user(group['id'], user['id'])
@@ -103,7 +104,8 @@
     def test_list_user_groups(self):
         # create a user
         user = self.users_client.create_user(
-            data_utils.rand_name('User'), data_utils.rand_password())['user']
+            name=data_utils.rand_name('User'),
+            password=data_utils.rand_password())['user']
         self.addCleanup(self.users_client.delete_user, user['id'])
         # create two groups, and add user into them
         groups = []
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index fe20349..76771bb 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -12,11 +12,8 @@
 
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class BaseInheritsV3Test(base.BaseIdentityV3AdminTest):
 
@@ -44,7 +41,7 @@
             name=data_utils.rand_name('group-'), project_id=cls.project['id'],
             domain_id=cls.domain['id'])['group']
         cls.user = cls.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email, project_id=cls.project['id'],
             domain_id=cls.domain['id'])['user']
 
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index 9691ee8..99df559 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -25,7 +25,7 @@
         # assert the response based on expected and not_expected
         # expected: user expected in the list response
         # not_expected: user, which should not be present in list response
-        body = self.users_client.list_users(params)['users']
+        body = self.users_client.list_users(**params)['users']
         self.assertIn(expected[key], map(lambda x: x[key], body))
         self.assertNotIn(not_expected[key],
                          map(lambda x: x[key], body))
@@ -42,13 +42,13 @@
         cls.users = list()
         u1_name = data_utils.rand_name('test_user')
         cls.domain_enabled_user = cls.users_client.create_user(
-            u1_name, password=alt_password,
+            name=u1_name, password=alt_password,
             email=cls.alt_email, domain_id=cls.domain['id'])['user']
         cls.users.append(cls.domain_enabled_user)
         # Create default not enabled user
         u2_name = data_utils.rand_name('test_user')
         cls.non_domain_enabled_user = cls.users_client.create_user(
-            u2_name, password=alt_password,
+            name=u2_name, password=alt_password,
             email=cls.alt_email, enabled=False)['user']
         cls.users.append(cls.non_domain_enabled_user)
 
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 1879e46..1137191 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -200,7 +200,7 @@
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email, project_id=project['id'])['user']
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user['id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 2b77023..4ecf0a5 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -44,7 +44,7 @@
             name=data_utils.rand_name('Group'), project_id=cls.project['id'],
             domain_id=cls.domain['id'])['group']
         cls.user_body = cls.users_client.create_user(
-            u_name, description=u_desc, password=cls.u_password,
+            name=u_name, description=u_desc, password=cls.u_password,
             email=u_email, project_id=cls.project['id'],
             domain_id=cls.domain['id'])['user']
         cls.role = cls.roles_client.create_role(
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 89cfd5b..fcf4772 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -32,7 +32,7 @@
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email)['user']
         self.addCleanup(self.users_client.delete_user, user['id'])
         # Perform Authentication
@@ -62,7 +62,7 @@
         # Create a user.
         user_name = data_utils.rand_name(name='user')
         user_password = data_utils.rand_password()
-        user = self.users_client.create_user(user_name,
+        user = self.users_client.create_user(name=user_name,
                                              password=user_password)['user']
         self.addCleanup(self.users_client.delete_user, user['id'])
 
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 9c8f1f6..58e2ab8 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -57,7 +57,7 @@
         u_email = self.trustor_username + '@testmail.xx'
         self.trustor_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            self.trustor_username,
+            name=self.trustor_username,
             description=u_desc,
             password=self.trustor_password,
             email=u_email,
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index f200095..1bcec62 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -31,7 +31,7 @@
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False)['user']
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user['id'])
@@ -71,7 +71,7 @@
         u_name = data_utils.rand_name('user')
         original_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            u_name, password=original_password)['user']
+            name=u_name, password=original_password)['user']
         # Delete the User at the end all test methods
         self.addCleanup(self.users_client.delete_user, user['id'])
         # Update user with new password
@@ -107,7 +107,7 @@
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
         user_body = self.users_client.create_user(
-            u_name, description=u_desc, password=u_password,
+            name=u_name, description=u_desc, password=u_password,
             email=u_email, enabled=False, project_id=u_project['id'])['user']
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user_body['id'])
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 71e8bc5..5b0fc97 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -29,7 +29,7 @@
         u_email = u_name + '@testmail.tm'
         u_password = data_utils.rand_password()
         self.assertRaises(lib_exc.NotFound, self.users_client.create_user,
-                          u_name, u_password,
+                          name=u_name, password=u_password,
                           email=u_email,
                           domain_id=data_utils.rand_uuid_hex())
 
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index ce052e6..6c926fb 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -13,14 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.common.utils import data_utils
 from tempest import config
 import tempest.test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class BaseIdentityTest(tempest.test.BaseTestCase):
@@ -39,7 +36,7 @@
     def get_user_by_name(cls, name, domain_id=None):
         if domain_id:
             params = {'domain_id': domain_id}
-            users = cls.users_client.list_users(params)['users']
+            users = cls.users_client.list_users(**params)['users']
         else:
             users = cls.users_client.list_users()['users']
         user = [u for u in users if u['name'] == name]
@@ -122,10 +119,6 @@
         super(BaseIdentityV2AdminTest, cls).resource_setup()
         cls.projects_client = cls.tenants_client
 
-    @classmethod
-    def resource_cleanup(cls):
-        super(BaseIdentityV2AdminTest, cls).resource_cleanup()
-
     def setup_test_user(self, password=None):
         """Set up a test user."""
         tenant = self.setup_test_tenant()
@@ -190,17 +183,9 @@
             cls.os_adm.auth_provider.scope = 'domain'
 
     @classmethod
-    def resource_setup(cls):
-        super(BaseIdentityV3AdminTest, cls).resource_setup()
-
-    @classmethod
-    def resource_cleanup(cls):
-        super(BaseIdentityV3AdminTest, cls).resource_cleanup()
-
-    @classmethod
     def disable_user(cls, user_name, domain_id=None):
         user = cls.get_user_by_name(user_name, domain_id)
-        cls.users_client.update_user(user['id'], user_name, enabled=False)
+        cls.users_client.update_user(user['id'], name=user_name, enabled=False)
 
     @classmethod
     def create_domain(cls):
@@ -221,7 +206,7 @@
         project = self.setup_test_project()
         username = data_utils.rand_name('test_user')
         email = username + '@testmail.tm'
-        user = self._create_test_user(user_name=username, email=email,
+        user = self._create_test_user(name=username, email=email,
                                       project_id=project['id'],
                                       password=password)
         return user
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
old mode 100644
new mode 100755
index 6fd6ea6..e7a46b0
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -144,6 +144,18 @@
         cls.resource_types_client = cls.os.resource_types_client
         cls.schemas_client = cls.os.schemas_client
 
+    def create_namespace(cls, namespace_name=None, visibility='public',
+                         description='Tempest', protected=False,
+                         **kwargs):
+        if not namespace_name:
+            namespace_name = data_utils.rand_name('test-ns')
+        kwargs.setdefault('display_name', namespace_name)
+        namespace = cls.namespaces_client.create_namespace(
+            namespace=namespace_name, visibility=visibility,
+            description=description, protected=protected, **kwargs)
+        cls.addCleanup(cls.namespaces_client.delete_namespace, namespace_name)
+        return namespace
+
 
 class BaseV2MemberImageTest(BaseV2ImageTest):
 
@@ -167,7 +179,7 @@
         return image_ids
 
     def _create_image(self):
-        name = data_utils.rand_name('image')
+        name = data_utils.rand_name(self.__class__.__name__ + '-image')
         image = self.client.create_image(name=name,
                                          container_format='bare',
                                          disk_format='raw')
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index e4fbbe3..694408d 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -322,10 +322,7 @@
         metadata['properties'].update(req_metadata)
         headers = common_image.image_meta_to_headers(
             properties=metadata['properties'])
-        metadata = self.client.update_image(self.image_id,
-                                            headers=headers)['image']
-
+        self.client.update_image(self.image_id, headers=headers)
         resp = self.client.check_image(self.image_id)
         resp_metadata = common_image.get_image_meta_from_headers(resp)
-        expected = {'key1': 'alt1', 'key2': 'value2'}
-        self.assertEqual(expected, resp_metadata['properties'])
+        self.assertEqual(req_metadata, resp_metadata['properties'])
diff --git a/tempest/api/image/v2/test_images_metadefs_resource_types.py b/tempest/api/image/v2/test_images_metadefs_resource_types.py
new file mode 100644
index 0000000..a5143a1
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_resource_types.py
@@ -0,0 +1,54 @@
+# Copyright 2016 Ericsson India Global Services Private Limited
+# 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.image import base
+from tempest import test
+
+
+class MetadataResourceTypesTest(base.BaseV2ImageTest):
+    """Test the Metadata definition ressource types basic functionality"""
+
+    @test.idempotent_id('6f358a4e-5ef0-11e6-a795-080027d0d606')
+    def test_basic_meta_def_resource_type_association(self):
+        # Get the available resource types and use one resource_type
+        body = self.resource_types_client.list_resource_types()
+        resource_name = body['resource_types'][0]['name']
+        # Create a namespace
+        namespace = self.create_namespace()
+        # Create resource type association
+        body = self.resource_types_client.create_resource_type_association(
+            namespace['namespace'], name=resource_name)
+        self.assertEqual(body['name'], resource_name)
+        # NOTE(raiesmh08): Here intentionally I have not added addcleanup
+        # method for resource type dissociation because its a metadata add and
+        # being cleaned as soon as namespace is cleaned at test case level.
+        # When namespace cleans, resource type associaion will automatically
+        # clean without any error or dependency.
+
+        # List resource type associations and validate creation
+        rs_type_associations = [
+            rs_type_association['name'] for rs_type_association in
+            self.resource_types_client.list_resource_type_association(
+                namespace['namespace'])['resource_type_associations']]
+        self.assertIn(resource_name, rs_type_associations)
+        # Delete resource type association
+        self.resource_types_client.delete_resource_type_association(
+            namespace['namespace'], resource_name)
+        # List resource type associations and validate deletion
+        rs_type_associations = [
+            rs_type_association['name'] for rs_type_association in
+            self.resource_types_client.list_resource_type_association(
+                namespace['namespace'])['resource_type_associations']]
+        self.assertNotIn(resource_name, rs_type_associations)
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index baeaa0c..2686af2 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -26,6 +26,13 @@
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
+    def skip_checks(cls):
+        super(FloatingIPAdminTestJSON, cls).skip_checks()
+        if not test.is_extension_enabled('router', 'network'):
+            msg = "router extension not enabled."
+            raise cls.skipException(msg)
+
+    @classmethod
     def setup_clients(cls):
         super(FloatingIPAdminTestJSON, cls).setup_clients()
         cls.alt_floating_ips_client = cls.alt_manager.floating_ips_client
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 9e7c795..5c67d68 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -270,7 +270,7 @@
         """Wrapper utility that returns a test metering label."""
         body = cls.admin_metering_labels_client.create_metering_label(
             description=description,
-            name=data_utils.rand_name("metering-label"))
+            name=name)
         metering_label = body['metering_label']
         cls.metering_labels.append(metering_label)
         return metering_label
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 0eec387..ae8dfcc 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -13,9 +13,7 @@
 # under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
-from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -91,14 +89,3 @@
         self.assertRaises(lib_exc.Forbidden,
                           self.account_client.create_account_metadata,
                           {"Quota-Bytes": "100"})
-
-    @test.attr(type=["negative"])
-    @decorators.skip_because(bug="1310597")
-    @test.idempotent_id('cf9e21f5-3aa4-41b1-9462-28ac550d8d3f')
-    @test.requires_ext(extension='account_quotas', service='object')
-    def test_upload_large_object(self):
-        object_name = data_utils.rand_name(name="TestObject")
-        data = data_utils.arbitrary_string(30)
-        self.assertRaises(lib_exc.OverLimit,
-                          self.object_client.create_object,
-                          self.container_name, object_name, data)
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index c26e49b..8cbe441 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -15,11 +15,9 @@
 
 from tempest.api.object_storage import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
-CONF = config.CONF
 QUOTA_BYTES = 10
 QUOTA_COUNT = 3
 
@@ -70,7 +68,7 @@
     @test.requires_ext(extension='container_quotas', service='object')
     @test.attr(type="smoke")
     def test_upload_large_object(self):
-        """Attempts to upload an object lagger than the bytes quota."""
+        """Attempts to upload an object larger than the bytes quota."""
         object_name = data_utils.rand_name(name="TestObject")
         data = data_utils.arbitrary_string(QUOTA_BYTES + 1)
 
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 296d8ee..8522269 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -19,9 +19,6 @@
 
 
 class ContainerTest(base.BaseObjectTest):
-    def setUp(self):
-        super(ContainerTest, self).setUp()
-
     def tearDown(self):
         self.delete_containers()
         super(ContainerTest, self).tearDown()
@@ -124,7 +121,6 @@
         # delete container, success asserted within
         resp, _ = self.container_client.delete_container(container_name)
         self.assertHeaders(resp, 'Container', 'DELETE')
-        self.containers.remove(container_name)
 
     @test.attr(type='smoke')
     @test.idempotent_id('312ff6bd-5290-497f-bda1-7c5fec6697ab')
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index c2d3b69..7287a2d 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -20,11 +20,8 @@
 
 from tempest.api.object_storage import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class ObjectTempUrlTest(base.BaseObjectTest):
 
diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py
index 9d2b425..f2ffbd7 100644
--- a/tempest/api/orchestration/stacks/test_environment.py
+++ b/tempest/api/orchestration/stacks/test_environment.py
@@ -12,13 +12,9 @@
 
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest import test
 
 
-CONF = config.CONF
-
-
 class StackEnvironmentTest(base.BaseOrchestrationTest):
 
     @test.idempotent_id('37d4346b-1abd-4442-b7b1-2a4e5749a1e3')
diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index aa0b46a..b660f6e 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.py
@@ -12,12 +12,9 @@
 
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
-from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
-CONF = config.CONF
-
 
 class TestSoftwareConfig(base.BaseOrchestrationTest):
 
diff --git a/tempest/api/volume/admin/test_backends_capabilities.py b/tempest/api/volume/admin/test_backends_capabilities.py
new file mode 100644
index 0000000..8a21853
--- /dev/null
+++ b/tempest/api/volume/admin/test_backends_capabilities.py
@@ -0,0 +1,79 @@
+# Copyright 2016 OpenStack Foundation
+# 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.
+
+import operator
+
+from tempest.api.volume import base
+from tempest import test
+
+
+class BackendsCapabilitiesAdminV2TestsJSON(base.BaseVolumeAdminTest):
+
+    CAPABILITIES = ('namespace',
+                    'vendor_name',
+                    'volume_backend_name',
+                    'pool_name',
+                    'driver_version',
+                    'storage_protocol',
+                    'display_name',
+                    'description',
+                    'visibility',
+                    'properties')
+
+    @classmethod
+    def resource_setup(cls):
+        super(BackendsCapabilitiesAdminV2TestsJSON, cls).resource_setup()
+        # Get host list, formation: host@backend-name
+        cls.hosts = [
+            pool['name'] for pool in
+            cls.admin_volume_client.show_pools()['pools']
+        ]
+
+    @test.idempotent_id('3750af44-5ea2-4cd4-bc3e-56e7e6caf854')
+    def test_get_capabilities_backend(self):
+        # Test backend properties
+        backend = self.admin_volume_client.show_backend_capabilities(
+            self.hosts[0])
+
+        # Verify getting capabilities parameters from a backend
+        for key in self.CAPABILITIES:
+            self.assertIn(key, backend)
+
+    @test.idempotent_id('a9035743-d46a-47c5-9cb7-3c80ea16dea0')
+    def test_compare_volume_stats_values(self):
+        # Test values comparison between show_backend_capabilities
+        # to show_pools
+        VOLUME_STATS = ('vendor_name',
+                        'volume_backend_name',
+                        'storage_protocol')
+
+        # Get list backend capabilities using show_pools
+        cinder_pools = [
+            pool['capabilities'] for pool in
+            self.admin_volume_client.show_pools(detail=True)['pools']
+        ]
+
+        # Get list backends capabilities using show_backend_capabilities
+        capabilities = [
+            self.admin_volume_client.show_backend_capabilities(
+                host=host) for host in self.hosts
+        ]
+
+        # Returns a tuple of VOLUME_STATS values
+        expected_list = map(operator.itemgetter(*VOLUME_STATS),
+                            cinder_pools)
+        observed_list = map(operator.itemgetter(*VOLUME_STATS),
+                            capabilities)
+        self.assertEqual(expected_list, observed_list)
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 5615cf3..120dbb1 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -53,30 +53,30 @@
             cls._create_type_and_volume(backend_name, True)
 
     @classmethod
-    def _create_type_and_volume(self, backend_name_key, with_prefix):
+    def _create_type_and_volume(cls, backend_name_key, with_prefix):
         # Volume/Type creation
-        type_name = data_utils.rand_name('Type')
-        vol_name = data_utils.rand_name('Volume')
+        type_name = data_utils.rand_name(cls.__name__ + '-Type')
+        vol_name = data_utils.rand_name(cls.__name__ + '-Volume')
         spec_key_with_prefix = "capabilities:volume_backend_name"
         spec_key_without_prefix = "volume_backend_name"
         if with_prefix:
             extra_specs = {spec_key_with_prefix: backend_name_key}
         else:
             extra_specs = {spec_key_without_prefix: backend_name_key}
-        self.type = self.create_volume_type(name=type_name,
-                                            extra_specs=extra_specs)
+        cls.type = cls.create_volume_type(name=type_name,
+                                          extra_specs=extra_specs)
 
-        params = {self.name_field: vol_name, 'volume_type': type_name}
-
-        self.volume = self.admin_volume_client.create_volume(
+        params = {cls.name_field: vol_name, 'volume_type': type_name,
+                  'size': CONF.volume.volume_size}
+        cls.volume = cls.admin_volume_client.create_volume(
             **params)['volume']
         if with_prefix:
-            self.volume_id_list_with_prefix.append(self.volume['id'])
+            cls.volume_id_list_with_prefix.append(cls.volume['id'])
         else:
-            self.volume_id_list_without_prefix.append(
-                self.volume['id'])
-        waiters.wait_for_volume_status(self.admin_volume_client,
-                                       self.volume['id'], 'available')
+            cls.volume_id_list_without_prefix.append(
+                cls.volume['id'])
+        waiters.wait_for_volume_status(cls.admin_volume_client,
+                                       cls.volume['id'], 'available')
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/tempest/api/volume/admin/test_qos.py b/tempest/api/volume/admin/test_qos.py
old mode 100644
new mode 100755
index 9402668..98139e7
--- a/tempest/api/volume/admin/test_qos.py
+++ b/tempest/api/volume/admin/test_qos.py
@@ -37,7 +37,7 @@
                                                     read_iops_sec='2000')
 
     def _create_delete_test_qos_with_given_consumer(self, consumer):
-        name = utils.rand_name('qos')
+        name = utils.rand_name(self.__class__.__name__ + '-qos')
         qos = {'name': name, 'consumer': consumer}
         body = self.create_test_qos_specs(name, consumer)
         for key in ['name', 'consumer']:
@@ -119,8 +119,7 @@
         self.admin_volume_qos_client.unset_qos_key(self.created_qos['id'],
                                                    keys)
         operation = 'qos-key-unset'
-        self.admin_volume_qos_client.wait_for_qos_operations(
-            self.created_qos['id'], operation, keys)
+        self.wait_for_qos_operations(self.created_qos['id'], operation, keys)
         body = self.admin_volume_qos_client.show_qos(
             self.created_qos['id'])['qos_specs']
         self.assertNotIn(keys[0], body['specs'])
@@ -154,8 +153,8 @@
         self.admin_volume_qos_client.disassociate_qos(
             self.created_qos['id'], vol_type[0]['id'])
         operation = 'disassociate'
-        self.admin_volume_qos_client.wait_for_qos_operations(
-            self.created_qos['id'], operation, vol_type[0]['id'])
+        self.wait_for_qos_operations(self.created_qos['id'],
+                                     operation, vol_type[0]['id'])
         associations = self._test_get_association_qos()
         self.assertNotIn(vol_type[0]['id'], associations)
 
@@ -163,8 +162,7 @@
         self.admin_volume_qos_client.disassociate_all_qos(
             self.created_qos['id'])
         operation = 'disassociate-all'
-        self.admin_volume_qos_client.wait_for_qos_operations(
-            self.created_qos['id'], operation)
+        self.wait_for_qos_operations(self.created_qos['id'], operation)
         associations = self._test_get_association_qos()
         self.assertEmpty(associations)
 
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index a17cc69..1468e90 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -15,7 +15,6 @@
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
 from tempest import test
 
@@ -42,28 +41,13 @@
         vol_name = data_utils.rand_name(cls.__name__ + '-Volume')
         cls.name_field = cls.special_fields['name_field']
         params = {cls.name_field: vol_name}
-        cls.volume = cls.volumes_client.create_volume(**params)['volume']
-        waiters.wait_for_volume_status(cls.volumes_client,
-                                       cls.volume['id'], 'available')
+        cls.volume = cls.create_volume(**params)
 
         # Create a test shared snapshot for tests
         snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot')
         params = {cls.name_field: snap_name}
-        cls.snapshot = cls.client.create_snapshot(
-            volume_id=cls.volume['id'], **params)['snapshot']
-        waiters.wait_for_snapshot_status(cls.client,
-                                         cls.snapshot['id'], 'available')
-
-    @classmethod
-    def resource_cleanup(cls):
-        # Delete the test snapshot
-        cls.client.delete_snapshot(cls.snapshot['id'])
-        cls.client.wait_for_resource_deletion(cls.snapshot['id'])
-
-        # Delete the test volume
-        cls.delete_volume(cls.volumes_client, cls.volume['id'])
-
-        super(SnapshotsActionsV2Test, cls).resource_cleanup()
+        cls.snapshot = cls.create_snapshot(
+            volume_id=cls.volume['id'], **params)
 
     def tearDown(self):
         # Set snapshot's status to available after test
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index dde8915..c19b1c4 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -32,8 +32,7 @@
     @classmethod
     def resource_setup(cls):
         super(BaseVolumeQuotasNegativeV2TestJSON, cls).resource_setup()
-        cls.default_volume_size = cls.volumes_client.default_volume_size
-        cls.shared_quota_set = {'gigabytes': 2 * cls.default_volume_size,
+        cls.shared_quota_set = {'gigabytes': 2 * CONF.volume.volume_size,
                                 'volumes': 1}
 
         # NOTE(gfidente): no need to restore original quota set
@@ -50,7 +49,8 @@
     @test.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
     def test_quota_volumes(self):
         self.assertRaises(lib_exc.OverLimit,
-                          self.volumes_client.create_volume)
+                          self.volumes_client.create_volume,
+                          size=CONF.volume.volume_size)
 
     @test.attr(type='negative')
     @test.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
@@ -61,13 +61,14 @@
         self.addCleanup(self.admin_quotas_client.update_quota_set,
                         self.demo_tenant_id,
                         **self.shared_quota_set)
-        new_quota_set = {'gigabytes': self.default_volume_size,
+        new_quota_set = {'gigabytes': CONF.volume.volume_size,
                          'volumes': 2, 'snapshots': 1}
         self.admin_quotas_client.update_quota_set(
             self.demo_tenant_id,
             **new_quota_set)
         self.assertRaises(lib_exc.OverLimit,
-                          self.volumes_client.create_volume)
+                          self.volumes_client.create_volume,
+                          size=CONF.volume.volume_size)
 
 
 class VolumeQuotasNegativeV1TestJSON(BaseVolumeQuotasNegativeV2TestJSON):
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 755365d..165874b 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -79,7 +79,7 @@
         services = (self.admin_volume_services_client.list_services(
             host=self.host_name, binary=self.binary_name))['services']
 
-        self.assertEqual(1, len(services))
+        self.assertNotEqual(0, len(services))
         self.assertEqual(self.host_name, _get_host(services[0]['host']))
         self.assertEqual(self.binary_name, services[0]['binary'])
 
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
index 1565a8c..09af7fe 100644
--- a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -38,7 +38,7 @@
     @classmethod
     def resource_setup(cls):
         super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).resource_setup()
-        cls.default_volume_size = cls.volumes_client.default_volume_size
+        cls.default_volume_size = CONF.volume.volume_size
         cls.shared_quota_set = {'gigabytes': 3 * cls.default_volume_size,
                                 'volumes': 1, 'snapshots': 1}
 
diff --git a/tempest/api/volume/admin/test_volume_type_access.py b/tempest/api/volume/admin/test_volume_type_access.py
index fac71a8..91ff5af 100644
--- a/tempest/api/volume/admin/test_volume_type_access.py
+++ b/tempest/api/volume/admin/test_volume_type_access.py
@@ -17,9 +17,12 @@
 
 from tempest.api.volume import base
 from tempest.common import waiters
+from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
+CONF = config.CONF
+
 
 class VolumeTypesAccessV2Test(base.BaseVolumeAdminTest):
 
@@ -38,7 +41,8 @@
 
         # Try creating a volume from volume type in primary tenant
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          volume_type=volume_type['id'])
+                          volume_type=volume_type['id'],
+                          size=CONF.volume.volume_size)
 
         # Adding volume type access for primary tenant
         self.admin_volume_types_client.add_type_access(
@@ -49,7 +53,8 @@
 
         # Creating a volume from primary tenant
         volume = self.volumes_client.create_volume(
-            volume_type=volume_type['id'])['volume']
+            volume_type=volume_type['id'],
+            size=CONF.volume.volume_size)['volume']
         self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
         waiters.wait_for_volume_status(self.volumes_client, volume['id'],
                                        'available')
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
old mode 100644
new mode 100755
index 8eae085..00da5be
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -35,7 +35,7 @@
     def test_volume_crud_with_volume_type_and_extra_specs(self):
         # Create/update/get/delete volume with volume_type and extra spec.
         volume_types = list()
-        vol_name = data_utils.rand_name("volume")
+        vol_name = data_utils.rand_name(self.__class__.__name__ + '-volume')
         self.name_field = self.special_fields['name_field']
         proto = CONF.volume.storage_protocol
         vendor = CONF.volume.vendor_name
@@ -43,13 +43,15 @@
                        "vendor_name": vendor}
         # Create two volume_types
         for i in range(2):
-            vol_type_name = data_utils.rand_name("volume-type")
+            vol_type_name = data_utils.rand_name(
+                self.__class__.__name__ + '-volume-type')
             vol_type = self.create_volume_type(
                 name=vol_type_name,
                 extra_specs=extra_specs)
             volume_types.append(vol_type)
         params = {self.name_field: vol_name,
-                  'volume_type': volume_types[0]['id']}
+                  'volume_type': volume_types[0]['id'],
+                  'size': CONF.volume.volume_size}
 
         # Create volume
         volume = self.volumes_client.create_volume(**params)['volume']
@@ -87,7 +89,7 @@
     def test_volume_type_create_get_delete(self):
         # Create/get volume type.
         body = {}
-        name = data_utils.rand_name("volume-type")
+        name = data_utils.rand_name(self.__class__.__name__ + '-volume-type')
         description = data_utils.rand_name("volume-type-description")
         proto = CONF.volume.storage_protocol
         vendor = CONF.volume.vendor_name
@@ -122,7 +124,7 @@
         # Create/get/delete encryption type.
         provider = "LuksEncryptor"
         control_location = "front-end"
-        name = data_utils.rand_name("volume-type")
+        name = data_utils.rand_name(self.__class__.__name__ + '-volume-type')
         body = self.create_volume_type(name=name)
         # Create encryption type
         encryption_type = \
@@ -161,6 +163,28 @@
                 encryption_type['volume_type_id']))
         self.assertEmpty(deleted_encryption_type)
 
+    @test.idempotent_id('cf9f07c6-db9e-4462-a243-5933ad65e9c8')
+    def test_volume_type_update(self):
+        # Create volume type
+        volume_type = self.create_volume_type()
+
+        # New volume type details
+        name = data_utils.rand_name("volume-type")
+        description = data_utils.rand_name("volume-type-description")
+        is_public = not volume_type['is_public']
+
+        # Update volume type details
+        kwargs = {'name': name,
+                  'description': description,
+                  'is_public': is_public}
+        updated_vol_type = self.admin_volume_types_client.update_volume_type(
+            volume_type['id'], **kwargs)['volume_type']
+
+        # Verify volume type details were updated
+        self.assertEqual(name, updated_vol_type['name'])
+        self.assertEqual(description, updated_vol_type['description'])
+        self.assertEqual(is_public, updated_vol_type['is_public'])
+
 
 class VolumeTypesV1Test(VolumeTypesV2Test):
     _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
old mode 100644
new mode 100755
index 9e49b94..d50ba27
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -23,7 +23,7 @@
     @classmethod
     def resource_setup(cls):
         super(VolumeTypesExtraSpecsV2Test, cls).resource_setup()
-        vol_type_name = data_utils.rand_name('Volume-type')
+        vol_type_name = data_utils.rand_name(cls.__name__ + '-Volume-type')
         cls.volume_type = cls.create_volume_type(name=vol_type_name)
 
     @test.idempotent_id('b42923e9-0452-4945-be5b-d362ae533e60')
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
old mode 100644
new mode 100755
index 2193aa6..2e07457
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -24,7 +24,7 @@
     @classmethod
     def resource_setup(cls):
         super(ExtraSpecsNegativeV2Test, cls).resource_setup()
-        vol_type_name = data_utils.rand_name('Volume-type')
+        vol_type_name = data_utils.rand_name(cls.__name__ + '-Volume-type')
         cls.extra_specs = {"spec1": "val1"}
         cls.volume_type = cls.create_volume_type(name=vol_type_name,
                                                  extra_specs=cls.extra_specs)
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
old mode 100644
new mode 100755
index 5388f7f..9686473
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -16,8 +16,11 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils as utils
 from tempest.common import waiters
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class VolumesActionsV2Test(base.BaseVolumeAdminTest):
 
@@ -33,7 +36,7 @@
         # Create a test shared volume for tests
         vol_name = utils.rand_name(cls.__name__ + '-Volume')
         cls.name_field = cls.special_fields['name_field']
-        params = {cls.name_field: vol_name}
+        params = {cls.name_field: vol_name, 'size': CONF.volume.volume_size}
 
         cls.volume = cls.client.create_volume(**params)['volume']
         waiters.wait_for_volume_status(cls.client,
@@ -59,8 +62,8 @@
 
     def _create_temp_volume(self):
         # Create a temp volume for force delete tests
-        vol_name = utils.rand_name('Volume')
-        params = {self.name_field: vol_name}
+        vol_name = utils.rand_name(self.__class__.__name__ + '-Volume')
+        params = {self.name_field: vol_name, 'size': CONF.volume.volume_size}
         temp_volume = self.client.create_volume(**params)['volume']
         waiters.wait_for_volume_status(self.client,
                                        temp_volume['id'], 'available')
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
old mode 100644
new mode 100755
index b144c7c..f7013d8
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -43,7 +43,7 @@
 
     def _delete_backup(self, backup_id):
         self.admin_backups_client.delete_backup(backup_id)
-        self.admin_backups_client.wait_for_backup_deletion(backup_id)
+        self.admin_backups_client.wait_for_resource_deletion(backup_id)
 
     def _decode_url(self, backup_url):
         return json.loads(base64.decodestring(backup_url))
@@ -59,44 +59,6 @@
         backup.update(changes)
         return self._encode_backup(backup)
 
-    @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
-    def test_volume_backup_create_get_detailed_list_restore_delete(self):
-        # Create backup
-        backup_name = data_utils.rand_name('Backup')
-        create_backup = self.admin_backups_client.create_backup
-        backup = create_backup(volume_id=self.volume['id'],
-                               name=backup_name)['backup']
-        self.addCleanup(self.admin_backups_client.delete_backup,
-                        backup['id'])
-        self.assertEqual(backup_name, backup['name'])
-        waiters.wait_for_volume_status(self.admin_volume_client,
-                                       self.volume['id'], 'available')
-        self.admin_backups_client.wait_for_backup_status(backup['id'],
-                                                         'available')
-
-        # Get a given backup
-        backup = self.admin_backups_client.show_backup(backup['id'])['backup']
-        self.assertEqual(backup_name, backup['name'])
-
-        # Get all backups with detail
-        backups = self.admin_backups_client.list_backups(
-            detail=True)['backups']
-        self.assertIn((backup['name'], backup['id']),
-                      [(m['name'], m['id']) for m in backups])
-
-        # Restore backup
-        restore = self.admin_backups_client.restore_backup(
-            backup['id'])['restore']
-
-        # Delete backup
-        self.addCleanup(self.admin_volume_client.delete_volume,
-                        restore['volume_id'])
-        self.assertEqual(backup['id'], restore['backup_id'])
-        self.admin_backups_client.wait_for_backup_status(backup['id'],
-                                                         'available')
-        waiters.wait_for_volume_status(self.admin_volume_client,
-                                       restore['volume_id'], 'available')
-
     @test.idempotent_id('a99c54a1-dd80-4724-8a13-13bf58d4068d')
     def test_volume_backup_export_import(self):
         """Test backup export import functionality.
@@ -105,7 +67,7 @@
         be imported back in case of a DB loss.
         """
         # Create backup
-        backup_name = data_utils.rand_name('Backup')
+        backup_name = data_utils.rand_name(self.__class__.__name__ + '-Backup')
         backup = (self.admin_backups_client.create_backup(
             volume_id=self.volume['id'], name=backup_name)['backup'])
         self.addCleanup(self._delete_backup, backup['id'])
@@ -169,7 +131,8 @@
     @test.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
     def test_volume_backup_reset_status(self):
         # Create a backup
-        backup_name = data_utils.rand_name('Backup')
+        backup_name = data_utils.rand_name(
+            self.__class__.__name__ + '-Backup')
         backup = self.admin_backups_client.create_backup(
             volume_id=self.volume['id'], name=backup_name)['backup']
         self.addCleanup(self.admin_backups_client.delete_backup,
diff --git a/tempest/api/volume/admin/test_volumes_list.py b/tempest/api/volume/admin/test_volumes_list.py
index 70c16f3..4437803 100644
--- a/tempest/api/volume/admin/test_volumes_list.py
+++ b/tempest/api/volume/admin/test_volumes_list.py
@@ -17,8 +17,11 @@
 
 from tempest.api.volume import base
 from tempest.common import waiters
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class VolumesListAdminV2TestJSON(base.BaseVolumeAdminTest):
 
@@ -38,7 +41,8 @@
     def test_volume_list_param_tenant(self):
         # Test to list volumes from single tenant
         # Create a volume in admin tenant
-        adm_vol = self.admin_volume_client.create_volume()['volume']
+        adm_vol = self.admin_volume_client.create_volume(
+            size=CONF.volume.volume_size)['volume']
         waiters.wait_for_volume_status(self.admin_volume_client,
                                        adm_vol['id'], 'available')
         self.addCleanup(self.admin_volume_client.delete_volume, adm_vol['id'])
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 087b9a8..4f37c82 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,12 +13,15 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.common import compute
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions as lib_exc
 import tempest.test
 
 CONF = config.CONF
@@ -110,7 +113,10 @@
     @classmethod
     def create_volume(cls, **kwargs):
         """Wrapper utility that returns a test volume."""
-        name = data_utils.rand_name('Volume')
+        if 'size' not in kwargs:
+            kwargs['size'] = CONF.volume.volume_size
+
+        name = data_utils.rand_name(cls.__name__ + '-Volume')
 
         name_field = cls.special_fields['name_field']
 
@@ -236,7 +242,7 @@
     @classmethod
     def create_volume_type(cls, name=None, **kwargs):
         """Create a test volume-type"""
-        name = name or data_utils.rand_name('volume-type')
+        name = name or data_utils.rand_name(cls.__name__ + '-volume-type')
         volume_type = cls.admin_volume_types_client.create_volume_type(
             name=name, **kwargs)['volume_type']
         cls.volume_types.append(volume_type['id'])
@@ -265,3 +271,35 @@
             test_utils.call_and_ignore_notfound_exc(
                 cls.admin_volume_types_client.wait_for_resource_deletion,
                 resource)
+
+    def wait_for_qos_operations(self, qos_id, operation, args=None):
+        """Waits for a qos operations to be completed.
+
+        NOTE : operation value is required for  wait_for_qos_operations()
+        operation = 'qos-key' / 'disassociate' / 'disassociate-all'
+        args = keys[] when operation = 'qos-key'
+        args = volume-type-id disassociated when operation = 'disassociate'
+        args = None when operation = 'disassociate-all'
+        """
+        start_time = int(time.time())
+        client = self.admin_volume_qos_client
+        while True:
+            if operation == 'qos-key-unset':
+                body = client.show_qos(qos_id)['qos_specs']
+                if not any(key in body['specs'] for key in args):
+                    return
+            elif operation == 'disassociate':
+                body = client.show_association_qos(qos_id)['qos_associations']
+                if not any(args in body[i]['id'] for i in range(0, len(body))):
+                    return
+            elif operation == 'disassociate-all':
+                body = client.show_association_qos(qos_id)['qos_associations']
+                if not body:
+                    return
+            else:
+                msg = (" operation value is either not defined or incorrect.")
+                raise lib_exc.UnprocessableEntity(msg)
+
+            if int(time.time()) - start_time >= self.build_timeout:
+                raise exceptions.TimeoutException
+            time.sleep(self.build_interval)
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index d138490..a8889e0 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -17,11 +17,8 @@
 
 from tempest.api.volume import base
 from tempest.common import waiters
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class VolumesV2TransfersTest(base.BaseVolumeTest):
 
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
old mode 100644
new mode 100755
index 76cd36c..7783c18
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -114,7 +114,8 @@
         self.addCleanup(self.client.detach_volume, self.volume['id'])
         volume = self.client.show_volume(self.volume['id'])['volume']
         self.assertIn('attachments', volume)
-        attachment = self.client.get_attachment_from_volume(volume)
+        attachment = volume['attachments'][0]
+
         self.assertEqual('/dev/%s' %
                          CONF.compute.volume_device_name,
                          attachment['device'])
@@ -129,7 +130,7 @@
         # it is shared with the other tests. After it is uploaded in Glance,
         # there is no way to delete it from Cinder, so we delete it from Glance
         # using the Glance image_client and from Cinder via tearDownClass.
-        image_name = data_utils.rand_name('Image')
+        image_name = data_utils.rand_name(self.__class__.__name__ + '-Image')
         body = self.client.upload_volume(
             self.volume['id'], image_name=image_name,
             disk_format=CONF.volume.disk_format)['os-volume_upload_image']
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
old mode 100644
new mode 100755
index 87146db..50a1360
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -34,7 +34,47 @@
     def resource_setup(cls):
         super(VolumesBackupsV2Test, cls).resource_setup()
 
-        cls.volume = cls.create_volume()
+    @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
+    def test_volume_backup_create_get_detailed_list_restore_delete(self):
+        # Create backup
+        volume = self.create_volume()
+        self.addCleanup(self.volumes_client.delete_volume,
+                        volume['id'])
+        backup_name = data_utils.rand_name(
+            self.__class__.__name__ + '-Backup')
+        create_backup = self.backups_client.create_backup
+        backup = create_backup(volume_id=volume['id'],
+                               name=backup_name)['backup']
+        self.addCleanup(self.backups_client.delete_backup,
+                        backup['id'])
+        self.assertEqual(backup_name, backup['name'])
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       volume['id'], 'available')
+        self.backups_client.wait_for_backup_status(backup['id'],
+                                                   'available')
+
+        # Get a given backup
+        backup = self.backups_client.show_backup(backup['id'])['backup']
+        self.assertEqual(backup_name, backup['name'])
+
+        # Get all backups with detail
+        backups = self.backups_client.list_backups(
+            detail=True)['backups']
+        self.assertIn((backup['name'], backup['id']),
+                      [(m['name'], m['id']) for m in backups])
+
+        # Restore backup
+        restore = self.backups_client.restore_backup(
+            backup['id'])['restore']
+
+        # Delete backup
+        self.addCleanup(self.volumes_client.delete_volume,
+                        restore['volume_id'])
+        self.assertEqual(backup['id'], restore['backup_id'])
+        self.backups_client.wait_for_backup_status(backup['id'],
+                                                   'available')
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       restore['volume_id'], 'available')
 
     @test.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
     @test.services('compute')
@@ -45,22 +85,27 @@
         is "available" or "in-use".
         """
         # Create a server
-        server_name = data_utils.rand_name('instance')
+        volume = self.create_volume()
+        self.addCleanup(self.volumes_client.delete_volume,
+                        volume['id'])
+        server_name = data_utils.rand_name(
+            self.__class__.__name__ + '-instance')
         server = self.create_server(name=server_name, wait_until='ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
         # Attach volume to instance
         self.servers_client.attach_volume(server['id'],
-                                          volumeId=self.volume['id'])
+                                          volumeId=volume['id'])
         waiters.wait_for_volume_status(self.volumes_client,
-                                       self.volume['id'], 'in-use')
+                                       volume['id'], 'in-use')
         self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
-                        self.volume['id'], 'available')
+                        volume['id'], 'available')
         self.addCleanup(self.servers_client.detach_volume, server['id'],
-                        self.volume['id'])
+                        volume['id'])
         # Create backup using force flag
-        backup_name = data_utils.rand_name('Backup')
+        backup_name = data_utils.rand_name(
+            self.__class__.__name__ + '-Backup')
         backup = self.backups_client.create_backup(
-            volume_id=self.volume['id'],
+            volume_id=volume['id'],
             name=backup_name, force=True)['backup']
         self.addCleanup(self.backups_client.delete_backup, backup['id'])
         self.backups_client.wait_for_backup_status(backup['id'],
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index f38a068..7529dc2 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -23,6 +23,12 @@
 
 class VolumesCloneTest(base.BaseVolumeTest):
 
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesCloneTest, cls).skip_checks()
+        if not CONF.volume_feature_enabled.clone:
+            raise cls.skipException("Cinder volume clones are disabled")
+
     @test.idempotent_id('9adae371-a257-43a5-9555-dc7c88e66e0e')
     def test_create_from_volume(self):
         # Creates a volume from another volume passing a size different from
diff --git a/tempest/api/volume/test_volumes_clone_negative.py b/tempest/api/volume/test_volumes_clone_negative.py
index ee51e00..d1bedb4 100644
--- a/tempest/api/volume/test_volumes_clone_negative.py
+++ b/tempest/api/volume/test_volumes_clone_negative.py
@@ -24,6 +24,12 @@
 
 class VolumesCloneTest(base.BaseVolumeTest):
 
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesCloneTest, cls).skip_checks()
+        if not CONF.volume_feature_enabled.clone:
+            raise cls.skipException("Cinder volume clones are disabled")
+
     @test.idempotent_id('9adae371-a257-43a5-459a-dc7c88e66e0e')
     def test_create_from_volume_decreasing_size(self):
         # Creates a volume from another volume passing a size different from
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 1947779..7aea1c4 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -15,11 +15,8 @@
 
 from tempest.api.volume import base
 from tempest.common import waiters
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class VolumesV2ExtendTest(base.BaseVolumeTest):
 
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
old mode 100644
new mode 100755
index e5fcdfe..07f799b
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -41,8 +41,7 @@
 
     def _volume_create_get_update_delete(self, **kwargs):
         # Create a volume, Get it's details and Delete the volume
-        volume = {}
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'Test'}
         # Create a volume
         kwargs[self.name_field] = v_name
@@ -82,7 +81,8 @@
         params = {self.name_field: v_name}
         self.client.update_volume(volume['id'], **params)
         # Test volume update when display_name is new
-        new_v_name = data_utils.rand_name('new-Volume')
+        new_v_name = data_utils.rand_name(
+            self.__class__.__name__ + '-new-Volume')
         new_desc = 'This is the new description of volume'
         params = {self.name_field: new_v_name,
                   self.descrip_field: new_desc}
@@ -103,10 +103,10 @@
         # Test volume create when display_name is none and display_description
         # contains specific characters,
         # then test volume update if display_name is duplicated
-        new_volume = {}
         new_v_desc = data_utils.rand_name('@#$%^* description')
         params = {self.descrip_field: new_v_desc,
-                  'availability_zone': volume['availability_zone']}
+                  'availability_zone': volume['availability_zone'],
+                  'size': CONF.volume.volume_size}
         new_volume = self.client.create_volume(**params)['volume']
         self.assertIn('id', new_volume)
         self.addCleanup(self.delete_volume, self.client, new_volume['id'])
@@ -125,7 +125,7 @@
     @test.attr(type='smoke')
     @test.idempotent_id('27fb0e9f-fb64-41dd-8bdb-1ffa762f0d51')
     def test_volume_create_get_update_delete(self):
-        self._volume_create_get_update_delete()
+        self._volume_create_get_update_delete(size=CONF.volume.volume_size)
 
     @test.attr(type='smoke')
     @test.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
@@ -143,7 +143,8 @@
                           'Cinder volume clones are disabled')
     def test_volume_create_get_update_delete_as_clone(self):
         origin = self.create_volume()
-        self._volume_create_get_update_delete(source_volid=origin['id'])
+        self._volume_create_get_update_delete(source_volid=origin['id'],
+                                              size=CONF.volume.volume_size)
 
 
 class VolumesV1GetTest(VolumesV2GetTest):
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index f7176f4..b5ef7c0 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -61,20 +61,11 @@
 
         # Create 3 test volumes
         cls.volume_list = []
-        cls.volume_id_list = []
         cls.metadata = {'Type': 'work'}
         for i in range(3):
             volume = cls.create_volume(metadata=cls.metadata)
             volume = cls.client.show_volume(volume['id'])['volume']
             cls.volume_list.append(volume)
-            cls.volume_id_list.append(volume['id'])
-
-    @classmethod
-    def resource_cleanup(cls):
-        # Delete the created volumes
-        for volid in cls.volume_id_list:
-            cls.delete_volume(cls.client, volid)
-        super(VolumesV2ListTestJSON, cls).resource_cleanup()
 
     def _list_by_param_value_and_assert(self, params, with_detail=False):
         """list or list_details with given params and validates result"""
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
old mode 100644
new mode 100755
index 77bfaf1..16c8571
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -56,7 +56,7 @@
     def test_create_volume_with_invalid_size(self):
         # Should not be able to create volume with invalid size
         # in request
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
@@ -66,7 +66,7 @@
     def test_create_volume_with_out_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
@@ -75,7 +75,7 @@
     @test.idempotent_id('41331caa-eaf4-4001-869d-bc18c1869360')
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
@@ -84,7 +84,7 @@
     @test.idempotent_id('8b472729-9eba-446e-a83b-916bdb34bef7')
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='-1', display_name=v_name, metadata=metadata)
@@ -93,7 +93,7 @@
     @test.idempotent_id('10254ed8-3849-454e-862e-3ab8e6aa01d2')
     def test_create_volume_with_nonexistent_volume_type(self):
         # Should not be able to create volume with non-existent volume type
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.create_volume,
                           size='1', volume_type=data_utils.rand_uuid(),
@@ -103,7 +103,7 @@
     @test.idempotent_id('0c36f6ae-4604-4017-b0a9-34fdc63096f9')
     def test_create_volume_with_nonexistent_snapshot_id(self):
         # Should not be able to create volume with non-existent snapshot
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.create_volume,
                           size='1', snapshot_id=data_utils.rand_uuid(),
@@ -113,7 +113,7 @@
     @test.idempotent_id('47c73e08-4be8-45bb-bfdf-0c4e79b88344')
     def test_create_volume_with_nonexistent_source_volid(self):
         # Should not be able to create volume with non-existent source volume
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.create_volume,
                           size='1', source_volid=data_utils.rand_uuid(),
@@ -122,7 +122,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('0186422c-999a-480e-a026-6a665744c30c')
     def test_update_volume_with_nonexistent_volume_id(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.update_volume,
                           volume_id=data_utils.rand_uuid(),
@@ -132,7 +132,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('e66e40d6-65e6-4e75-bdc7-636792fa152d')
     def test_update_volume_with_invalid_volume_id(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.update_volume,
                           volume_id='#$%%&^&^', display_name=v_name,
@@ -141,7 +141,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('72aeca85-57a5-4c1f-9057-f320f9ea575b')
     def test_update_volume_with_empty_volume_id(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.client.update_volume,
                           volume_id='', display_name=v_name,
@@ -177,7 +177,7 @@
     @test.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
     @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
-        srv_name = data_utils.rand_name('Instance')
+        srv_name = data_utils.rand_name(self.__class__.__name__ + '-Instance')
         server = self.create_server(
             name=srv_name,
             wait_until='ACTIVE')
@@ -267,7 +267,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('0f4aa809-8c7b-418f-8fb3-84c7a5dfc52f')
     def test_list_volumes_with_nonexistent_name(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         params = {self.name_field: v_name}
         fetched_volume = self.client.list_volumes(params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
@@ -275,7 +275,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('9ca17820-a0e7-4cbd-a7fa-f4468735e359')
     def test_list_volumes_detail_with_nonexistent_name(self):
-        v_name = data_utils.rand_name('Volume')
+        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         params = {self.name_field: v_name}
         fetched_volume = \
             self.client.list_volumes(detail=True, params=params)['volumes']
@@ -299,4 +299,3 @@
 
 class VolumesV1NegativeTest(VolumesV2NegativeTest):
     _api_version = 1
-    _name = 'display_name'
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
old mode 100644
new mode 100755
index c7f1e6e..20c647a
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -75,7 +75,8 @@
     def test_snapshot_create_with_volume_in_use(self):
         # Create a snapshot when volume status is in-use
         # Create a test instance
-        server_name = data_utils.rand_name('instance')
+        server_name = data_utils.rand_name(
+            self.__class__.__name__ + '-instance')
         server = self.create_server(
             name=server_name,
             wait_until='ACTIVE')
@@ -98,7 +99,7 @@
     @test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
     def test_snapshot_create_get_list_update_delete(self):
         # Create a snapshot
-        s_name = data_utils.rand_name('snap')
+        s_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
         params = {self.name_field: s_name}
         snapshot = self.create_snapshot(self.volume_origin['id'], **params)
 
@@ -116,7 +117,8 @@
         self.assertIn(tracking_data, snaps_data)
 
         # Updates snapshot with new values
-        new_s_name = data_utils.rand_name('new-snap')
+        new_s_name = data_utils.rand_name(
+            self.__class__.__name__ + '-new-snap')
         new_desc = 'This is the new description of snapshot.'
         params = {self.name_field: new_s_name,
                   self.descrip_field: new_desc}
@@ -138,7 +140,7 @@
     def test_snapshots_list_with_params(self):
         """list snapshots with params."""
         # Create a snapshot
-        display_name = data_utils.rand_name('snap')
+        display_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
         params = {self.name_field: display_name}
         snapshot = self.create_snapshot(self.volume_origin['id'], **params)
         self.addCleanup(self.cleanup_snapshot, snapshot)
@@ -160,7 +162,7 @@
     def test_snapshots_list_details_with_params(self):
         """list snapshot details with params."""
         # Create a snapshot
-        display_name = data_utils.rand_name('snap')
+        display_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
         params = {self.name_field: display_name}
         snapshot = self.create_snapshot(self.volume_origin['id'], **params)
         self.addCleanup(self.cleanup_snapshot, snapshot)
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
old mode 100644
new mode 100755
index 2df9523..1f5bb0d
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -31,7 +31,7 @@
     @test.idempotent_id('e3e466af-70ab-4f4b-a967-ab04e3532ea7')
     def test_create_snapshot_with_nonexistent_volume_id(self):
         # Create a snapshot with nonexistent volume id
-        s_name = data_utils.rand_name('snap')
+        s_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
         self.assertRaises(lib_exc.NotFound,
                           self.snapshots_client.create_snapshot,
                           volume_id=data_utils.rand_uuid(),
@@ -41,7 +41,7 @@
     @test.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
     def test_create_snapshot_without_passing_volume_id(self):
         # Create a snapshot without passing volume id
-        s_name = data_utils.rand_name('snap')
+        s_name = data_utils.rand_name(self.__class__.__name__ + '-snap')
         self.assertRaises(lib_exc.NotFound,
                           self.snapshots_client.create_snapshot,
                           volume_id=None, display_name=s_name)
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 1fdcb49..60a35b0 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -42,22 +42,15 @@
         super(VolumesV2ListTestJSON, cls).resource_setup()
 
         # Create 3 test volumes
-        cls.volume_list = []
-        cls.volume_id_list = []
         cls.metadata = {'Type': 'work'}
+        # NOTE(zhufl): When using pre-provisioned credentials, the project
+        # may have volumes other than those created below.
+        existing_volumes = cls.client.list_volumes()['volumes']
+        cls.volume_id_list = [vol['id'] for vol in existing_volumes]
         for i in range(3):
             volume = cls.create_volume(metadata=cls.metadata)
-            volume = cls.client.show_volume(volume['id'])['volume']
-            cls.volume_list.append(volume)
             cls.volume_id_list.append(volume['id'])
 
-    @classmethod
-    def resource_cleanup(cls):
-        # Delete the created volumes
-        for volid in cls.volume_id_list:
-            cls.delete_volume(cls.client, volid)
-        super(VolumesV2ListTestJSON, cls).resource_cleanup()
-
     @test.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
     def test_volume_list_details_with_multiple_params(self):
         # List volumes detail using combined condition
diff --git a/tempest/api/volume/v3/admin/test_user_messages.py b/tempest/api/volume/v3/admin/test_user_messages.py
old mode 100644
new mode 100755
index 9d59d1b..39a5dfa
--- a/tempest/api/volume/v3/admin/test_user_messages.py
+++ b/tempest/api/volume/v3/admin/test_user_messages.py
@@ -16,9 +16,12 @@
 from tempest.api.volume.v3 import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
+from tempest import config
 from tempest import exceptions
 from tempest import test
 
+CONF = config.CONF
+
 MESSAGE_KEYS = [
     'created_at',
     'event_id',
@@ -42,13 +45,15 @@
         bad_vendor = data_utils.rand_name('vendor_name')
         extra_specs = {'storage_protocol': bad_protocol,
                        'vendor_name': bad_vendor}
-        vol_type_name = data_utils.rand_name('volume-type')
+        vol_type_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume-type')
         bogus_type = self.admin_volume_types_client.create_volume_type(
             name=vol_type_name,
             extra_specs=extra_specs)['volume_type']
         self.addCleanup(self.admin_volume_types_client.delete_volume_type,
                         bogus_type['id'])
-        params = {'volume_type': bogus_type['id']}
+        params = {'volume_type': bogus_type['id'],
+                  'size': CONF.volume.volume_size}
         volume = self.volumes_client.create_volume(**params)['volume']
         self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
         try:
diff --git a/tempest/clients.py b/tempest/clients.py
index e070637..5406d73 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -14,15 +14,13 @@
 #    under the License.
 
 import copy
-
 from oslo_log import log as logging
-
 from tempest.common import negative_rest_client
 from tempest import config
 from tempest import exceptions
 from tempest.lib import auth
 from tempest.lib import exceptions as lib_exc
-from tempest import service_clients
+from tempest.lib.services import clients
 from tempest.services import baremetal
 from tempest.services import data_processing
 from tempest.services import identity
@@ -34,7 +32,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class Manager(service_clients.ServiceClients):
+class Manager(clients.ServiceClients):
     """Top level manager for OpenStack tempest clients"""
 
     default_params = config.service_client_config()
@@ -99,17 +97,16 @@
         This uses `config.service_client_config` for all services to collect
         most configuration items needed to init the clients.
         """
-        # NOTE(andreaf) Configuration items will be passed in future patches
-        # into ClientFactory objects, but for now we update all the
-        # _set_*_client methods to consume them so we can verify that the
-        # configuration collected is correct
+        # NOTE(andreaf) Once all service clients in Tempest are migrated
+        # to tempest.lib, their configuration will be picked up from the
+        # registry, and this method will become redundant.
 
         configuration = {}
 
-        # Setup the parameters for all Tempest services.
+        # Setup the parameters for all Tempest services which are not in lib.
         # NOTE(andreaf) Since client.py is an internal module of Tempest,
         # it doesn't have to consider plugin configuration.
-        for service in service_clients.tempest_modules():
+        for service in clients._tempest_internal_modules():
             try:
                 # NOTE(andreaf) Use the unversioned service name to fetch
                 # the configuration since configuration is not versioned.
@@ -300,12 +297,10 @@
                                                           **params)
         self.snapshots_v2_client = volume.v2.SnapshotsClient(
             self.auth_provider, **params)
-        self.volumes_client = volume.v1.VolumesClient(
-            self.auth_provider, default_volume_size=CONF.volume.volume_size,
-            **params)
-        self.volumes_v2_client = volume.v2.VolumesClient(
-            self.auth_provider, default_volume_size=CONF.volume.volume_size,
-            **params)
+        self.volumes_client = volume.v1.VolumesClient(self.auth_provider,
+                                                      **params)
+        self.volumes_v2_client = volume.v2.VolumesClient(self.auth_provider,
+                                                         **params)
         self.volume_messages_client = volume.v3.MessagesClient(
             self.auth_provider, **params)
         self.volume_types_client = volume.v1.TypesClient(self.auth_provider,
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index e3788ab..eeca063 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -22,7 +22,7 @@
 from oslo_log import log as logging
 from six import moves
 
-from tempest.cmd.workspace import WorkspaceManager
+from tempest.cmd import workspace
 
 LOG = logging.getLogger(__name__)
 
@@ -89,18 +89,28 @@
         with open(testr_conf_path, 'w+') as testr_conf_file:
             testr_conf_file.write(testr_conf)
 
-    def update_local_conf(self, conf_path, lock_dir, log_dir):
+    def get_configparser(self, conf_path):
         config_parse = moves.configparser.SafeConfigParser()
         config_parse.optionxform = str
-        with open(conf_path, 'a+') as conf_file:
-            # Set local lock_dir in tempest conf
-            if not config_parse.has_section('oslo_concurrency'):
-                config_parse.add_section('oslo_concurrency')
-            config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
-            # Set local log_dir in tempest conf
-            config_parse.set('DEFAULT', 'log_dir', log_dir)
-            # Set default log filename to tempest.log
-            config_parse.set('DEFAULT', 'log_file', 'tempest.log')
+        # get any existing values if a config file already exists
+        if os.path.isfile(conf_path):
+            # use read() for Python 2 and 3 compatibility
+            config_parse.read(conf_path)
+        return config_parse
+
+    def update_local_conf(self, conf_path, lock_dir, log_dir):
+        config_parse = self.get_configparser(conf_path)
+        # Set local lock_dir in tempest conf
+        if not config_parse.has_section('oslo_concurrency'):
+            config_parse.add_section('oslo_concurrency')
+        config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
+        # Set local log_dir in tempest conf
+        config_parse.set('DEFAULT', 'log_dir', log_dir)
+        # Set default log filename to tempest.log
+        config_parse.set('DEFAULT', 'log_file', 'tempest.log')
+
+        # write out a new file with the updated configurations
+        with open(conf_path, 'w+') as conf_file:
             config_parse.write(conf_file)
 
     def copy_config(self, etc_dir, config_dir):
@@ -157,7 +167,8 @@
             subprocess.call(['testr', 'init'], cwd=local_dir)
 
     def take_action(self, parsed_args):
-        workspace_manager = WorkspaceManager(parsed_args.workspace_path)
+        workspace_manager = workspace.WorkspaceManager(
+            parsed_args.workspace_path)
         name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
         workspace_manager.register_new_workspace(
             name, parsed_args.dir, init=True)
diff --git a/tempest/cmd/list_plugins.py b/tempest/cmd/list_plugins.py
index 36e45a5..86732da 100644
--- a/tempest/cmd/list_plugins.py
+++ b/tempest/cmd/list_plugins.py
@@ -21,7 +21,7 @@
 from cliff import command
 import prettytable
 
-from tempest.test_discover.plugins import TempestTestPluginManager
+from tempest.test_discover import plugins as plg
 
 
 class TempestListPlugins(command.Command):
@@ -32,7 +32,7 @@
         return 'List all tempest plugins'
 
     def _list_plugins(self):
-        plugins = TempestTestPluginManager()
+        plugins = plg.TempestTestPluginManager()
 
         output = prettytable.PrettyTable(["Name", "EntryPoint"])
         for plugin in plugins.ext_plugins.extensions:
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 1c0d9c4..fef836c 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -23,7 +23,7 @@
                    any tests that match on re.match() with the regex
  * **--smoke**: Run all the tests tagged as smoke
 
-There are also the **--blacklist_file** and **--whitelist_file** options that
+There are also the **--blacklist-file** and **--whitelist-file** options that
 let you pass a filepath to tempest run with the file format being a line
 separated regex, with '#' used to signify the start of a comment on a line.
 For example::
@@ -191,11 +191,11 @@
                            help='A normal testr selection regex used to '
                                 'specify a subset of tests to run')
         list_selector = parser.add_mutually_exclusive_group()
-        list_selector.add_argument('--whitelist_file',
+        list_selector.add_argument('--whitelist-file', '--whitelist_file',
                                    help="Path to a whitelist file, this file "
                                         "contains a separate regex on each "
                                         "newline.")
-        list_selector.add_argument('--blacklist_file',
+        list_selector.add_argument('--blacklist-file', '--blacklist_file',
                                    help='Path to a blacklist file, this file '
                                         'contains a separate regex exclude on '
                                         'each newline')
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 77b88f9..9947f2a 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -147,6 +147,10 @@
             contains_version('v2.', versions)):
         print_and_or_update('api_v2', 'volume-feature-enabled',
                             not CONF.volume_feature_enabled.api_v2, update)
+    if (CONF.volume_feature_enabled.api_v3 !=
+            contains_version('v3.', versions)):
+        print_and_or_update('api_v3', 'volume-feature-enabled',
+                            not CONF.volume_feature_enabled.api_v3, update)
 
 
 def verify_api_versions(os, service, update):
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index a2edcdc..8e9f0b0 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -101,13 +101,14 @@
                 wait_until = 'ACTIVE'
 
     if volume_backed:
-        volume_name = data_utils.rand_name('volume')
+        volume_name = data_utils.rand_name(__name__ + '-volume')
         volumes_client = clients.volumes_v2_client
         if CONF.volume_feature_enabled.api_v1:
             volumes_client = clients.volumes_client
         volume = volumes_client.create_volume(
             display_name=volume_name,
-            imageRef=image_id)
+            imageRef=image_id,
+            size=CONF.volume.volume_size)
         waiters.wait_for_volume_status(volumes_client,
                                        volume['volume']['id'], 'available')
 
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index 2ca9f40..d8b808b 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -17,7 +17,7 @@
 
 from tempest.lib import auth
 from tempest.lib import exceptions as lib_exc
-from tempest.services.identity.v2.json import identity_client as v2_identity
+from tempest.lib.services.identity.v2 import identity_client as v2_identity
 
 LOG = logging.getLogger(__name__)
 
@@ -40,8 +40,10 @@
         self.roles_client = roles_client
 
     def create_user(self, username, password, project, email):
-        params = self._create_user_params(username, password,
-                                          project['id'], email)
+        params = {'name': username,
+                  'password': password,
+                  self.project_id_param: project['id'],
+                  'email': email}
         user = self.users_client.create_user(**params)
         if 'user' in user:
             user = user['user']
@@ -94,6 +96,7 @@
 
 
 class V2CredsClient(CredsClient):
+    project_id_param = 'tenantId'
 
     def __init__(self, identity_client, projects_client, users_client,
                  roles_client):
@@ -102,13 +105,6 @@
                                             users_client,
                                             roles_client)
 
-    def _create_user_params(self, username, password, project_id, email):
-        params = {'name': username,
-                  'password': password,
-                  'tenantId': project_id,
-                  'email': email}
-        return params
-
     def create_project(self, name, description):
         tenant = self.projects_client.create_tenant(
             name=name, description=description)['tenant']
@@ -135,6 +131,7 @@
 
 
 class V3CredsClient(CredsClient):
+    project_id_param = 'project_id'
 
     def __init__(self, identity_client, projects_client, users_client,
                  roles_client, domains_client, domain_name):
@@ -152,13 +149,6 @@
             msg = "Requested domain %s could not be found" % domain_name
             raise lib_exc.InvalidCredentials(msg)
 
-    def _create_user_params(self, username, password, project_id, email):
-        params = {'user_name': username,
-                  'password': password,
-                  'project_id': project_id,
-                  'email': email}
-        return params
-
     def create_project(self, name, description):
         project = self.projects_client.create_project(
             name=name, description=description,
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index c9b9db1..04c9645 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -401,9 +401,18 @@
             except lib_exc.NotFound:
                 LOG.warning("user with name: %s not found for delete" %
                             creds.username)
+            # NOTE(zhufl): Only when neutron's security_group ext is
+            # enabled, _cleanup_default_secgroup will not raise error. But
+            # here cannot use test.is_extension_enabled for it will cause
+            # "circular dependency". So here just use try...except to
+            # ensure tenant deletion without big changes.
             try:
                 if CONF.service_available.neutron:
                     self._cleanup_default_secgroup(creds.tenant_id)
+            except lib_exc.NotFound:
+                LOG.warning("failed to cleanup tenant %s's secgroup" %
+                            creds.tenant_name)
+            try:
                 self.creds_client.delete_project(creds.tenant_id)
             except lib_exc.NotFound:
                 LOG.warning("tenant with name: %s not found for delete" %
diff --git a/tempest/common/utils/net_utils.py b/tempest/common/utils/net_utils.py
index fd0391d..f0d3da3 100644
--- a/tempest/common/utils/net_utils.py
+++ b/tempest/common/utils/net_utils.py
@@ -37,6 +37,11 @@
         for fixed_ip in port.get('fixed_ips'):
             alloc_set.add(fixed_ip['ip_address'])
 
+    # exclude gateway_ip of subnet
+    gateway_ip = subnet['subnet']['gateway_ip']
+    if gateway_ip:
+        alloc_set.add(gateway_ip)
+
     av_set = subnet_set - alloc_set
     addrs = []
     for cidr in reversed(av_set.iter_cidrs()):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 073481c..9d307ee 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -53,9 +53,7 @@
                     return
                 # NOTE(afazekas): The instance is in "ready for action state"
                 # when no task in progress
-                # NOTE(afazekas): Converted to string because of the XML
-                # responses
-                if str(task_state) == "None":
+                if task_state is None:
                     # without state api extension 3 sec usually enough
                     time.sleep(CONF.compute.ready_wait)
                     return
diff --git a/tempest/config.py b/tempest/config.py
index 6bae021..3fd20ab 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -26,6 +26,7 @@
 import testtools
 
 from tempest.lib import exceptions
+from tempest.lib.services import clients
 from tempest.test_discover import plugins
 
 
@@ -379,8 +380,9 @@
                 help='Does the test environment support creating snapshot '
                      'images of running instances?'),
     cfg.BoolOpt('nova_cert',
-                default=True,
-                help='Does the test environment have the nova cert running?'),
+                default=False,
+                help='Does the test environment have the nova cert running?',
+                deprecated_for_removal=True),
     cfg.BoolOpt('personality',
                 default=False,
                 help='Does the test environment support server personality'),
@@ -501,7 +503,7 @@
                 default=False,
                 help="Whether project networks can be reached directly from "
                      "the test client. This must be set to True when the "
-                     "'fixed' ssh_connect_method is selected."),
+                     "'fixed' connect_method is selected."),
     cfg.StrOpt('public_network_id',
                default="",
                help="Id of the public network that provides external "
@@ -652,7 +654,7 @@
     cfg.StrOpt('network_for_ssh',
                default='public',
                help="Network used for SSH connections. Ignored if "
-                    "connect_method=floating or run_validation=false.",
+                    "connect_method=floating.",
                deprecated_opts=[cfg.DeprecatedOpt('network_for_ssh',
                                                   group='compute')]),
 ]
@@ -1287,6 +1289,15 @@
             lockutils.set_defaults(lock_dir)
             self._config = TempestConfigPrivate(config_path=self._path)
 
+            # Pushing tempest internal service client configuration to the
+            # service clients register. Doing this in the config module ensures
+            # that the configuration is available by the time we register the
+            # service clients.
+            # NOTE(andreaf) This has to be done at the time the first
+            # attribute is accessed, to ensure all plugins have been already
+            # loaded, options registered, and _config is set.
+            _register_tempest_service_clients()
+
         return getattr(self._config, attr)
 
     def set_config_path(self, path):
@@ -1446,3 +1457,29 @@
     # Set service
     _parameters['service'] = getattr(options, 'catalog_type')
     return _parameters
+
+
+def _register_tempest_service_clients():
+    # Register tempest own service clients using the same mechanism used
+    # for external plugins.
+    # The configuration data is pushed to the registry so that automatic
+    # configuration of tempest own service clients is possible both for
+    # tempest as well as for the plugins.
+    service_clients = clients.tempest_modules()
+    registry = clients.ClientsRegistry()
+    all_clients = []
+    for service_client in service_clients:
+        module = service_clients[service_client]
+        configs = service_client.split('.')[0]
+        service_client_data = dict(
+            name=service_client.replace('.', '_'),
+            service_version=service_client,
+            module_path=module.__name__,
+            client_names=module.__all__,
+            **service_client_config(configs)
+        )
+        all_clients.append(service_client_data)
+    # NOTE(andreaf) Internal service clients do not actually belong
+    # to a plugin, so using '__tempest__' to indicate a virtual plugin
+    # which holds internal service clients.
+    registry.register_service_client('__tempest__', all_clients)
diff --git a/tempest/lib/api_schema/response/compute/v2_26/__init__.py b/tempest/lib/api_schema/response/compute/v2_26/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_26/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_26/servers.py b/tempest/lib/api_schema/response/compute/v2_26/servers.py
new file mode 100644
index 0000000..bc5d18e
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_26/servers.py
@@ -0,0 +1,47 @@
+# Copyright 2016 IBM Corp.
+#
+#    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 copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import servers as servers21
+from tempest.lib.api_schema.response.compute.v2_19 import servers as servers219
+
+# The 2.26 microversion changes the server GET and (detailed) LIST responses to
+# include the server 'tags' which is just a list of strings.
+
+tag_items = {
+    'type': 'array',
+    'maxItems': 50,
+    'items': {
+        'type': 'string',
+        'pattern': '^[^,/]*$',
+        'maxLength': 60
+    }
+}
+
+get_server = copy.deepcopy(servers219.get_server)
+get_server['response_body']['properties']['server'][
+    'properties'].update({'tags': tag_items})
+get_server['response_body']['properties']['server'][
+    'required'].append('tags')
+
+list_servers_detail = copy.deepcopy(servers219.list_servers_detail)
+list_servers_detail['response_body']['properties']['servers']['items'][
+    'properties'].update({'tags': tag_items})
+list_servers_detail['response_body']['properties']['servers']['items'][
+    'required'].append('tags')
+
+# list response schema wasn't changed for v2.26 so use v2.1
+
+list_servers = copy.deepcopy(servers21.list_servers)
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 1857a43..83aa405 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -689,6 +689,10 @@
         """Credentials are equal if attributes in self.ATTRIBUTES are equal"""
         return str(self) == str(other)
 
+    def __ne__(self, other):
+        """Contrary to the __eq__"""
+        return not self.__eq__(other)
+
     def __getattr__(self, key):
         # If an attribute is set, __getattr__ is not invoked
         # If an attribute is not set, and it is a known one, return None
diff --git a/tempest/lib/base.py b/tempest/lib/base.py
index f687343..33a32ee 100644
--- a/tempest/lib/base.py
+++ b/tempest/lib/base.py
@@ -42,7 +42,7 @@
     def setUp(self):
         super(BaseTestCase, self).setUp()
         if not self.setUpClassCalled:
-            raise RuntimeError("setUpClass does not calls the super's"
+            raise RuntimeError("setUpClass does not calls the super's "
                                "setUpClass in the "
                                + self.__class__.__name__)
         test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 4e851b0..8507f8a 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -105,6 +105,9 @@
             timeout=http_timeout)
 
     def _get_type(self):
+        if self.TYPE != "json":
+            self.LOG.warning("Tempest has dropped XML support and the TYPE "
+                             "became meaningless")
         return self.TYPE
 
     def get_headers(self, accept_type=None, send_type=None):
@@ -232,8 +235,8 @@
             raise TypeError("'read_code' must be an int instead of (%s)"
                             % type(read_code))
 
-        assert_msg = ("This function only allowed to use for HTTP status"
-                      "codes which explicitly defined in the RFC 7231 & 4918."
+        assert_msg = ("This function only allowed to use for HTTP status "
+                      "codes which explicitly defined in the RFC 7231 & 4918. "
                       "{0} is not a defined Success Code!"
                       ).format(expected_code)
         if isinstance(expected_code, list):
@@ -400,19 +403,14 @@
         else:
             return text
 
-    def _log_request_start(self, method, req_url, req_headers=None,
-                           req_body=None):
-        if req_headers is None:
-            req_headers = {}
+    def _log_request_start(self, method, req_url):
         caller_name = test_utils.find_test_caller()
         if self.trace_requests and re.search(self.trace_requests, caller_name):
             self.LOG.debug('Starting Request (%s): %s %s' %
                            (caller_name, method, req_url))
 
-    def _log_request_full(self, method, req_url, resp,
-                          secs="", req_headers=None,
-                          req_body=None, resp_body=None,
-                          caller_name=None, extra=None):
+    def _log_request_full(self, resp, req_headers=None, req_body=None,
+                          resp_body=None, extra=None):
         if 'X-Auth-Token' in req_headers:
             req_headers['X-Auth-Token'] = '<omitted>'
         # A shallow copy is sufficient
@@ -458,8 +456,8 @@
         # Also look everything at DEBUG if you want to filter this
         # out, don't run at debug.
         if self.LOG.isEnabledFor(real_logging.DEBUG):
-            self._log_request_full(method, req_url, resp, secs, req_headers,
-                                   req_body, resp_body, caller_name, extra)
+            self._log_request_full(resp, req_headers, req_body,
+                                   resp_body, extra)
 
     def _parse_resp(self, body):
         try:
@@ -895,11 +893,11 @@
                                         cls=JSONSCHEMA_VALIDATOR,
                                         format_checker=FORMAT_CHECKER)
                 except jsonschema.ValidationError as ex:
-                    msg = ("HTTP response body is invalid (%s)") % ex
+                    msg = ("HTTP response body is invalid (%s)" % ex)
                     raise exceptions.InvalidHTTPResponseBody(msg)
             else:
                 if body:
-                    msg = ("HTTP response body should not exist (%s)") % body
+                    msg = ("HTTP response body should not exist (%s)" % body)
                     raise exceptions.InvalidHTTPResponseBody(msg)
 
             # Check the header of a response
@@ -910,7 +908,7 @@
                                         cls=JSONSCHEMA_VALIDATOR,
                                         format_checker=FORMAT_CHECKER)
                 except jsonschema.ValidationError as ex:
-                    msg = ("HTTP response header is invalid (%s)") % ex
+                    msg = ("HTTP response header is invalid (%s)" % ex)
                     raise exceptions.InvalidHTTPResponseHeader(msg)
 
 
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index a831dbd..c13f41a 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -77,7 +77,7 @@
                          self.username, self.host)
                 return ssh
             except (EOFError,
-                    socket.error,
+                    socket.error, socket.timeout,
                     paramiko.SSHException) as e:
                 if self._is_timed_out(_start_time):
                     LOG.exception("Failed to establish authenticated ssh"
@@ -121,7 +121,6 @@
             channel.fileno()  # Register event pipe
             channel.exec_command(cmd)
             channel.shutdown_write()
-            exit_status = channel.recv_exit_status()
 
             # If the executing host is linux-based, poll the channel
             if self._can_system_poll():
@@ -162,6 +161,8 @@
                 out_data = out_data.decode(encoding)
                 err_data = err_data.decode(encoding)
 
+            exit_status = channel.recv_exit_status()
+
             if 0 != exit_status:
                 raise exceptions.SSHExecCommandFailed(
                     command=cmd, exit_status=exit_status,
diff --git a/tempest/lib/common/utils/test_utils.py b/tempest/lib/common/utils/test_utils.py
index 50a1a7d..3b28701 100644
--- a/tempest/lib/common/utils/test_utils.py
+++ b/tempest/lib/common/utils/test_utils.py
@@ -14,6 +14,7 @@
 #    under the License.
 import inspect
 import re
+import time
 
 from oslo_log import log as logging
 
@@ -83,3 +84,24 @@
         return func(*args, **kwargs)
     except exceptions.NotFound:
         pass
+
+
+def call_until_true(func, duration, sleep_for):
+    """Call the given function until it returns True (and return True)
+
+    or until the specified duration (in seconds) elapses (and return False).
+
+    :param func: A zero argument callable that returns True on success.
+    :param duration: The number of seconds for which to attempt a
+        successful call of the function.
+    :param sleep_for: The number of seconds to sleep after an unsuccessful
+                      invocation of the function.
+    """
+    now = time.time()
+    timeout = now + duration
+    while now < timeout:
+        if func():
+            return True
+        time.sleep(sleep_for)
+        now = time.time()
+    return False
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index de2d713..e3f25e6 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -100,7 +100,7 @@
 
 
 class OverLimit(ClientRestClientException):
-    message = "Quota exceeded"
+    message = "Request entity is too large"
 
 
 class ServerFault(ServerRestClientException):
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index 8054e62..adf666b 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -1,3 +1,4 @@
+# Copyright 2012 OpenStack Foundation
 # Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
 # All Rights Reserved.
 #
@@ -13,8 +14,94 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import copy
+import importlib
+import inspect
+import logging
+
+from tempest.lib import auth
 from tempest.lib.common.utils import misc
 from tempest.lib import exceptions
+from tempest.lib.services import compute
+from tempest.lib.services import image
+from tempest.lib.services import network
+
+
+LOG = logging.getLogger(__name__)
+
+
+def tempest_modules():
+    """Dict of service client modules available in Tempest.
+
+    Provides a dict of stable service modules available in Tempest, with
+    ``service_version`` as key, and the module object as value.
+    """
+    return {
+        'compute': compute,
+        'image.v1': image.v1,
+        'image.v2': image.v2,
+        'network': network
+    }
+
+
+def _tempest_internal_modules():
+    # Set of unstable service clients available in Tempest
+    # NOTE(andreaf) This list will exists only as long the remain clients
+    # are migrated to tempest.lib, and it will then be deleted without
+    # deprecation or advance notice
+    return set(['identity.v2', 'identity.v3', 'object-storage', 'volume.v1',
+                'volume.v2', 'volume.v3'])
+
+
+def available_modules():
+    """Set of service client modules available in Tempest and plugins
+
+    Set of stable service clients from Tempest and service clients exposed
+    by plugins. This set of available modules can be used for automatic
+    configuration.
+
+    :raise PluginRegistrationException: if a plugin exposes a service_version
+        already defined by Tempest or another plugin.
+
+    Examples:
+
+        >>> from tempest import config
+        >>> params = {}
+        >>> for service_version in available_modules():
+        >>>     service = service_version.split('.')[0]
+        >>>     params[service] = config.service_client_config(service)
+        >>> service_clients = ServiceClients(creds, identity_uri,
+        >>>                                  client_parameters=params)
+    """
+    extra_service_versions = set([])
+    _tempest_modules = set(tempest_modules())
+    plugin_services = ClientsRegistry().get_service_clients()
+    for plugin_name in plugin_services:
+        plug_service_versions = set([x['service_version'] for x in
+                                     plugin_services[plugin_name]])
+        # If a plugin exposes a duplicate service_version raise an exception
+        if plug_service_versions:
+            if not plug_service_versions.isdisjoint(extra_service_versions):
+                detailed_error = (
+                    'Plugin %s is trying to register a service %s already '
+                    'claimed by another one' % (plugin_name,
+                                                extra_service_versions &
+                                                plug_service_versions))
+                raise exceptions.PluginRegistrationException(
+                    name=plugin_name, detailed_error=detailed_error)
+            # NOTE(andreaf) Once all tempest clients are stable, the following
+            # if will have to be removed.
+            if not plug_service_versions.isdisjoint(
+                    _tempest_internal_modules()):
+                detailed_error = (
+                    'Plugin %s is trying to register a service %s already '
+                    'claimed by a Tempest one' % (plugin_name,
+                                                  _tempest_internal_modules() &
+                                                  plug_service_versions))
+                raise exceptions.PluginRegistrationException(
+                    name=plugin_name, detailed_error=detailed_error)
+        extra_service_versions |= plug_service_versions
+    return _tempest_modules | extra_service_versions
 
 
 @misc.singleton
@@ -34,3 +121,327 @@
 
     def get_service_clients(self):
         return self._service_clients
+
+
+class ClientsFactory(object):
+    """Builds service clients for a service client module
+
+    This class implements the logic of feeding service client parameters
+    to service clients from a specific module. It allows setting the
+    parameters once and obtaining new instances of the clients without the
+    need of passing any parameter.
+
+    ClientsFactory can be used directly, or consumed via the `ServiceClients`
+    class, which manages the authorization part.
+    """
+
+    def __init__(self, module_path, client_names, auth_provider, **kwargs):
+        """Initialises the client factory
+
+        :param module_path: Path to module that includes all service clients.
+            All service client classes must be exposed by a single module.
+            If they are separated in different modules, defining __all__
+            in the root module can help, similar to what is done by service
+            clients in tempest.
+        :param client_names: List or set of names of the service client
+            classes.
+        :param auth_provider: The auth provider used to initialise client.
+        :param kwargs: Parameters to be passed to all clients. Parameters
+            values can be overwritten when clients are initialised, but
+            parameters cannot be deleted.
+        :raise ImportError if the specified module_path cannot be imported
+
+        Example:
+
+            >>> # Get credentials and an auth_provider
+            >>> clients = ClientsFactory(
+            >>>     module_path='my_service.my_service_clients',
+            >>>     client_names=['ServiceClient1', 'ServiceClient2'],
+            >>>     auth_provider=auth_provider,
+            >>>     service='my_service',
+            >>>     region='region1')
+            >>> my_api_client = clients.MyApiClient()
+            >>> my_api_client_region2 = clients.MyApiClient(region='region2')
+
+        """
+        # Import the module. If it's not importable, the raised exception
+        # provides good enough information about what happened
+        _module = importlib.import_module(module_path)
+        # If any of the classes is not in the module we fail
+        for class_name in client_names:
+            # TODO(andreaf) This always passes all parameters to all clients.
+            # In future to allow clients to specify the list of parameters
+            # that they accept based out of a list of standard ones.
+
+            # Obtain the class
+            klass = self._get_class(_module, class_name)
+            final_kwargs = copy.copy(kwargs)
+
+            # Set the function as an attribute of the factory
+            setattr(self, class_name, self._get_partial_class(
+                klass, auth_provider, final_kwargs))
+
+    def _get_partial_class(self, klass, auth_provider, kwargs):
+
+        # Define a function that returns a new class instance by
+        # combining default kwargs with extra ones
+        def partial_class(alias=None, **later_kwargs):
+            """Returns a callable the initialises a service client
+
+            Builds a callable that accepts kwargs, which are passed through
+            to the __init__ of the service client, along with a set of defaults
+            set in factory at factory __init__ time.
+            Original args in the service client can only be passed as kwargs.
+
+            It accepts one extra parameter 'alias' compared to the original
+            service client. When alias is provided, the returned callable will
+            also set an attribute called with a name defined in 'alias', which
+            contains the instance of the service client.
+
+            :param alias: str Name of the attribute set on the factory once
+                the callable is invoked which contains the initialised
+                service client. If None, no attribute is set.
+            :param later_kwargs: kwargs passed through to the service client
+                __init__ on top of defaults set at factory level.
+            """
+            kwargs.update(later_kwargs)
+            _client = klass(auth_provider=auth_provider, **kwargs)
+            if alias:
+                setattr(self, alias, _client)
+            return _client
+
+        return partial_class
+
+    @classmethod
+    def _get_class(cls, module, class_name):
+        klass = getattr(module, class_name, None)
+        if not klass:
+            msg = 'Invalid class name, %s is not found in %s'
+            raise AttributeError(msg % (class_name, module))
+        if not inspect.isclass(klass):
+            msg = 'Expected a class, got %s of type %s instead'
+            raise TypeError(msg % (klass, type(klass)))
+        return klass
+
+
+class ServiceClients(object):
+    """Service client provider class
+
+    The ServiceClients object provides a useful means for tests to access
+    service clients configured for a specified set of credentials.
+    It hides some of the complexity from the authorization and configuration
+    layers.
+
+    Examples:
+
+        >>> from tempest.lib.services import clients
+        >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
+        >>> johndoe_clients = clients.ServiceClients(johndoe,
+        >>>                                                  identity_uri)
+        >>> johndoe_servers = johndoe_clients.servers_client.list_servers()
+
+    """
+    # NOTE(andreaf) This class does not depend on tempest configuration
+    # and its meant for direct consumption by external clients such as tempest
+    # plugins. Tempest provides a wrapper class, `clients.Manager`, that
+    # initialises this class using values from tempest CONF object. The wrapper
+    # class should only be used by tests hosted in Tempest.
+
+    def __init__(self, credentials, identity_uri, region=None, scope='project',
+                 disable_ssl_certificate_validation=True, ca_certs=None,
+                 trace_requests='', client_parameters=None):
+        """Service Clients provider
+
+        Instantiate a `ServiceClients` object, from a set of credentials and an
+        identity URI. The identity version is inferred from the credentials
+        object. Optionally auth scope can be provided.
+
+        A few parameters can be given a value which is applied as default
+        for all service clients: region, dscv, ca_certs, trace_requests.
+
+        Parameters dscv, ca_certs and trace_requests all apply to the auth
+        provider as well as any service clients provided by this manager.
+
+        Any other client parameter must be set via client_parameters.
+        The list of available parameters is defined in the service clients
+        interfaces. For reference, most clients will accept 'region',
+        'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
+        are all inherited from RestClient.
+
+        The `config` module in Tempest exposes an helper function
+        `service_client_config` that can be used to extract from configuration
+        a dictionary ready to be injected in kwargs.
+
+        Exceptions are:
+        - Token clients for 'identity' have a very different interface
+        - Volume client for 'volume' accepts 'default_volume_size'
+        - Servers client from 'compute' accepts 'enable_instance_password'
+
+        Examples:
+
+            >>> identity_params = config.service_client_config('identity')
+            >>> params = {
+            >>>     'identity': identity_params,
+            >>>     'compute': {'region': 'region2'}}
+            >>> manager = lib_manager.Manager(
+            >>>     my_creds, identity_uri, client_parameters=params)
+
+        :param credentials: An instance of `auth.Credentials`
+        :param identity_uri: URI of the identity API. This should be a
+                             mandatory parameter, and it will so soon.
+        :param region: Default value of region for service clients.
+        :param scope: default scope for tokens produced by the auth provider
+        :param disable_ssl_certificate_validation: Applies to auth and to all
+                                                  service clients.
+        :param ca_certs: Applies to auth and to all service clients.
+        :param trace_requests: Applies to auth and to all service clients.
+        :param client_parameters: Dictionary with parameters for service
+            clients. Keys of the dictionary are the service client service
+            name, as declared in `service_clients.available_modules()` except
+            for the version. Values are dictionaries of parameters that are
+            going to be passed to all clients in the service client module.
+
+        Examples:
+
+            >>> params_service_x = {'param_name': 'param_value'}
+            >>> client_parameters = { 'service_x': params_service_x }
+
+            >>> params_service_y = config.service_client_config('service_y')
+            >>> client_parameters['service_y'] = params_service_y
+
+        """
+        self._registered_services = set([])
+        self.credentials = credentials
+        self.identity_uri = identity_uri
+        if not identity_uri:
+            raise exceptions.InvalidCredentials(
+                'ServiceClients requires a non-empty identity_uri.')
+        self.region = region
+        # Check if passed or default credentials are valid
+        if not self.credentials.is_valid():
+            raise exceptions.InvalidCredentials()
+        # Get the identity classes matching the provided credentials
+        # TODO(andreaf) Define a new interface in Credentials to get
+        # the API version from an instance
+        identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in
+                    auth.IDENTITY_VERSION.keys() if
+                    isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
+        # Zero matches or more than one are both not valid.
+        if len(identity) != 1:
+            raise exceptions.InvalidCredentials()
+        self.auth_version, auth_provider_class = identity[0]
+        self.dscv = disable_ssl_certificate_validation
+        self.ca_certs = ca_certs
+        self.trace_requests = trace_requests
+        # Creates an auth provider for the credentials
+        self.auth_provider = auth_provider_class(
+            self.credentials, self.identity_uri, scope=scope,
+            disable_ssl_certificate_validation=self.dscv,
+            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
+        # Setup some defaults for client parameters of registered services
+        client_parameters = client_parameters or {}
+        self.parameters = {}
+        # Parameters are provided for unversioned services
+        all_modules = available_modules() | _tempest_internal_modules()
+        unversioned_services = set(
+            [x.split('.')[0] for x in all_modules])
+        for service in unversioned_services:
+            self.parameters[service] = self._setup_parameters(
+                client_parameters.pop(service, {}))
+        # Check that no client parameters was supplied for unregistered clients
+        if client_parameters:
+            raise exceptions.UnknownServiceClient(
+                services=list(client_parameters.keys()))
+
+        # Register service clients from the registry (__tempest__ and plugins)
+        clients_registry = ClientsRegistry()
+        plugin_service_clients = clients_registry.get_service_clients()
+        for plugin in plugin_service_clients:
+            service_clients = plugin_service_clients[plugin]
+            # Each plugin returns a list of service client parameters
+            for service_client in service_clients:
+                # NOTE(andreaf) If a plugin cannot register, stop the
+                # registration process, log some details to help
+                # troubleshooting, and re-raise
+                try:
+                    self.register_service_client_module(**service_client)
+                except Exception:
+                    LOG.exception(
+                        'Failed to register service client from plugin %s '
+                        'with parameters %s' % (plugin, service_client))
+                    raise
+
+    def register_service_client_module(self, name, service_version,
+                                       module_path, client_names, **kwargs):
+        """Register a service client module
+
+        Initiates a client factory for the specified module, using this
+        class auth_provider, and accessible via a `name` attribute in the
+        service client.
+
+        :param name: Name used to access the client
+        :param service_version: Name of the service complete with version.
+            Used to track registered services. When a plugin implements it,
+            it can be used by other plugins to obtain their configuration.
+        :param module_path: Path to module that includes all service clients.
+            All service client classes must be exposed by a single module.
+            If they are separated in different modules, defining __all__
+            in the root module can help, similar to what is done by service
+            clients in tempest.
+        :param client_names: List or set of names of service client classes.
+        :param kwargs: Extra optional parameters to be passed to all clients.
+            ServiceClient provides defaults for region, dscv, ca_certs and
+            trace_requests.
+        :raise ServiceClientRegistrationException: if the provided name is
+            already in use or if service_version is already registered.
+        :raise ImportError: if module_path cannot be imported.
+        """
+        if hasattr(self, name):
+            using_name = getattr(self, name)
+            detailed_error = 'Module name already in use: %s' % using_name
+            raise exceptions.ServiceClientRegistrationException(
+                name=name, service_version=service_version,
+                module_path=module_path, client_names=client_names,
+                detailed_error=detailed_error)
+        if service_version in self.registered_services:
+            detailed_error = 'Service %s already registered.' % service_version
+            raise exceptions.ServiceClientRegistrationException(
+                name=name, service_version=service_version,
+                module_path=module_path, client_names=client_names,
+                detailed_error=detailed_error)
+        params = dict(region=self.region,
+                      disable_ssl_certificate_validation=self.dscv,
+                      ca_certs=self.ca_certs,
+                      trace_requests=self.trace_requests)
+        params.update(kwargs)
+        # Instantiate the client factory
+        _factory = ClientsFactory(module_path=module_path,
+                                  client_names=client_names,
+                                  auth_provider=self.auth_provider,
+                                  **params)
+        # Adds the client factory to the service_client
+        setattr(self, name, _factory)
+        # Add the name of the new service in self.SERVICES for discovery
+        self._registered_services.add(service_version)
+
+    @property
+    def registered_services(self):
+        # NOTE(andreaf) Once all tempest modules are stable this needs to
+        # be updated to remove _tempest_internal_modules
+        return self._registered_services | _tempest_internal_modules()
+
+    def _setup_parameters(self, parameters):
+        """Setup default values for client parameters
+
+        Region by default is the region passed as an __init__ parameter.
+        Checks that no parameter for an unknown service is provided.
+        """
+        _parameters = {}
+        # Use region from __init__
+        if self.region:
+            _parameters['region'] = self.region
+        # Update defaults with specified parameters
+        _parameters.update(parameters)
+        # If any parameter is left, parameters for an unknown service were
+        # provided as input. Fail rather than ignore silently.
+        return _parameters
diff --git a/tempest/lib/services/compute/images_client.py b/tempest/lib/services/compute/images_client.py
index da8a61e..3dc3749 100644
--- a/tempest/lib/services/compute/images_client.py
+++ b/tempest/lib/services/compute/images_client.py
@@ -61,7 +61,6 @@
     def show_image(self, image_id):
         """Return the details of a single image."""
         resp, body = self.get("images/%s" % image_id)
-        self.expected_success(200, resp.status)
         body = json.loads(body)
         self.validate_response(schema.get_image, resp, body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 24c0be9..8b22be0 100755
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -22,6 +22,7 @@
 from tempest.lib.api_schema.response.compute.v2_1 import servers as schema
 from tempest.lib.api_schema.response.compute.v2_16 import servers as schemav216
 from tempest.lib.api_schema.response.compute.v2_19 import servers as schemav219
+from tempest.lib.api_schema.response.compute.v2_26 import servers as schemav226
 from tempest.lib.api_schema.response.compute.v2_3 import servers as schemav23
 from tempest.lib.api_schema.response.compute.v2_9 import servers as schemav29
 from tempest.lib.common import rest_client
@@ -34,7 +35,8 @@
         {'min': '2.3', 'max': '2.8', 'schema': schemav23},
         {'min': '2.9', 'max': '2.15', 'schema': schemav29},
         {'min': '2.16', 'max': '2.18', 'schema': schemav216},
-        {'min': '2.19', 'max': None, 'schema': schemav219}]
+        {'min': '2.19', 'max': '2.25', 'schema': schemav219},
+        {'min': '2.26', 'max': None, 'schema': schemav226}]
 
     def __init__(self, auth_provider, service, region,
                  enable_instance_password=True, **kwargs):
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/lib/services/identity/v2/identity_client.py
similarity index 100%
rename from tempest/services/identity/v2/json/identity_client.py
rename to tempest/lib/services/identity/v2/identity_client.py
diff --git a/tempest/lib/services/identity/v2/roles_client.py b/tempest/lib/services/identity/v2/roles_client.py
index 15c8834..aaa75f1 100644
--- a/tempest/lib/services/identity/v2/roles_client.py
+++ b/tempest/lib/services/identity/v2/roles_client.py
@@ -66,7 +66,7 @@
         Available params: see http://developer.openstack.org/
                               api-ref-identity-v2-ext.html#deleteRole
         """
-        resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id))
+        resp, body = self.delete('OS-KSADM/roles/%s' % role_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
diff --git a/tempest/lib/services/identity/v2/tenants_client.py b/tempest/lib/services/identity/v2/tenants_client.py
index 77ddaa5..f92c703 100644
--- a/tempest/lib/services/identity/v2/tenants_client.py
+++ b/tempest/lib/services/identity/v2/tenants_client.py
@@ -25,7 +25,8 @@
         """Create a tenant
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v2-ext.html#createTenant
+                              api-ref/identity/v2-admin/index.html#
+                              create-tenant
         """
         post_body = json.dumps({'tenant': kwargs})
         resp, body = self.post('tenants', post_body)
@@ -59,7 +60,8 @@
         """Returns tenants.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v2-ext.html#admin-listTenants
+                              api-ref/identity/v2-admin/index.html#
+                              list-tenants-admin-endpoint
         """
         url = 'tenants'
         if params:
@@ -73,7 +75,8 @@
         """Updates a tenant.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v2-ext.html#updateTenant
+                              api-ref/identity/v2-admin/index.html#
+                              update-tenant
         """
         if 'id' not in kwargs:
             kwargs['id'] = tenant_id
@@ -87,7 +90,8 @@
         """List users for a Tenant.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v2-ext.html#listUsersForTenant
+                              api-ref/identity/v2-admin/index.html#
+                              list-users-on-a-tenant
         """
         url = '/tenants/%s/users' % tenant_id
         if params:
diff --git a/tempest/lib/services/identity/v2/users_client.py b/tempest/lib/services/identity/v2/users_client.py
index 4ea17f9..2a266d9 100644
--- a/tempest/lib/services/identity/v2/users_client.py
+++ b/tempest/lib/services/identity/v2/users_client.py
@@ -23,7 +23,8 @@
         """Create a user.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-admin-v2.html#admin-createUser
+                              api-ref/identity/v2-admin/index.html#
+                              create-user-admin-endpoint
         """
         post_body = json.dumps({'user': kwargs})
         resp, body = self.post('users', post_body)
@@ -35,7 +36,8 @@
         """Updates a user.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-admin-v2.html#admin-updateUser
+                              api-ref/identity/v2-admin/index.html#
+                              update-user-admin-endpoint
         """
         put_body = json.dumps({'user': kwargs})
         resp, body = self.put('users/%s' % user_id, put_body)
@@ -68,7 +70,8 @@
         """Get the list of users.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-admin-v2.html#admin-listUsers
+                              api-ref/identity/v2-admin/index.html#
+                              list-users-admin-endpoint
         """
         url = "users"
         if params:
diff --git a/tempest/services/identity/v3/json/projects_client.py b/tempest/lib/services/identity/v3/projects_client.py
similarity index 97%
rename from tempest/services/identity/v3/json/projects_client.py
rename to tempest/lib/services/identity/v3/projects_client.py
index 97e43df..ce2f38d 100644
--- a/tempest/services/identity/v3/json/projects_client.py
+++ b/tempest/lib/services/identity/v3/projects_client.py
@@ -68,6 +68,6 @@
 
     def delete_project(self, project_id):
         """Delete a project."""
-        resp, body = self.delete('projects/%s' % str(project_id))
+        resp, body = self.delete('projects/%s' % project_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/regions_client.py b/tempest/lib/services/identity/v3/regions_client.py
similarity index 100%
rename from tempest/services/identity/v3/json/regions_client.py
rename to tempest/lib/services/identity/v3/regions_client.py
diff --git a/tempest/services/identity/v3/json/services_client.py b/tempest/lib/services/identity/v3/services_client.py
similarity index 84%
rename from tempest/services/identity/v3/json/services_client.py
rename to tempest/lib/services/identity/v3/services_client.py
index e863016..95caf7d 100644
--- a/tempest/services/identity/v3/json/services_client.py
+++ b/tempest/lib/services/identity/v3/services_client.py
@@ -18,6 +18,7 @@
 """
 
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.lib.common import rest_client
 
@@ -57,13 +58,21 @@
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_service(self, serv_id):
-        url = "services/" + serv_id
+    def delete_service(self, service_id):
+        url = "services/" + service_id
         resp, body = self.delete(url)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def list_services(self):
+    def list_services(self, **params):
+        """List services.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-services
+        """
+        url = 'services'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
         resp, body = self.get('services')
         self.expected_success(200, resp.status)
         body = json.loads(body)
diff --git a/tempest/lib/services/image/v2/resource_types_client.py b/tempest/lib/services/image/v2/resource_types_client.py
index 1349c63..8f2a977 100644
--- a/tempest/lib/services/image/v2/resource_types_client.py
+++ b/tempest/lib/services/image/v2/resource_types_client.py
@@ -22,8 +22,54 @@
     api_version = "v2"
 
     def list_resource_types(self):
+        """Lists all resource types.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref/image/v2/metadefs-index.html?expanded=#
+                               list-resource-types
+         """
         url = 'metadefs/resource_types'
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
+
+    def create_resource_type_association(self, namespace_id, **kwargs):
+        """Creates a resource type association in given namespace.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref/image/v2/metadefs-index.html?expanded=#
+                               create-resource-type-association
+         """
+        url = 'metadefs/namespaces/%s/resource_types' % namespace_id
+        data = json.dumps(kwargs)
+        resp, body = self.post(url, data)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_resource_type_association(self, namespace_id):
+        """Lists resource type associations in given namespace.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref/image/v2/metadefs-index.html?expanded=#
+                               list-resource-type-associations
+         """
+        url = 'metadefs/namespaces/%s/resource_types' % namespace_id
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_resource_type_association(self, namespace_id, resource_name):
+        """Removes resource type association in given namespace.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref/image/v2/metadefs-index.html?expanded=#
+                               remove-resource-type-association
+         """
+        url = 'metadefs/namespaces/%s/resource_types/%s' % (namespace_id,
+                                                            resource_name)
+        resp, _ = self.delete(url)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/network/agents_client.py b/tempest/lib/services/network/agents_client.py
index c5d4c66..9bdf090 100644
--- a/tempest/lib/services/network/agents_client.py
+++ b/tempest/lib/services/network/agents_client.py
@@ -44,7 +44,7 @@
         # link to api-site.
         # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526670
         uri = '/agents/%s/l3-routers' % agent_id
-        return self.create_resource(uri, kwargs)
+        return self.create_resource(uri, kwargs, expect_empty_body=True)
 
     def delete_router_from_l3_agent(self, agent_id, router_id):
         uri = '/agents/%s/l3-routers/%s' % (agent_id, router_id)
@@ -65,4 +65,4 @@
         # link to api-site.
         # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1526212
         uri = '/agents/%s/dhcp-networks' % agent_id
-        return self.create_resource(uri, kwargs)
+        return self.create_resource(uri, kwargs, expect_empty_body=True)
diff --git a/tempest/lib/services/network/base.py b/tempest/lib/services/network/base.py
index a6ada04..b6f9c91 100644
--- a/tempest/lib/services/network/base.py
+++ b/tempest/lib/services/network/base.py
@@ -54,18 +54,30 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def create_resource(self, uri, post_data):
+    def create_resource(self, uri, post_data, expect_empty_body=False):
         req_uri = self.uri_prefix + uri
         req_post_data = json.dumps(post_data)
         resp, body = self.post(req_uri, req_post_data)
-        body = json.loads(body)
+        # NOTE: RFC allows both a valid non-empty body and an empty body for
+        # response of POST API. If a body is expected not empty, we decode the
+        # body. Otherwise we returns the body as it is.
+        if not expect_empty_body:
+            body = json.loads(body)
+        else:
+            body = None
         self.expected_success(201, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def update_resource(self, uri, post_data):
+    def update_resource(self, uri, post_data, expect_empty_body=False):
         req_uri = self.uri_prefix + uri
         req_post_data = json.dumps(post_data)
         resp, body = self.put(req_uri, req_post_data)
-        body = json.loads(body)
+        # NOTE: RFC allows both a valid non-empty body and an empty body for
+        # response of PUT API. If a body is expected not empty, we decode the
+        # body. Otherwise we returns the body as it is.
+        if not expect_empty_body:
+            body = json.loads(body)
+        else:
+            body = None
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/network/networks_client.py b/tempest/lib/services/network/networks_client.py
index 7d75bf7..6b601ee 100755
--- a/tempest/lib/services/network/networks_client.py
+++ b/tempest/lib/services/network/networks_client.py
@@ -19,7 +19,7 @@
         """Creates a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#createNetwork
+                              api-ref/networking/v2/index.html#create-network
         """
         uri = '/networks'
         post_data = {'network': kwargs}
@@ -29,7 +29,7 @@
         """Updates a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#updateNetwork
+                              api-ref/networking/v2/index.html#update-network
         """
         uri = '/networks/%s' % network_id
         post_data = {'network': kwargs}
@@ -39,7 +39,7 @@
         """Shows details for a network.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#showNetwork
+                              api-ref/networking/v2/index.html#show-network-details
         """
         uri = '/networks/%s' % network_id
         return self.show_resource(uri, **fields)
@@ -52,7 +52,7 @@
         """Lists networks to which the tenant has access.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#listNetworks
+                              api-ref/networking/v2/index.html#list-networks
         """
         uri = '/networks'
         return self.list_resources(uri, **filters)
@@ -61,7 +61,7 @@
         """Create multiple networks in a single request.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2.html#bulkCreateNetwork
+                              api-ref/networking/v2/index.html#bulk-create-networks
         """
         uri = '/networks'
         return self.create_resource(uri, kwargs)
diff --git a/tempest/lib/services/volume/__init__.py b/tempest/lib/services/volume/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/services/volume/__init__.py
diff --git a/tempest/lib/services/volume/v1/__init__.py b/tempest/lib/services/volume/v1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/services/volume/v1/__init__.py
diff --git a/tempest/services/volume/v1/json/availability_zone_client.py b/tempest/lib/services/volume/v1/availability_zone_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/availability_zone_client.py
rename to tempest/lib/services/volume/v1/availability_zone_client.py
diff --git a/tempest/services/volume/v1/json/extensions_client.py b/tempest/lib/services/volume/v1/extensions_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/extensions_client.py
rename to tempest/lib/services/volume/v1/extensions_client.py
diff --git a/tempest/services/volume/v1/json/admin/hosts_client.py b/tempest/lib/services/volume/v1/hosts_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/admin/hosts_client.py
rename to tempest/lib/services/volume/v1/hosts_client.py
diff --git a/tempest/services/volume/base/admin/base_quotas_client.py b/tempest/lib/services/volume/v1/quotas_client.py
similarity index 91%
rename from tempest/services/volume/base/admin/base_quotas_client.py
rename to tempest/lib/services/volume/v1/quotas_client.py
index 2c1f50d..8924b42 100644
--- a/tempest/services/volume/base/admin/base_quotas_client.py
+++ b/tempest/lib/services/volume/v1/quotas_client.py
@@ -18,8 +18,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseQuotasClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Quotas API requests"""
+class QuotasClient(rest_client.RestClient):
+    """Client class to send CRUD Volume Quotas API V1 requests"""
 
     def show_default_quota_set(self, tenant_id):
         """List the default volume quota set for a tenant."""
@@ -46,7 +46,7 @@
         """Updates quota set
 
         Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#updateQuotas-v2
+                              api-ref-blockstorage-v1.html#updateQuota
         """
         put_body = jsonutils.dumps({'quota_set': kwargs})
         resp, body = self.put('os-quota-sets/%s' % tenant_id, put_body)
diff --git a/tempest/services/volume/v1/json/admin/services_client.py b/tempest/lib/services/volume/v1/services_client.py
similarity index 100%
rename from tempest/services/volume/v1/json/admin/services_client.py
rename to tempest/lib/services/volume/v1/services_client.py
diff --git a/tempest/lib/services/volume/v2/__init__.py b/tempest/lib/services/volume/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/services/volume/v2/__init__.py
diff --git a/tempest/services/volume/v2/json/availability_zone_client.py b/tempest/lib/services/volume/v2/availability_zone_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/availability_zone_client.py
rename to tempest/lib/services/volume/v2/availability_zone_client.py
diff --git a/tempest/services/volume/v2/json/extensions_client.py b/tempest/lib/services/volume/v2/extensions_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/extensions_client.py
rename to tempest/lib/services/volume/v2/extensions_client.py
diff --git a/tempest/services/volume/v2/json/admin/hosts_client.py b/tempest/lib/services/volume/v2/hosts_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/admin/hosts_client.py
rename to tempest/lib/services/volume/v2/hosts_client.py
diff --git a/tempest/services/volume/base/admin/base_quotas_client.py b/tempest/lib/services/volume/v2/quotas_client.py
similarity index 91%
copy from tempest/services/volume/base/admin/base_quotas_client.py
copy to tempest/lib/services/volume/v2/quotas_client.py
index 2c1f50d..a302045 100644
--- a/tempest/services/volume/base/admin/base_quotas_client.py
+++ b/tempest/lib/services/volume/v2/quotas_client.py
@@ -1,4 +1,5 @@
-# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
+# Copyright 2014 OpenStack Foundation
+# 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
@@ -18,8 +19,9 @@
 from tempest.lib.common import rest_client
 
 
-class BaseQuotasClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Quotas API requests"""
+class QuotasClient(rest_client.RestClient):
+    """Client class to send CRUD Volume Quotas API V2 requests"""
+    api_version = "v2"
 
     def show_default_quota_set(self, tenant_id):
         """List the default volume quota set for a tenant."""
diff --git a/tempest/services/volume/v2/json/admin/services_client.py b/tempest/lib/services/volume/v2/services_client.py
similarity index 100%
rename from tempest/services/volume/v2/json/admin/services_client.py
rename to tempest/lib/services/volume/v2/services_client.py
diff --git a/tempest/manager.py b/tempest/manager.py
index 3d495b6..e3174d4 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -15,15 +15,15 @@
 
 from oslo_log import log as logging
 
-from tempest import clients
+from tempest import clients as tempest_clients
 from tempest import config
-from tempest import service_clients
+from tempest.lib.services import clients
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
 
 
-class Manager(service_clients.ServiceClients):
+class Manager(clients.ServiceClients):
     """Service client manager class for backward compatibility
 
     The former manager.Manager is not a stable interface in Tempest,
@@ -37,7 +37,7 @@
                "soon as the client manager becomes available in tempest.lib.")
         LOG.warning(msg)
         dscv = CONF.identity.disable_ssl_certificate_validation
-        _, uri = clients.get_auth_provider_class(credentials)
+        _, uri = tempest_clients.get_auth_provider_class(credentials)
         super(Manager, self).__init__(
             credentials=credentials, scope=scope,
             identity_uri=uri,
@@ -58,5 +58,5 @@
            "as such it should not imported directly. It will be removed as "
            "the client manager becomes available in tempest.lib.")
     LOG.warning(msg)
-    return clients.get_auth_provider(credentials=credentials,
-                                     pre_auth=pre_auth, scope=scope)
+    return tempest_clients.get_auth_provider(credentials=credentials,
+                                             pre_auth=pre_auth, scope=scope)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 952c0c2..a3f832a 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -87,63 +87,26 @@
             cls.volumes_client = cls.manager.volumes_v2_client
             cls.snapshots_client = cls.manager.snapshots_v2_client
 
-    # ## Methods to handle sync and async deletes
-
-    def setUp(self):
-        super(ScenarioTest, self).setUp()
-        self.cleanup_waits = []
-        # NOTE(mtreinish) This is safe to do in setUp instead of setUp class
-        # because scenario tests in the same test class should not share
-        # resources. If resources were shared between test cases then it
-        # should be a single scenario test instead of multiples.
-
-        # NOTE(yfried): this list is cleaned at the end of test_methods and
-        # not at the end of the class
-        self.addCleanup(self._wait_for_cleanups)
-
-    def addCleanup_with_wait(self, waiter_callable, thing_id, thing_id_param,
-                             cleanup_callable, cleanup_args=None,
-                             cleanup_kwargs=None, waiter_client=None):
-        """Adds wait for async resource deletion at the end of cleanups
-
-        @param waiter_callable: callable to wait for the resource to delete
-            with the following waiter_client if specified.
-        @param thing_id: the id of the resource to be cleaned-up
-        @param thing_id_param: the name of the id param in the waiter
-        @param cleanup_callable: method to load pass to self.addCleanup with
-            the following *cleanup_args, **cleanup_kwargs.
-            usually a delete method.
-        """
-        if cleanup_args is None:
-            cleanup_args = []
-        if cleanup_kwargs is None:
-            cleanup_kwargs = {}
-        self.addCleanup(cleanup_callable, *cleanup_args, **cleanup_kwargs)
-        wait_dict = {
-            'waiter_callable': waiter_callable,
-            thing_id_param: thing_id
-        }
-        if waiter_client:
-            wait_dict['client'] = waiter_client
-        self.cleanup_waits.append(wait_dict)
-
-    def _wait_for_cleanups(self):
-        # To handle async delete actions, a list of waits is added
-        # which will be iterated over as the last step of clearing the
-        # cleanup queue. That way all the delete calls are made up front
-        # and the tests won't succeed unless the deletes are eventually
-        # successful. This is the same basic approach used in the api tests to
-        # limit cleanup execution time except here it is multi-resource,
-        # because of the nature of the scenario tests.
-        for wait in self.cleanup_waits:
-            waiter_callable = wait.pop('waiter_callable')
-            waiter_callable(**wait)
-
     # ## Test functions library
     #
     # The create_[resource] functions only return body and discard the
     # resp part which is not used in scenario tests
 
+    def _create_port(self, network_id, client=None, namestart='port-quotatest',
+                     **kwargs):
+        if not client:
+            client = self.ports_client
+        name = data_utils.rand_name(namestart)
+        result = client.create_port(
+            name=name,
+            network_id=network_id,
+            **kwargs)
+        self.assertIsNotNone(result, 'Unable to allocate port')
+        port = result['port']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        client.delete_port, port['id'])
+        return port
+
     def create_keypair(self, client=None):
         if not client:
             client = self.keypairs_client
@@ -155,7 +118,7 @@
 
     def create_server(self, name=None, image_id=None, flavor=None,
                       validatable=False, wait_until=None,
-                      wait_on_delete=True, clients=None, **kwargs):
+                      clients=None, **kwargs):
         """Wrapper utility that returns a test server.
 
         This wrapper utility calls the common create test server and
@@ -209,18 +172,18 @@
                 networks = []
 
             # If there are no networks passed to us we look up
-            # for the project's private networks and create a port
-            # if there is only one private network. The same behaviour
-            # as we would expect when passing the call to the clients
-            # with no networks
+            # for the project's private networks and create a port.
+            # The same behaviour as we would expect when passing
+            # the call to the clients with no networks
             if not networks:
                 networks = clients.networks_client.list_networks(
-                    filters={'router:external': False})
-                self.assertEqual(1, len(networks),
-                                 "There is more than one"
-                                 " network for the tenant")
+                    **{'router:external': False, 'fields': 'id'})['networks']
+
+            # It's net['uuid'] if networks come from kwargs
+            # and net['id'] if they come from
+            # clients.networks_client.list_networks
             for net in networks:
-                net_id = net['uuid']
+                net_id = net.get('uuid', net.get('id'))
                 if 'port' not in net:
                     port = self._create_port(network_id=net_id,
                                              client=clients.ports_client,
@@ -241,31 +204,24 @@
             name=name, flavor=flavor,
             image_id=image_id, **kwargs)
 
-        # TODO(jlanoux) Move wait_on_delete in compute.py
-        if wait_on_delete:
-            self.addCleanup(waiters.wait_for_server_termination,
-                            clients.servers_client,
-                            body['id'])
-
-        self.addCleanup_with_wait(
-            waiter_callable=waiters.wait_for_server_termination,
-            thing_id=body['id'], thing_id_param='server_id',
-            cleanup_callable=test_utils.call_and_ignore_notfound_exc,
-            cleanup_args=[clients.servers_client.delete_server, body['id']],
-            waiter_client=clients.servers_client)
+        self.addCleanup(waiters.wait_for_server_termination,
+                        clients.servers_client, body['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        clients.servers_client.delete_server, body['id'])
         server = clients.servers_client.show_server(body['id'])['server']
         return server
 
     def create_volume(self, size=None, name=None, snapshot_id=None,
                       imageRef=None, volume_type=None):
+        if size is None:
+            size = CONF.volume.volume_size
         if name is None:
             name = data_utils.rand_name(self.__class__.__name__)
         kwargs = {'display_name': name,
                   'snapshot_id': snapshot_id,
                   'imageRef': imageRef,
-                  'volume_type': volume_type}
-        if size is not None:
-            kwargs.update({'size': size})
+                  'volume_type': volume_type,
+                  'size': size}
         volume = self.volumes_client.create_volume(**kwargs)['volume']
 
         self.addCleanup(self.volumes_client.wait_for_resource_deletion,
@@ -466,11 +422,12 @@
         image = _images_client.create_image(server['id'], name=name)
         image_id = image.response['location'].split('images/')[1]
         waiters.wait_for_image_status(_image_client, image_id, 'active')
-        self.addCleanup_with_wait(
-            waiter_callable=_image_client.wait_for_resource_deletion,
-            thing_id=image_id, thing_id_param='id',
-            cleanup_callable=test_utils.call_and_ignore_notfound_exc,
-            cleanup_args=[_image_client.delete_image, image_id])
+
+        self.addCleanup(_image_client.wait_for_resource_deletion,
+                        image_id)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        _image_client.delete_image, image_id)
+
         if CONF.image_feature_enabled.api_v1:
             # In glance v1 the additional properties are stored in the headers.
             resp = _image_client.check_image(image_id)
@@ -557,7 +514,7 @@
                       'should_succeed':
                       'reachable' if should_succeed else 'unreachable'
                   })
-        result = tempest.test.call_until_true(ping, timeout, 1)
+        result = test_utils.call_until_true(ping, timeout, 1)
         LOG.debug('%(caller)s finishes ping %(ip)s in %(timeout)s sec and the '
                   'ping result is %(result)s' % {
                       'caller': caller, 'ip': ip_address, 'timeout': timeout,
@@ -813,21 +770,6 @@
 
         return subnet
 
-    def _create_port(self, network_id, client=None, namestart='port-quotatest',
-                     **kwargs):
-        if not client:
-            client = self.ports_client
-        name = data_utils.rand_name(namestart)
-        result = client.create_port(
-            name=name,
-            network_id=network_id,
-            **kwargs)
-        self.assertIsNotNone(result, 'Unable to allocate port')
-        port = result['port']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        client.delete_port, port['id'])
-        return port
-
     def _get_server_port_id_and_ip4(self, server, ip_addr=None):
         ports = self._list_ports(device_id=server['id'], fixed_ip=ip_addr)
         # A port can have more then one IP address in some cases.
@@ -916,9 +858,9 @@
                       show_floatingip(floatingip_id)['floatingip'])
             return status == result['status']
 
-        tempest.test.call_until_true(refresh,
-                                     CONF.network.build_timeout,
-                                     CONF.network.build_interval)
+        test_utils.call_until_true(refresh,
+                                   CONF.network.build_timeout,
+                                   CONF.network.build_interval)
         floating_ip = self.floating_ips_client.show_floatingip(
             floatingip_id)['floatingip']
         self.assertEqual(status, floating_ip['status'],
@@ -973,9 +915,9 @@
                 return not should_succeed
             return should_succeed
 
-        return tempest.test.call_until_true(ping_remote,
-                                            CONF.validation.ping_timeout,
-                                            1)
+        return test_utils.call_until_true(ping_remote,
+                                          CONF.validation.ping_timeout,
+                                          1)
 
     def _create_security_group(self, security_group_rules_client=None,
                                tenant_id=None,
@@ -1308,7 +1250,7 @@
                 return True
             return False
 
-        if not tempest.test.call_until_true(
+        if not test_utils.call_until_true(
             check_state, timeout, interval):
             msg = ("Timed out waiting for node %s to reach %s state(s) %s" %
                    (node_id, state_attr, target_states))
@@ -1332,7 +1274,7 @@
                 self.get_node, instance_id=instance_id)
             return node is not None
 
-        if not tempest.test.call_until_true(
+        if not test_utils.call_until_true(
             _get_node, CONF.baremetal.association_timeout, 1):
             msg = ('Timed out waiting to get Ironic node by instance id %s'
                    % instance_id)
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index 655d19d..45c38f6 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -15,17 +15,14 @@
 
 from oslo_log import log as logging
 
-from tempest import config
 from tempest.scenario import manager
 from tempest import test
 
-CONF = config.CONF
-
 LOG = logging.getLogger(__name__)
 
 
 class BaremetalBasicOps(manager.BaremetalScenarioTest):
-    """This smoke test tests the pxe_ssh Ironic driver.
+    """This test tests the pxe_ssh Ironic driver.
 
     It follows this basic set of operations:
         * Creates a keypair
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index dcd77ad..1659ebe 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -53,7 +53,7 @@
         volume_type = self.create_volume_type(name=volume_type)
         self.create_encryption_type(type_id=volume_type['id'],
                                     provider=encryption_provider,
-                                    key_size=512,
+                                    key_size=256,
                                     cipher='aes-xts-plain64',
                                     control_location='front-end')
         return self.create_volume(volume_type=volume_type['name'])
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index f7c7434..dba1c92 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -17,6 +17,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import test_utils
 from tempest.scenario import manager
 from tempest import test
 
@@ -88,9 +89,9 @@
                     ['server'])
             return {'name': secgroup['name']} in body['security_groups']
 
-        if not test.call_until_true(wait_for_secgroup_add,
-                                    CONF.compute.build_timeout,
-                                    CONF.compute.build_interval):
+        if not test_utils.call_until_true(wait_for_secgroup_add,
+                                          CONF.compute.build_timeout,
+                                          CONF.compute.build_interval):
             msg = ('Timed out waiting for adding security group %s to server '
                    '%s' % (secgroup['id'], server['id']))
             raise exceptions.TimeoutException(msg)
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index e4b699e..a89147a 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -58,7 +58,7 @@
             security_groups = [{'name': security_group['name']}]
         network, subnet, router = self.create_networks()
         public_network_id = CONF.network.public_network_id
-        server_name = data_utils.rand_name('server-smoke')
+        server_name = data_utils.rand_name('server')
         server = self.create_server(
             name=server_name,
             networks=[{'uuid': network['id']}],
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 9c48080..519dbec 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -24,6 +24,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
 
@@ -262,8 +263,9 @@
                                   if port['id'] != old_port['id']]
             return len(self.new_port_list) == 1
 
-        if not test.call_until_true(check_ports, CONF.network.build_timeout,
-                                    CONF.network.build_interval):
+        if not test_utils.call_until_true(
+                check_ports, CONF.network.build_timeout,
+                CONF.network.build_interval):
             raise exceptions.TimeoutException(
                 "No new port attached to the server in time (%s sec)! "
                 "Old port: %s. Number of new ports: %d" % (
@@ -276,8 +278,9 @@
             self.diff_list = [n for n in new_nic_list if n not in old_nic_list]
             return len(self.diff_list) == 1
 
-        if not test.call_until_true(check_new_nic, CONF.network.build_timeout,
-                                    CONF.network.build_interval):
+        if not test_utils.call_until_true(
+                check_new_nic, CONF.network.build_timeout,
+                CONF.network.build_interval):
             raise exceptions.TimeoutException("Interface not visible on the "
                                               "guest after %s sec"
                                               % CONF.network.build_timeout)
@@ -410,6 +413,7 @@
     @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
     @testtools.skipIf(CONF.baremetal.driver_enabled,
                       'Baremetal relies on a shared physical network.')
+    @decorators.skip_because(bug="1610994")
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
         """Test connectivity between VMs on different networks
@@ -591,9 +595,9 @@
                 return False
             return True
 
-        self.assertTrue(test.call_until_true(check_new_dns_server,
-                                             renew_timeout,
-                                             renew_delay),
+        self.assertTrue(test_utils.call_until_true(check_new_dns_server,
+                                                   renew_timeout,
+                                                   renew_delay),
                         msg="DHCP renewal failed to fetch "
                             "new DNS nameservers")
 
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 364b6f5..dd86d90 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -187,10 +187,10 @@
             srv2_v6_addr_assigned = functools.partial(
                 guest_has_address, sshv4_2, ips_from_api_2['6'][i])
 
-            self.assertTrue(test.call_until_true(srv1_v6_addr_assigned,
+            self.assertTrue(test_utils.call_until_true(srv1_v6_addr_assigned,
                             CONF.validation.ping_timeout, 1))
 
-            self.assertTrue(test.call_until_true(srv2_v6_addr_assigned,
+            self.assertTrue(test_utils.call_until_true(srv2_v6_addr_assigned,
                             CONF.validation.ping_timeout, 1))
 
         self._check_connectivity(sshv4_1, ips_from_api_2['4'])
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 63ffa0b..9ac1e30 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -13,12 +13,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest import config
 from tempest.scenario import manager
 from tempest import test
 
-CONF = config.CONF
-
 
 class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
     """Test swift basic ops.
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 60dca3d..e031ff7 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -18,6 +18,7 @@
 
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import test_utils
 from tempest.scenario import manager
 from tempest import test
 
@@ -70,9 +71,9 @@
                     self.assertEqual(self.fip, result, msg)
                     return 'Verification is successful!'
 
-            if not test.call_until_true(exec_cmd_and_verify_output,
-                                        CONF.compute.build_timeout,
-                                        CONF.compute.build_interval):
+            if not test_utils.call_until_true(exec_cmd_and_verify_output,
+                                              CONF.compute.build_timeout,
+                                              CONF.compute.build_interval):
                 raise exceptions.TimeoutException('Timed out while waiting to '
                                                   'verify metadata on server. '
                                                   '%s is empty.' % md_url)
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 4b9c61c..7f04b0d 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -53,25 +53,12 @@
         security_group = self._create_security_group()
         security_groups = [{'name': security_group['name']}]
 
-        if boot_from_volume:
-            volume = self.create_volume(size=CONF.volume.volume_size,
-                                        imageRef=CONF.compute.image_ref)
-            bd_map = [{
-                'device_name': 'vda',
-                'volume_id': volume['id'],
-                'delete_on_termination': '0'}]
-
-            server = self.create_server(
-                key_name=keypair['name'],
-                security_groups=security_groups,
-                block_device_mapping=bd_map,
-                wait_until='ACTIVE')
-        else:
-            server = self.create_server(
-                image_id=CONF.compute.image_ref,
-                key_name=keypair['name'],
-                security_groups=security_groups,
-                wait_until='ACTIVE')
+        server = self.create_server(
+            image_id=CONF.compute.image_ref,
+            key_name=keypair['name'],
+            security_groups=security_groups,
+            wait_until='ACTIVE',
+            volume_backed=boot_from_volume)
 
         instance_ip = self.get_server_ip(server)
         timestamp = self.create_timestamp(instance_ip,
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index e7223c7..5fd934c 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -22,6 +22,7 @@
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest.scenario import manager
@@ -89,9 +90,9 @@
             LOG.debug("Partitions:%s" % part)
             return CONF.compute.volume_device_name in part
 
-        if not test.call_until_true(_func,
-                                    CONF.compute.build_timeout,
-                                    CONF.compute.build_interval):
+        if not test_utils.call_until_true(_func,
+                                          CONF.compute.build_timeout,
+                                          CONF.compute.build_interval):
             raise exceptions.TimeoutException
 
     @decorators.skip_because(bug="1205344")
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
old mode 100644
new mode 100755
index 25d825a..3f6d9c4
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -48,7 +48,8 @@
 
     def _create_volume_from_image(self):
         img_uuid = CONF.compute.image_ref
-        vol_name = data_utils.rand_name('volume-origin')
+        vol_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume-origin')
         return self.create_volume(name=vol_name, imageRef=img_uuid)
 
     def _get_bdm(self, vol_id, delete_on_termination=False):
@@ -79,7 +80,8 @@
             **create_kwargs)
 
     def _create_snapshot_from_volume(self, vol_id):
-        snap_name = data_utils.rand_name('snapshot')
+        snap_name = data_utils.rand_name(
+            self.__class__.__name__ + '-snapshot')
         snap = self.snapshots_client.create_snapshot(
             volume_id=vol_id,
             force=True,
@@ -99,7 +101,8 @@
         return snap
 
     def _create_volume_from_snapshot(self, snap_id):
-        vol_name = data_utils.rand_name('volume')
+        vol_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume')
         return self.create_volume(name=vol_name, snapshot_id=snap_id)
 
     def _delete_server(self, server):
@@ -170,7 +173,7 @@
         instance = self._boot_instance_from_volume(volume_origin['id'],
                                                    delete_on_termination=True)
         # create EBS image
-        name = data_utils.rand_name('image')
+        name = data_utils.rand_name(self.__class__.__name__ + '-image')
         image = self.create_server_snapshot(instance, name=name)
 
         # delete instance
diff --git a/tempest/service_clients.py b/tempest/service_clients.py
deleted file mode 100644
index 136ad65..0000000
--- a/tempest/service_clients.py
+++ /dev/null
@@ -1,425 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
-# 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.
-
-import copy
-import importlib
-import inspect
-import logging
-
-from tempest.lib import auth
-from tempest.lib import exceptions
-from tempest.lib.services import clients
-from tempest.lib.services import compute
-from tempest.lib.services import image
-from tempest.lib.services import network
-
-LOG = logging.getLogger(__name__)
-
-client_modules_by_service_name = {
-    'compute': compute,
-    'image.v1': image.v1,
-    'image.v2': image.v2,
-    'network': network
-}
-
-
-def tempest_modules():
-    """List of service client modules available in Tempest.
-
-    Provides a list of service modules available Tempest.
-    """
-    return set(['compute', 'identity.v2', 'identity.v3', 'image.v1',
-                'image.v2', 'network', 'object-storage', 'volume.v1',
-                'volume.v2', 'volume.v3'])
-
-
-def available_modules():
-    """List of service client modules available in Tempest and plugins
-
-    The list of available modules can be used for automatic configuration.
-
-    :raise PluginRegistrationException: if a plugin exposes a service_version
-        already defined by Tempest or another plugin.
-
-    Examples:
-
-        >>> from tempest import config
-        >>> params = {}
-        >>> for service_version in available_modules():
-        >>>     service = service_version.split('.')[0]
-        >>>     params[service] = config.service_client_config(service)
-        >>> service_clients = ServiceClients(creds, identity_uri,
-        >>>                                  client_parameters=params)
-    """
-    extra_service_versions = set([])
-    plugin_services = clients.ClientsRegistry().get_service_clients()
-    for plugin_name in plugin_services:
-        plug_service_versions = set([x['service_version'] for x in
-                                     plugin_services[plugin_name]])
-        # If a plugin exposes a duplicate service_version raise an exception
-        if plug_service_versions:
-            if not plug_service_versions.isdisjoint(extra_service_versions):
-                detailed_error = (
-                    'Plugin %s is trying to register a service %s already '
-                    'claimed by another one' % (plugin_name,
-                                                extra_service_versions &
-                                                plug_service_versions))
-                raise exceptions.PluginRegistrationException(
-                    name=plugin_name, detailed_error=detailed_error)
-            if not plug_service_versions.isdisjoint(tempest_modules()):
-                detailed_error = (
-                    'Plugin %s is trying to register a service %s already '
-                    'claimed by a Tempest one' % (plugin_name,
-                                                  tempest_modules() &
-                                                  plug_service_versions))
-                raise exceptions.PluginRegistrationException(
-                    name=plugin_name, detailed_error=detailed_error)
-        extra_service_versions |= plug_service_versions
-    return tempest_modules() | extra_service_versions
-
-
-class ClientsFactory(object):
-    """Builds service clients for a service client module
-
-    This class implements the logic of feeding service client parameters
-    to service clients from a specific module. It allows setting the
-    parameters once and obtaining new instances of the clients without the
-    need of passing any parameter.
-
-    ClientsFactory can be used directly, or consumed via the `ServiceClients`
-    class, which manages the authorization part.
-    """
-
-    def __init__(self, module_path, client_names, auth_provider, **kwargs):
-        """Initialises the client factory
-
-        :param module_path: Path to module that includes all service clients.
-            All service client classes must be exposed by a single module.
-            If they are separated in different modules, defining __all__
-            in the root module can help, similar to what is done by service
-            clients in tempest.
-        :param client_names: List or set of names of the service client
-            classes.
-        :param auth_provider: The auth provider used to initialise client.
-        :param kwargs: Parameters to be passed to all clients. Parameters
-            values can be overwritten when clients are initialised, but
-            parameters cannot be deleted.
-        :raise ImportError if the specified module_path cannot be imported
-
-        Example:
-
-            >>> # Get credentials and an auth_provider
-            >>> clients = ClientsFactory(
-            >>>     module_path='my_service.my_service_clients',
-            >>>     client_names=['ServiceClient1', 'ServiceClient2'],
-            >>>     auth_provider=auth_provider,
-            >>>     service='my_service',
-            >>>     region='region1')
-            >>> my_api_client = clients.MyApiClient()
-            >>> my_api_client_region2 = clients.MyApiClient(region='region2')
-
-        """
-        # Import the module. If it's not importable, the raised exception
-        # provides good enough information about what happened
-        _module = importlib.import_module(module_path)
-        # If any of the classes is not in the module we fail
-        for class_name in client_names:
-            # TODO(andreaf) This always passes all parameters to all clients.
-            # In future to allow clients to specify the list of parameters
-            # that they accept based out of a list of standard ones.
-
-            # Obtain the class
-            klass = self._get_class(_module, class_name)
-            final_kwargs = copy.copy(kwargs)
-
-            # Set the function as an attribute of the factory
-            setattr(self, class_name, self._get_partial_class(
-                klass, auth_provider, final_kwargs))
-
-    def _get_partial_class(self, klass, auth_provider, kwargs):
-
-        # Define a function that returns a new class instance by
-        # combining default kwargs with extra ones
-        def partial_class(alias=None, **later_kwargs):
-            """Returns a callable the initialises a service client
-
-            Builds a callable that accepts kwargs, which are passed through
-            to the __init__ of the service client, along with a set of defaults
-            set in factory at factory __init__ time.
-            Original args in the service client can only be passed as kwargs.
-
-            It accepts one extra parameter 'alias' compared to the original
-            service client. When alias is provided, the returned callable will
-            also set an attribute called with a name defined in 'alias', which
-            contains the instance of the service client.
-
-            :param alias: str Name of the attribute set on the factory once
-                the callable is invoked which contains the initialised
-                service client. If None, no attribute is set.
-            :param later_kwargs: kwargs passed through to the service client
-                __init__ on top of defaults set at factory level.
-            """
-            kwargs.update(later_kwargs)
-            _client = klass(auth_provider=auth_provider, **kwargs)
-            if alias:
-                setattr(self, alias, _client)
-            return _client
-
-        return partial_class
-
-    @classmethod
-    def _get_class(cls, module, class_name):
-        klass = getattr(module, class_name, None)
-        if not klass:
-            msg = 'Invalid class name, %s is not found in %s'
-            raise AttributeError(msg % (class_name, module))
-        if not inspect.isclass(klass):
-            msg = 'Expected a class, got %s of type %s instead'
-            raise TypeError(msg % (klass, type(klass)))
-        return klass
-
-
-class ServiceClients(object):
-    """Service client provider class
-
-    The ServiceClients object provides a useful means for tests to access
-    service clients configured for a specified set of credentials.
-    It hides some of the complexity from the authorization and configuration
-    layers.
-
-    Examples:
-
-        >>> from tempest import service_clients
-        >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
-        >>> johndoe_clients = service_clients.ServiceClients(johndoe,
-        >>>                                                  identity_uri)
-        >>> johndoe_servers = johndoe_clients.servers_client.list_servers()
-
-    """
-    # NOTE(andreaf) This class does not depend on tempest configuration
-    # and its meant for direct consumption by external clients such as tempest
-    # plugins. Tempest provides a wrapper class, `clients.Manager`, that
-    # initialises this class using values from tempest CONF object. The wrapper
-    # class should only be used by tests hosted in Tempest.
-
-    def __init__(self, credentials, identity_uri, region=None, scope='project',
-                 disable_ssl_certificate_validation=True, ca_certs=None,
-                 trace_requests='', client_parameters=None):
-        """Service Clients provider
-
-        Instantiate a `ServiceClients` object, from a set of credentials and an
-        identity URI. The identity version is inferred from the credentials
-        object. Optionally auth scope can be provided.
-
-        A few parameters can be given a value which is applied as default
-        for all service clients: region, dscv, ca_certs, trace_requests.
-
-        Parameters dscv, ca_certs and trace_requests all apply to the auth
-        provider as well as any service clients provided by this manager.
-
-        Any other client parameter must be set via client_parameters.
-        The list of available parameters is defined in the service clients
-        interfaces. For reference, most clients will accept 'region',
-        'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
-        are all inherited from RestClient.
-
-        The `config` module in Tempest exposes an helper function
-        `service_client_config` that can be used to extract from configuration
-        a dictionary ready to be injected in kwargs.
-
-        Exceptions are:
-        - Token clients for 'identity' have a very different interface
-        - Volume client for 'volume' accepts 'default_volume_size'
-        - Servers client from 'compute' accepts 'enable_instance_password'
-
-        Examples:
-
-            >>> identity_params = config.service_client_config('identity')
-            >>> params = {
-            >>>     'identity': identity_params,
-            >>>     'compute': {'region': 'region2'}}
-            >>> manager = lib_manager.Manager(
-            >>>     my_creds, identity_uri, client_parameters=params)
-
-        :param credentials: An instance of `auth.Credentials`
-        :param identity_uri: URI of the identity API. This should be a
-                             mandatory parameter, and it will so soon.
-        :param region: Default value of region for service clients.
-        :param scope: default scope for tokens produced by the auth provider
-        :param disable_ssl_certificate_validation: Applies to auth and to all
-                                                  service clients.
-        :param ca_certs: Applies to auth and to all service clients.
-        :param trace_requests: Applies to auth and to all service clients.
-        :param client_parameters: Dictionary with parameters for service
-            clients. Keys of the dictionary are the service client service
-            name, as declared in `service_clients.available_modules()` except
-            for the version. Values are dictionaries of parameters that are
-            going to be passed to all clients in the service client module.
-
-        Examples:
-
-            >>> params_service_x = {'param_name': 'param_value'}
-            >>> client_parameters = { 'service_x': params_service_x }
-
-            >>> params_service_y = config.service_client_config('service_y')
-            >>> client_parameters['service_y'] = params_service_y
-
-        """
-        self._registered_services = set([])
-        self.credentials = credentials
-        self.identity_uri = identity_uri
-        if not identity_uri:
-            raise exceptions.InvalidCredentials(
-                'ServiceClients requires a non-empty identity_uri.')
-        self.region = region
-        # Check if passed or default credentials are valid
-        if not self.credentials.is_valid():
-            raise exceptions.InvalidCredentials()
-        # Get the identity classes matching the provided credentials
-        # TODO(andreaf) Define a new interface in Credentials to get
-        # the API version from an instance
-        identity = [(k, auth.IDENTITY_VERSION[k][1]) for k in
-                    auth.IDENTITY_VERSION.keys() if
-                    isinstance(self.credentials, auth.IDENTITY_VERSION[k][0])]
-        # Zero matches or more than one are both not valid.
-        if len(identity) != 1:
-            raise exceptions.InvalidCredentials()
-        self.auth_version, auth_provider_class = identity[0]
-        self.dscv = disable_ssl_certificate_validation
-        self.ca_certs = ca_certs
-        self.trace_requests = trace_requests
-        # Creates an auth provider for the credentials
-        self.auth_provider = auth_provider_class(
-            self.credentials, self.identity_uri, scope=scope,
-            disable_ssl_certificate_validation=self.dscv,
-            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
-        # Setup some defaults for client parameters of registered services
-        client_parameters = client_parameters or {}
-        self.parameters = {}
-        # Parameters are provided for unversioned services
-        unversioned_services = set(
-            [x.split('.')[0] for x in available_modules()])
-        for service in unversioned_services:
-            self.parameters[service] = self._setup_parameters(
-                client_parameters.pop(service, {}))
-        # Check that no client parameters was supplied for unregistered clients
-        if client_parameters:
-            raise exceptions.UnknownServiceClient(
-                services=list(client_parameters.keys()))
-
-        # Register service clients owned by tempest
-        for service in tempest_modules():
-            if service in list(client_modules_by_service_name):
-                attribute = service.replace('.', '_')
-                configs = service.split('.')[0]
-                module = client_modules_by_service_name[service]
-                self.register_service_client_module(
-                    attribute, service, module.__name__,
-                    module.__all__, **self.parameters[configs])
-
-        # Register service clients from plugins
-        clients_registry = clients.ClientsRegistry()
-        plugin_service_clients = clients_registry.get_service_clients()
-        for plugin in plugin_service_clients:
-            service_clients = plugin_service_clients[plugin]
-            # Each plugin returns a list of service client parameters
-            for service_client in service_clients:
-                # NOTE(andreaf) If a plugin cannot register, stop the
-                # registration process, log some details to help
-                # troubleshooting, and re-raise
-                try:
-                    self.register_service_client_module(**service_client)
-                except Exception:
-                    LOG.exception(
-                        'Failed to register service client from plugin %s '
-                        'with parameters %s' % (plugin, service_client))
-                    raise
-
-    def register_service_client_module(self, name, service_version,
-                                       module_path, client_names, **kwargs):
-        """Register a service client module
-
-        Initiates a client factory for the specified module, using this
-        class auth_provider, and accessible via a `name` attribute in the
-        service client.
-
-        :param name: Name used to access the client
-        :param service_version: Name of the service complete with version.
-            Used to track registered services. When a plugin implements it,
-            it can be used by other plugins to obtain their configuration.
-        :param module_path: Path to module that includes all service clients.
-            All service client classes must be exposed by a single module.
-            If they are separated in different modules, defining __all__
-            in the root module can help, similar to what is done by service
-            clients in tempest.
-        :param client_names: List or set of names of service client classes.
-        :param kwargs: Extra optional parameters to be passed to all clients.
-            ServiceClient provides defaults for region, dscv, ca_certs and
-            trace_requests.
-        :raise ServiceClientRegistrationException: if the provided name is
-            already in use or if service_version is already registered.
-        :raise ImportError: if module_path cannot be imported.
-        """
-        if hasattr(self, name):
-            using_name = getattr(self, name)
-            detailed_error = 'Module name already in use: %s' % using_name
-            raise exceptions.ServiceClientRegistrationException(
-                name=name, service_version=service_version,
-                module_path=module_path, client_names=client_names,
-                detailed_error=detailed_error)
-        if service_version in self.registered_services:
-            detailed_error = 'Service %s already registered.' % service_version
-            raise exceptions.ServiceClientRegistrationException(
-                name=name, service_version=service_version,
-                module_path=module_path, client_names=client_names,
-                detailed_error=detailed_error)
-        params = dict(region=self.region,
-                      disable_ssl_certificate_validation=self.dscv,
-                      ca_certs=self.ca_certs,
-                      trace_requests=self.trace_requests)
-        params.update(kwargs)
-        # Instantiate the client factory
-        _factory = ClientsFactory(module_path=module_path,
-                                  client_names=client_names,
-                                  auth_provider=self.auth_provider,
-                                  **params)
-        # Adds the client factory to the service_client
-        setattr(self, name, _factory)
-        # Add the name of the new service in self.SERVICES for discovery
-        self._registered_services.add(service_version)
-
-    @property
-    def registered_services(self):
-        # TODO(andreaf) Temporary set needed until all services are migrated
-        _non_migrated_services = tempest_modules() - set(
-            client_modules_by_service_name)
-        return self._registered_services | _non_migrated_services
-
-    def _setup_parameters(self, parameters):
-        """Setup default values for client parameters
-
-        Region by default is the region passed as an __init__ parameter.
-        Checks that no parameter for an unknown service is provided.
-        """
-        _parameters = {}
-        # Use region from __init__
-        if self.region:
-            _parameters['region'] = self.region
-        # Update defaults with specified parameters
-        _parameters.update(parameters)
-        # If any parameter is left, parameters for an unknown service were
-        # provided as input. Fail rather than ignore silently.
-        return _parameters
diff --git a/tempest/services/identity/v2/__init__.py b/tempest/services/identity/v2/__init__.py
index ac2a874..b7d3c74 100644
--- a/tempest/services/identity/v2/__init__.py
+++ b/tempest/services/identity/v2/__init__.py
@@ -13,12 +13,12 @@
 # the License.
 
 from tempest.lib.services.identity.v2.endpoints_client import EndpointsClient
+from tempest.lib.services.identity.v2.identity_client import IdentityClient
 from tempest.lib.services.identity.v2.roles_client import RolesClient
 from tempest.lib.services.identity.v2.services_client import ServicesClient
 from tempest.lib.services.identity.v2.tenants_client import TenantsClient
 from tempest.lib.services.identity.v2.token_client import TokenClient
 from tempest.lib.services.identity.v2.users_client import UsersClient
-from tempest.services.identity.v2.json.identity_client import IdentityClient
 
-__all__ = ['EndpointsClient', 'TokenClient', 'IdentityClient', 'RolesClient',
-           'ServicesClient', 'TenantsClient', 'UsersClient']
+__all__ = ['EndpointsClient', 'IdentityClient', 'RolesClient',
+           'ServicesClient', 'TenantsClient', 'TokenClient', 'UsersClient']
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
index 6ad8ef2..c77c78d 100644
--- a/tempest/services/identity/v3/__init__.py
+++ b/tempest/services/identity/v3/__init__.py
@@ -14,20 +14,20 @@
 
 from tempest.lib.services.identity.v3.endpoints_client import EndPointsClient
 from tempest.lib.services.identity.v3.policies_client import PoliciesClient
+from tempest.lib.services.identity.v3.projects_client import ProjectsClient
+from tempest.lib.services.identity.v3.regions_client import RegionsClient
+from tempest.lib.services.identity.v3.services_client import ServicesClient
 from tempest.lib.services.identity.v3.token_client import V3TokenClient
 from tempest.services.identity.v3.json.credentials_client import \
     CredentialsClient
 from tempest.services.identity.v3.json.domains_client import DomainsClient
 from tempest.services.identity.v3.json.groups_client import GroupsClient
 from tempest.services.identity.v3.json.identity_client import IdentityClient
-from tempest.services.identity.v3.json.projects_client import ProjectsClient
-from tempest.services.identity.v3.json.regions_client import RegionsClient
 from tempest.services.identity.v3.json.roles_client import RolesClient
-from tempest.services.identity.v3.json.services_client import ServicesClient
 from tempest.services.identity.v3.json.trusts_client import TrustsClient
 from tempest.services.identity.v3.json.users_clients import UsersClient
 
-__all__ = ['EndPointsClient', 'PoliciesClient', 'V3TokenClient',
+__all__ = ['EndPointsClient', 'PoliciesClient', 'ProjectsClient',
+           'RegionsClient', 'ServicesClient', 'V3TokenClient',
            'CredentialsClient', 'DomainsClient', 'GroupsClient',
-           'IdentityClient', 'ProjectsClient', 'RegionsClient', 'RolesClient',
-           'ServicesClient', 'TrustsClient', 'UsersClient', ]
+           'IdentityClient', 'RolesClient', 'TrustsClient', 'UsersClient', ]
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/services/identity/v3/json/credentials_client.py
index 6ab94d0..55eeee4 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/services/identity/v3/json/credentials_client.py
@@ -14,10 +14,11 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#credentials-v3
+http://developer.openstack.org/api-ref-identity-v3.html#credentials
 """
 
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.lib.common import rest_client
 
@@ -29,7 +30,7 @@
         """Creates a credential.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v3.html#createCredential
+                              api-ref-identity-v3.html#create-credential
         """
         post_body = json.dumps({'credential': kwargs})
         resp, body = self.post('credentials', post_body)
@@ -42,7 +43,7 @@
         """Updates a credential.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-identity-v3.html#updateCredential
+                              api-ref-identity-v3.html#update-credential
         """
         post_body = json.dumps({'credential': kwargs})
         resp, body = self.patch('credentials/%s' % credential_id, post_body)
@@ -52,22 +53,37 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_credential(self, credential_id):
-        """To GET Details of a credential."""
+        """To GET Details of a credential.
+
+        For API details, see http://developer.openstack.org/
+                             api-ref-identity-v3.html#show-credential-details
+        """
         resp, body = self.get('credentials/%s' % credential_id)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         body['credential']['blob'] = json.loads(body['credential']['blob'])
         return rest_client.ResponseBody(resp, body)
 
-    def list_credentials(self):
-        """Lists out all the available credentials."""
-        resp, body = self.get('credentials')
+    def list_credentials(self, **params):
+        """Lists out all the available credentials.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-credentials
+        """
+        url = 'credentials'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
     def delete_credential(self, credential_id):
-        """Deletes a credential."""
+        """Deletes a credential.
+
+        For API details, see http://developer.openstack.org/
+                             api-ref/identity/v3/#delete-credential
+        """
         resp, body = self.delete('credentials/%s' % credential_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/domains_client.py b/tempest/services/identity/v3/json/domains_client.py
index d129a0a..fe929a5 100644
--- a/tempest/services/identity/v3/json/domains_client.py
+++ b/tempest/services/identity/v3/json/domains_client.py
@@ -38,7 +38,7 @@
 
     def delete_domain(self, domain_id):
         """Deletes a domain."""
-        resp, body = self.delete('domains/%s' % str(domain_id))
+        resp, body = self.delete('domains/%s' % domain_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
diff --git a/tempest/services/identity/v3/json/groups_client.py b/tempest/services/identity/v3/json/groups_client.py
index 1a495f8..3674496 100644
--- a/tempest/services/identity/v3/json/groups_client.py
+++ b/tempest/services/identity/v3/json/groups_client.py
@@ -18,6 +18,7 @@
 """
 
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.lib.common import rest_client
 
@@ -44,9 +45,16 @@
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def list_groups(self):
-        """Lists the groups."""
-        resp, body = self.get('groups')
+    def list_groups(self, **params):
+        """Lists the groups.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-groups
+        """
+        url = 'groups'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
@@ -65,7 +73,7 @@
 
     def delete_group(self, group_id):
         """Delete a group."""
-        resp, body = self.delete('groups/%s' % str(group_id))
+        resp, body = self.delete('groups/%s' % group_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -76,9 +84,16 @@
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def list_group_users(self, group_id):
-        """List users in group."""
-        resp, body = self.get('groups/%s/users' % group_id)
+    def list_group_users(self, group_id, **params):
+        """List users in group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-users-in-group
+        """
+        url = 'groups/%s/users' % group_id
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/roles_client.py b/tempest/services/identity/v3/json/roles_client.py
index bdb0490..aab203f 100644
--- a/tempest/services/identity/v3/json/roles_client.py
+++ b/tempest/services/identity/v3/json/roles_client.py
@@ -34,7 +34,7 @@
 
     def show_role(self, role_id):
         """GET a Role."""
-        resp, body = self.get('roles/%s' % str(role_id))
+        resp, body = self.get('roles/%s' % role_id)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
@@ -53,14 +53,14 @@
                           api-ref-identity-v3.html#updateRole
         """
         post_body = json.dumps({'role': kwargs})
-        resp, body = self.patch('roles/%s' % str(role_id), post_body)
+        resp, body = self.patch('roles/%s' % role_id, post_body)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
     def delete_role(self, role_id):
         """Delete a role."""
-        resp, body = self.delete('roles/%s' % str(role_id))
+        resp, body = self.delete('roles/%s' % role_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
diff --git a/tempest/services/identity/v3/json/users_clients.py b/tempest/services/identity/v3/json/users_clients.py
index 73bd343..0dcdacd 100644
--- a/tempest/services/identity/v3/json/users_clients.py
+++ b/tempest/services/identity/v3/json/users_clients.py
@@ -21,56 +21,27 @@
 class UsersClient(rest_client.RestClient):
     api_version = "v3"
 
-    def create_user(self, user_name, password=None, project_id=None,
-                    email=None, domain_id='default', **kwargs):
-        """Creates a user."""
-        en = kwargs.get('enabled', True)
-        description = kwargs.get('description', None)
-        default_project_id = kwargs.get('default_project_id')
-        post_body = {
-            'project_id': project_id,
-            'default_project_id': default_project_id,
-            'description': description,
-            'domain_id': domain_id,
-            'email': email,
-            'enabled': en,
-            'name': user_name,
-            'password': password
-        }
-        post_body = json.dumps({'user': post_body})
+    def create_user(self, **kwargs):
+        """Creates a user.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#create-user
+        """
+        post_body = json.dumps({'user': kwargs})
         resp, body = self.post('users', post_body)
         self.expected_success(201, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def update_user(self, user_id, name, **kwargs):
+    def update_user(self, user_id, **kwargs):
         """Updates a user.
 
         Available params: see http://developer.openstack.org/
                               api-ref-identity-v3.html#updateUser
         """
-        body = self.show_user(user_id)['user']
-        email = kwargs.get('email', body['email'])
-        en = kwargs.get('enabled', body['enabled'])
-        project_id = kwargs.get('project_id', body['project_id'])
-        if 'default_project_id' in body.keys():
-            default_project_id = kwargs.get('default_project_id',
-                                            body['default_project_id'])
-        else:
-            default_project_id = kwargs.get('default_project_id')
-        description = kwargs.get('description', body['description'])
-        domain_id = kwargs.get('domain_id', body['domain_id'])
-        post_body = {
-            'name': name,
-            'email': email,
-            'enabled': en,
-            'project_id': project_id,
-            'default_project_id': default_project_id,
-            'id': user_id,
-            'domain_id': domain_id,
-            'description': description
-        }
-        post_body = json.dumps({'user': post_body})
+        if 'id' not in kwargs:
+            kwargs['id'] = user_id
+        post_body = json.dumps({'user': kwargs})
         resp, body = self.patch('users/%s' % user_id, post_body)
         self.expected_success(200, resp.status)
         body = json.loads(body)
@@ -87,15 +58,26 @@
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp)
 
-    def list_user_projects(self, user_id):
-        """Lists the projects on which a user has roles assigned."""
-        resp, body = self.get('users/%s/projects' % user_id)
+    def list_user_projects(self, user_id, **params):
+        """Lists the projects on which a user has roles assigned.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-projects-for-user
+        """
+        url = 'users/%s/projects' % user_id
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def list_users(self, params=None):
-        """Get the list of users."""
+    def list_users(self, **params):
+        """Get the list of users.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/identity/v3/#list-users
+        """
         url = 'users'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -117,9 +99,16 @@
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def list_user_groups(self, user_id):
-        """Lists groups which a user belongs to."""
-        resp, body = self.get('users/%s/groups' % user_id)
+    def list_user_groups(self, user_id, **params):
+        """Lists groups which a user belongs to.
+
+        Available params: see http://developer.openstack.org/
+            api-ref/identity/v3/#list-groups-to-which-a-user-belongs
+        """
+        url = 'users/%s/groups' % user_id
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 33dba6e..a7db30e 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -42,12 +42,6 @@
         self.expected_success(201, resp.status)
         return resp, body
 
-    def update_object(self, container, object_name, data):
-        """Upload data to replace current storage object."""
-        resp, body = self.create_object(container, object_name, data)
-        self.expected_success(201, resp.status)
-        return resp, body
-
     def delete_object(self, container, object_name, params=None):
         """Delete storage object."""
         url = "%s/%s" % (str(container), str(object_name))
@@ -237,37 +231,3 @@
         conn = httplib.HTTPConnection(parsed_url.netloc)
 
     return conn
-
-
-def put_object_connection(base_url, container, name, contents=None,
-                          chunk_size=65536, headers=None, query_string=None):
-    """Helper function to make connection to put object with httplib
-
-    :param base_url: base_url of an object client
-    :param container: container name that the object is in
-    :param name: object name to put
-    :param contents: a string or a file like object to read object data
-                     from; if None, a zero-byte put will be done
-    :param chunk_size: chunk size of data to write; it defaults to 65536;
-                       used only if the contents object has a 'read'
-                       method, eg. file-like objects, ignored otherwise
-    :param headers: additional headers to include in the request, if any
-    :param query_string: if set will be appended with '?' to generated path
-    """
-    parsed = urlparse.urlparse(base_url)
-
-    path = str(parsed.path) + "/"
-    path += "%s/%s" % (str(container), str(name))
-
-    conn = create_connection(parsed)
-
-    if query_string:
-        path += '?' + query_string
-    if headers:
-        headers = dict(headers)
-    else:
-        headers = {}
-
-    conn.request('PUT', path, contents, headers)
-
-    return conn
diff --git a/tempest/services/volume/base/admin/base_types_client.py b/tempest/services/volume/base/admin/base_types_client.py
index afca752..83870ae 100755
--- a/tempest/services/volume/base/admin/base_types_client.py
+++ b/tempest/services/volume/base/admin/base_types_client.py
@@ -62,13 +62,13 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def show_volume_type(self, volume_id):
+    def show_volume_type(self, volume_type_id):
         """Returns the details of a single volume_type.
 
         Available params: see http://developer.openstack.org/
                               api-ref-blockstorage-v2.html#showVolumeType
         """
-        url = "types/%s" % str(volume_id)
+        url = "types/%s" % volume_type_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -86,24 +86,24 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_volume_type(self, volume_id):
+    def delete_volume_type(self, volume_type_id):
         """Deletes the Specified Volume_type.
 
         Available params: see http://developer.openstack.org/
                               api-ref-blockstorage-v2.html#deleteVolumeType
         """
-        resp, body = self.delete("types/%s" % str(volume_id))
+        resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def list_volume_types_extra_specs(self, vol_type_id, **params):
+    def list_volume_types_extra_specs(self, volume_type_id, **params):
         """List all the volume_types extra specs created.
 
         TODO: Current api-site doesn't contain this API description.
         After fixing the api-site, we need to fix here also for putting
         the link to api-site.
         """
-        url = 'types/%s/extra_specs' % str(vol_type_id)
+        url = 'types/%s/extra_specs' % volume_type_id
         if params:
             url += '?%s' % urllib.urlencode(params)
 
@@ -112,40 +112,51 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def show_volume_type_extra_specs(self, vol_type_id, extra_specs_name):
+    def show_volume_type_extra_specs(self, volume_type_id, extra_specs_name):
         """Returns the details of a single volume_type extra spec."""
-        url = "types/%s/extra_specs/%s" % (str(vol_type_id),
-                                           str(extra_specs_name))
+        url = "types/%s/extra_specs/%s" % (volume_type_id, extra_specs_name)
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def create_volume_type_extra_specs(self, vol_type_id, extra_specs):
+    def create_volume_type_extra_specs(self, volume_type_id, extra_specs):
         """Creates a new Volume_type extra spec.
 
-        vol_type_id: Id of volume_type.
+        volume_type_id: Id of volume_type.
         extra_specs: A dictionary of values to be used as extra_specs.
         """
-        url = "types/%s/extra_specs" % str(vol_type_id)
+        url = "types/%s/extra_specs" % volume_type_id
         post_body = json.dumps({'extra_specs': extra_specs})
         resp, body = self.post(url, post_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_volume_type_extra_specs(self, vol_id, extra_spec_name):
+    def delete_volume_type_extra_specs(self, volume_type_id, extra_spec_name):
         """Deletes the Specified Volume_type extra spec."""
         resp, body = self.delete("types/%s/extra_specs/%s" % (
-            (str(vol_id)), str(extra_spec_name)))
+            volume_type_id, extra_spec_name))
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name,
+    def update_volume_type(self, volume_type_id, **kwargs):
+        """Updates volume type name, description, and/or is_public.
+
+        Available params: see http://developer.openstack.org/
+        api-ref-blockstorage-v2.html#updateVolumeType
+        """
+        put_body = json.dumps({'volume_type': kwargs})
+        resp, body = self.put('types/%s' % volume_type_id, put_body)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_volume_type_extra_specs(self, volume_type_id, extra_spec_name,
                                        extra_specs):
         """Update a volume_type extra spec.
 
-        vol_type_id: Id of volume_type.
+        volume_type_id: Id of volume_type.
         extra_spec_name: Name of the extra spec to be updated.
         extra_spec: A dictionary of with key as extra_spec_name and the
                      updated value.
@@ -153,81 +164,41 @@
                               api-ref-blockstorage-v2.html#
                               updateVolumeTypeExtraSpecs
         """
-        url = "types/%s/extra_specs/%s" % (str(vol_type_id),
-                                           str(extra_spec_name))
+        url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def show_encryption_type(self, vol_type_id):
+    def show_encryption_type(self, volume_type_id):
         """Get the volume encryption type for the specified volume type.
 
-        vol_type_id: Id of volume_type.
+        volume_type_id: Id of volume_type.
         """
-        url = "/types/%s/encryption" % str(vol_type_id)
+        url = "/types/%s/encryption" % volume_type_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def create_encryption_type(self, vol_type_id, **kwargs):
+    def create_encryption_type(self, volume_type_id, **kwargs):
         """Create encryption type.
 
         TODO: Current api-site doesn't contain this API description.
         After fixing the api-site, we need to fix here also for putting
         the link to api-site.
         """
-        url = "/types/%s/encryption" % str(vol_type_id)
+        url = "/types/%s/encryption" % volume_type_id
         post_body = json.dumps({'encryption': kwargs})
         resp, body = self.post(url, post_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_encryption_type(self, vol_type_id):
+    def delete_encryption_type(self, volume_type_id):
         """Delete the encryption type for the specified volume-type."""
         resp, body = self.delete(
-            "/types/%s/encryption/provider" % str(vol_type_id))
+            "/types/%s/encryption/provider" % volume_type_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
-
-    def add_type_access(self, volume_type_id, **kwargs):
-        """Adds volume type access for the given project.
-
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #createVolumeTypeAccessExt
-        """
-        post_body = json.dumps({'addProjectAccess': kwargs})
-        url = 'types/%s/action' % (volume_type_id)
-        resp, body = self.post(url, post_body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def remove_type_access(self, volume_type_id, **kwargs):
-        """Removes volume type access for the given project.
-
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #removeVolumeTypeAccessExt
-        """
-        post_body = json.dumps({'removeProjectAccess': kwargs})
-        url = 'types/%s/action' % (volume_type_id)
-        resp, body = self.post(url, post_body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def list_type_access(self, volume_type_id):
-        """Print access information about the given volume type.
-
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              listVolumeTypeAccessExt
-        """
-        url = 'types/%s/os-volume-type-access' % (volume_type_id)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        self.expected_success(200, resp.status)
-        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_backups_client.py b/tempest/services/volume/base/base_backups_client.py
index 63c5417..a57e628 100644
--- a/tempest/services/volume/base/base_backups_client.py
+++ b/tempest/services/volume/base/base_backups_client.py
@@ -51,13 +51,13 @@
 
     def delete_backup(self, backup_id):
         """Delete a backup of volume."""
-        resp, body = self.delete('backups/%s' % (str(backup_id)))
+        resp, body = self.delete('backups/%s' % backup_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
     def show_backup(self, backup_id):
         """Returns the details of a single backup."""
-        url = "backups/%s" % str(backup_id)
+        url = "backups/%s" % backup_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -116,14 +116,9 @@
                             self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
-    def wait_for_backup_deletion(self, backup_id):
-        """Waits for backup deletion"""
-        start_time = int(time.time())
-        while True:
-            try:
-                self.show_backup(backup_id)
-            except lib_exc.NotFound:
-                return
-            if int(time.time()) - start_time >= self.build_timeout:
-                raise exceptions.TimeoutException
-            time.sleep(self.build_interval)
+    def is_resource_deleted(self, id):
+        try:
+            self.show_backup(id)
+        except lib_exc.NotFound:
+            return True
+        return False
diff --git a/tempest/services/volume/base/base_qos_client.py b/tempest/services/volume/base/base_qos_client.py
index 2d9f02a..0ce76a7 100644
--- a/tempest/services/volume/base/base_qos_client.py
+++ b/tempest/services/volume/base/base_qos_client.py
@@ -12,11 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import time
-
 from oslo_serialization import jsonutils as json
 
-from tempest import exceptions
 from tempest.lib.common import rest_client
 from tempest.lib import exceptions as lib_exc
 
@@ -36,37 +33,6 @@
         """Returns the primary type of resource this client works with."""
         return 'qos'
 
-    def wait_for_qos_operations(self, qos_id, operation, args=None):
-        """Waits for a qos operations to be completed.
-
-        NOTE : operation value is required for  wait_for_qos_operations()
-        operation = 'qos-key' / 'disassociate' / 'disassociate-all'
-        args = keys[] when operation = 'qos-key'
-        args = volume-type-id disassociated when operation = 'disassociate'
-        args = None when operation = 'disassociate-all'
-        """
-        start_time = int(time.time())
-        while True:
-            if operation == 'qos-key-unset':
-                body = self.show_qos(qos_id)['qos_specs']
-                if not any(key in body['specs'] for key in args):
-                    return
-            elif operation == 'disassociate':
-                body = self.show_association_qos(qos_id)['qos_associations']
-                if not any(args in body[i]['id'] for i in range(0, len(body))):
-                    return
-            elif operation == 'disassociate-all':
-                body = self.show_association_qos(qos_id)['qos_associations']
-                if not body:
-                    return
-            else:
-                msg = (" operation value is either not defined or incorrect.")
-                raise lib_exc.UnprocessableEntity(msg)
-
-            if int(time.time()) - start_time >= self.build_timeout:
-                raise exceptions.TimeoutException
-            time.sleep(self.build_interval)
-
     def create_qos(self, **kwargs):
         """Create a QoS Specification.
 
@@ -82,7 +48,7 @@
     def delete_qos(self, qos_id, force=False):
         """Delete the specified QoS specification."""
         resp, body = self.delete(
-            "qos-specs/%s?force=%s" % (str(qos_id), force))
+            "qos-specs/%s?force=%s" % (qos_id, force))
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -96,7 +62,7 @@
 
     def show_qos(self, qos_id):
         """Get the specified QoS specification."""
-        url = "qos-specs/%s" % str(qos_id)
+        url = "qos-specs/%s" % qos_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -128,7 +94,7 @@
 
     def associate_qos(self, qos_id, vol_type_id):
         """Associate the specified QoS with specified volume-type."""
-        url = "qos-specs/%s/associate" % str(qos_id)
+        url = "qos-specs/%s/associate" % qos_id
         url += "?vol_type_id=%s" % vol_type_id
         resp, body = self.get(url)
         self.expected_success(202, resp.status)
@@ -136,7 +102,7 @@
 
     def show_association_qos(self, qos_id):
         """Get the association of the specified QoS specification."""
-        url = "qos-specs/%s/associations" % str(qos_id)
+        url = "qos-specs/%s/associations" % qos_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -144,7 +110,7 @@
 
     def disassociate_qos(self, qos_id, vol_type_id):
         """Disassociate the specified QoS with specified volume-type."""
-        url = "qos-specs/%s/disassociate" % str(qos_id)
+        url = "qos-specs/%s/disassociate" % qos_id
         url += "?vol_type_id=%s" % vol_type_id
         resp, body = self.get(url)
         self.expected_success(202, resp.status)
@@ -152,7 +118,7 @@
 
     def disassociate_all_qos(self, qos_id):
         """Disassociate the specified QoS with all associations."""
-        url = "qos-specs/%s/disassociate_all" % str(qos_id)
+        url = "qos-specs/%s/disassociate_all" % qos_id
         resp, body = self.get(url)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
index 7a8e12b..38a6dc7 100755
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -45,7 +45,7 @@
         Available params: see http://developer.openstack.org/
                               api-ref-blockstorage-v2.html#showSnapshot
         """
-        url = "snapshots/%s" % str(snapshot_id)
+        url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -81,7 +81,7 @@
         Available params: see http://developer.openstack.org/
                               api-ref-blockstorage-v2.html#deleteSnapshot
         """
-        resp, body = self.delete("snapshots/%s" % str(snapshot_id))
+        resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -112,7 +112,7 @@
         # Bug https://bugs.launchpad.net/openstack-api-site/+bug/1532645
 
         post_body = json.dumps({'os-update_snapshot_status': kwargs})
-        url = 'snapshots/%s/action' % str(snapshot_id)
+        url = 'snapshots/%s/action' % snapshot_id
         resp, body = self.post(url, post_body)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
@@ -120,7 +120,7 @@
     def create_snapshot_metadata(self, snapshot_id, metadata):
         """Create metadata for the snapshot."""
         put_body = json.dumps({'metadata': metadata})
-        url = "snapshots/%s/metadata" % str(snapshot_id)
+        url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.post(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -133,7 +133,7 @@
                               api-ref-blockstorage-v2.html#
                               showSnapshotMetadata
         """
-        url = "snapshots/%s/metadata" % str(snapshot_id)
+        url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -147,7 +147,7 @@
                               updateSnapshotMetadata
         """
         put_body = json.dumps(kwargs)
-        url = "snapshots/%s/metadata" % str(snapshot_id)
+        url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -160,7 +160,7 @@
         # link to api-site.
         # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1529064
         put_body = json.dumps(kwargs)
-        url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
+        url = "snapshots/%s/metadata/%s" % (snapshot_id, id)
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -168,7 +168,7 @@
 
     def delete_snapshot_metadata_item(self, snapshot_id, id):
         """Delete metadata item for the snapshot."""
-        url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
+        url = "snapshots/%s/metadata/%s" % (snapshot_id, id)
         resp, body = self.delete(url)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_volumes_client.py b/tempest/services/volume/base/base_volumes_client.py
index d694c53..308f818 100755
--- a/tempest/services/volume/base/base_volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -26,16 +26,6 @@
 
     create_resp = 200
 
-    def __init__(self, auth_provider, service, region,
-                 default_volume_size=1, **kwargs):
-        super(BaseVolumesClient, self).__init__(
-            auth_provider, service, region, **kwargs)
-        self.default_volume_size = default_volume_size
-
-    def get_attachment_from_volume(self, volume):
-        """Return the element 'attachment' from input volumes."""
-        return volume['attachments'][0]
-
     def _prepare_params(self, params):
         """Prepares params for use in get or _ext_get methods.
 
@@ -63,7 +53,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_pools(self, detail=False):
-        # List all the volumes pools (hosts)
+        """List all the volumes pools (hosts).
+
+        Output params: see http://developer.openstack.org/
+                           api-ref-blockstorage-v2.html#listPools
+        """
         url = 'scheduler-stats/get_pools'
         if detail:
             url += '?detail=True'
@@ -73,9 +67,22 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
+    def show_backend_capabilities(self, host):
+        """Shows capabilities for a storage back end.
+
+         Output params: see http://developer.openstack.org/
+                            api-ref-blockstorage-v2.html
+                            #showBackendCapabilities
+        """
+        url = 'capabilities/%s' % host
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
     def show_volume(self, volume_id):
         """Returns the details of a single volume."""
-        url = "volumes/%s" % str(volume_id)
+        url = "volumes/%s" % volume_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -87,8 +94,6 @@
         Available params: see http://developer.openstack.org/
                               api-ref-blockstorage-v2.html#createVolume
         """
-        if 'size' not in kwargs:
-            kwargs['size'] = self.default_volume_size
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
         body = json.loads(body)
@@ -109,7 +114,7 @@
 
     def delete_volume(self, volume_id):
         """Deletes the Specified Volume."""
-        resp, body = self.delete("volumes/%s" % str(volume_id))
+        resp, body = self.delete("volumes/%s" % volume_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -201,22 +206,6 @@
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def volume_begin_detaching(self, volume_id):
-        """Volume Begin Detaching."""
-        # ref cinder/api/contrib/volume_actions.py#L158
-        post_body = json.dumps({'os-begin_detaching': {}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def volume_roll_detaching(self, volume_id):
-        """Volume Roll Detaching."""
-        # cinder/api/contrib/volume_actions.py#L170
-        post_body = json.dumps({'os-roll_detaching': {}})
-        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
     def create_volume_transfer(self, **kwargs):
         """Create a volume transfer.
 
@@ -231,7 +220,7 @@
 
     def show_volume_transfer(self, transfer_id):
         """Returns the details of a volume transfer."""
-        url = "os-volume-transfer/%s" % str(transfer_id)
+        url = "os-volume-transfer/%s" % transfer_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -253,7 +242,7 @@
 
     def delete_volume_transfer(self, transfer_id):
         """Delete a volume transfer."""
-        resp, body = self.delete("os-volume-transfer/%s" % str(transfer_id))
+        resp, body = self.delete("os-volume-transfer/%s" % transfer_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -288,7 +277,7 @@
     def create_volume_metadata(self, volume_id, metadata):
         """Create metadata for the volume."""
         put_body = json.dumps({'metadata': metadata})
-        url = "volumes/%s/metadata" % str(volume_id)
+        url = "volumes/%s/metadata" % volume_id
         resp, body = self.post(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -296,7 +285,7 @@
 
     def show_volume_metadata(self, volume_id):
         """Get metadata of the volume."""
-        url = "volumes/%s/metadata" % str(volume_id)
+        url = "volumes/%s/metadata" % volume_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -305,7 +294,7 @@
     def update_volume_metadata(self, volume_id, metadata):
         """Update metadata for the volume."""
         put_body = json.dumps({'metadata': metadata})
-        url = "volumes/%s/metadata" % str(volume_id)
+        url = "volumes/%s/metadata" % volume_id
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -314,7 +303,7 @@
     def update_volume_metadata_item(self, volume_id, id, meta_item):
         """Update metadata item for the volume."""
         put_body = json.dumps({'meta': meta_item})
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
+        url = "volumes/%s/metadata/%s" % (volume_id, id)
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -322,7 +311,7 @@
 
     def delete_volume_metadata_item(self, volume_id, id):
         """Delete metadata item for the volume."""
-        url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
+        url = "volumes/%s/metadata/%s" % (volume_id, id)
         resp, body = self.delete(url)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/v1/__init__.py b/tempest/services/volume/v1/__init__.py
index 6bdb8c4..945d2f2 100644
--- a/tempest/services/volume/v1/__init__.py
+++ b/tempest/services/volume/v1/__init__.py
@@ -12,15 +12,14 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-from tempest.services.volume.v1.json.admin.hosts_client import HostsClient
-from tempest.services.volume.v1.json.admin.quotas_client import QuotasClient
-from tempest.services.volume.v1.json.admin.services_client import \
-    ServicesClient
-from tempest.services.volume.v1.json.admin.types_client import TypesClient
-from tempest.services.volume.v1.json.availability_zone_client import \
+from tempest.lib.services.volume.v1.availability_zone_client import \
     AvailabilityZoneClient
+from tempest.lib.services.volume.v1.extensions_client import ExtensionsClient
+from tempest.lib.services.volume.v1.hosts_client import HostsClient
+from tempest.lib.services.volume.v1.quotas_client import QuotasClient
+from tempest.lib.services.volume.v1.services_client import ServicesClient
+from tempest.services.volume.v1.json.admin.types_client import TypesClient
 from tempest.services.volume.v1.json.backups_client import BackupsClient
-from tempest.services.volume.v1.json.extensions_client import ExtensionsClient
 from tempest.services.volume.v1.json.qos_client import QosSpecsClient
 from tempest.services.volume.v1.json.snapshots_client import SnapshotsClient
 from tempest.services.volume.v1.json.volumes_client import VolumesClient
diff --git a/tempest/services/volume/v1/json/admin/quotas_client.py b/tempest/services/volume/v1/json/admin/quotas_client.py
deleted file mode 100644
index 27fc301..0000000
--- a/tempest/services/volume/v1/json/admin/quotas_client.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
-#
-#    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.services.volume.base.admin import base_quotas_client
-
-
-class QuotasClient(base_quotas_client.BaseQuotasClient):
-    """Client class to send CRUD Volume Type API V1 requests"""
diff --git a/tempest/services/volume/v2/__init__.py b/tempest/services/volume/v2/__init__.py
index c75b0e5..80f7a94 100644
--- a/tempest/services/volume/v2/__init__.py
+++ b/tempest/services/volume/v2/__init__.py
@@ -12,15 +12,14 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-from tempest.services.volume.v2.json.admin.hosts_client import HostsClient
-from tempest.services.volume.v2.json.admin.quotas_client import QuotasClient
-from tempest.services.volume.v2.json.admin.services_client import \
-    ServicesClient
-from tempest.services.volume.v2.json.admin.types_client import TypesClient
-from tempest.services.volume.v2.json.availability_zone_client import \
+from tempest.lib.services.volume.v2.availability_zone_client import \
     AvailabilityZoneClient
+from tempest.lib.services.volume.v2.extensions_client import ExtensionsClient
+from tempest.lib.services.volume.v2.hosts_client import HostsClient
+from tempest.lib.services.volume.v2.quotas_client import QuotasClient
+from tempest.lib.services.volume.v2.services_client import ServicesClient
+from tempest.services.volume.v2.json.admin.types_client import TypesClient
 from tempest.services.volume.v2.json.backups_client import BackupsClient
-from tempest.services.volume.v2.json.extensions_client import ExtensionsClient
 from tempest.services.volume.v2.json.qos_client import QosSpecsClient
 from tempest.services.volume.v2.json.snapshots_client import SnapshotsClient
 from tempest.services.volume.v2.json.volumes_client import VolumesClient
diff --git a/tempest/services/volume/v2/json/admin/quotas_client.py b/tempest/services/volume/v2/json/admin/quotas_client.py
deleted file mode 100644
index 11e0e22..0000000
--- a/tempest/services/volume/v2/json/admin/quotas_client.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2014 OpenStack Foundation
-# 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.services.volume.base.admin import base_quotas_client
-
-
-class QuotasClient(base_quotas_client.BaseQuotasClient):
-    """Client class to send CRUD Volume V2 API requests"""
-    api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/types_client.py b/tempest/services/volume/v2/json/admin/types_client.py
index ecf5131..f76e8dc 100644
--- a/tempest/services/volume/v2/json/admin/types_client.py
+++ b/tempest/services/volume/v2/json/admin/types_client.py
@@ -13,9 +13,51 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
 from tempest.services.volume.base.admin import base_types_client
 
 
 class TypesClient(base_types_client.BaseTypesClient):
     """Client class to send CRUD Volume V2 API requests"""
     api_version = "v2"
+
+    def add_type_access(self, volume_type_id, **kwargs):
+        """Adds volume type access for the given project.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html
+                              #createVolumeTypeAccessExt
+        """
+        post_body = json.dumps({'addProjectAccess': kwargs})
+        url = 'types/%s/action' % volume_type_id
+        resp, body = self.post(url, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def remove_type_access(self, volume_type_id, **kwargs):
+        """Removes volume type access for the given project.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html
+                              #removeVolumeTypeAccessExt
+        """
+        post_body = json.dumps({'removeProjectAccess': kwargs})
+        url = 'types/%s/action' % volume_type_id
+        resp, body = self.post(url, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_type_access(self, volume_type_id):
+        """Print access information about the given volume type.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#
+                              listVolumeTypeAccessExt
+        """
+        url = 'types/%s/os-volume-type-access' % volume_type_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 4f8c6bd..c9a4d38 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -16,8 +16,8 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import test_utils
 import tempest.stress.stressaction as stressaction
-import tempest.test
 
 CONF = config.CONF
 
@@ -52,8 +52,8 @@
     def check_port_ssh(self):
         def func():
             return self.tcp_connect_scan(self.floating['ip'], 22)
-        if not tempest.test.call_until_true(func, self.check_timeout,
-                                            self.check_interval):
+        if not test_utils.call_until_true(func, self.check_timeout,
+                                          self.check_interval):
             raise RuntimeError("Cannot connect to the ssh port.")
 
     def check_icmp_echo(self):
@@ -62,8 +62,8 @@
 
         def func():
             return self.ping_ip_address(self.floating['ip'])
-        if not tempest.test.call_until_true(func, self.check_timeout,
-                                            self.check_interval):
+        if not test_utils.call_until_true(func, self.check_timeout,
+                                          self.check_interval):
             raise RuntimeError("%s(%s): Cannot ping the machine.",
                                self.server_id, self.floating['ip'])
         self.logger.info("%s(%s): pong :)",
@@ -153,8 +153,8 @@
                         ['floating_ip'])
             return floating['instance_id'] is None
 
-        if not tempest.test.call_until_true(func, self.check_timeout,
-                                            self.check_interval):
+        if not test_utils.call_until_true(func, self.check_timeout,
+                                          self.check_interval):
             raise RuntimeError("IP disassociate timeout!")
 
     def run_core(self):
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index 847f342..e06c364 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -30,7 +30,7 @@
         name = data_utils.rand_name("volume")
         self.logger.info("creating volume: %s" % name)
         volume = self.manager.volumes_client.create_volume(
-            display_name=name)['volume']
+            display_name=name, size=CONF.volume.volume_size)['volume']
         self.manager.volumes_client.wait_for_volume_status(volume['id'],
                                                            'available')
         self.logger.info("created volume: %s" % volume['id'])
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 8bbbfc4..743cb11 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -16,8 +16,8 @@
 from tempest.common.utils.linux import remote_client
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import test_utils
 import tempest.stress.stressaction as stressaction
-import tempest.test
 
 CONF = config.CONF
 
@@ -85,7 +85,7 @@
         self.logger.info("creating volume: %s" % name)
         volumes_client = self.manager.volumes_client
         self.volume = volumes_client.create_volume(
-            display_name=name)['volume']
+            display_name=name, size=CONF.volume.volume_size)['volume']
         volumes_client.wait_for_volume_status(self.volume['id'],
                                               'available')
         self.logger.info("created volume: %s" % self.volume['id'])
@@ -105,8 +105,8 @@
                         ['floating_ip'])
             return floating['instance_id'] is None
 
-        if not tempest.test.call_until_true(func, CONF.compute.build_timeout,
-                                            CONF.compute.build_interval):
+        if not test_utils.call_until_true(func, CONF.compute.build_timeout,
+                                          CONF.compute.build_interval):
             raise RuntimeError("IP disassociate timeout!")
 
     def new_server_ops(self):
@@ -179,9 +179,9 @@
                 if self.part_line_re.match(part_line):
                     matching += 1
             return matching == num_match
-        if tempest.test.call_until_true(_part_state,
-                                        CONF.compute.build_timeout,
-                                        CONF.compute.build_interval):
+        if test_utils.call_until_true(_part_state,
+                                      CONF.compute.build_timeout,
+                                      CONF.compute.build_interval):
             return
         else:
             raise RuntimeError("Unexpected partitions: %s",
diff --git a/tempest/stress/actions/volume_create_delete.py b/tempest/stress/actions/volume_create_delete.py
index 3986748..66971ea 100644
--- a/tempest/stress/actions/volume_create_delete.py
+++ b/tempest/stress/actions/volume_create_delete.py
@@ -11,8 +11,11 @@
 #    limitations under the License.
 
 from tempest.common.utils import data_utils
+from tempest import config
 import tempest.stress.stressaction as stressaction
 
+CONF = config.CONF
+
 
 class VolumeCreateDeleteTest(stressaction.StressAction):
 
@@ -20,7 +23,8 @@
         name = data_utils.rand_name("volume")
         self.logger.info("creating %s" % name)
         volumes_client = self.manager.volumes_client
-        volume = volumes_client.create_volume(display_name=name)['volume']
+        volume = volumes_client.create_volume(
+            display_name=name, size=CONF.volume.volume_size)['volume']
         vol_id = volume['id']
         volumes_client.wait_for_volume_status(vol_id, 'available')
         self.logger.info("created %s" % volume['id'])
diff --git a/tempest/test.py b/tempest/test.py
index 97ab25c..609f1f6 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -18,8 +18,8 @@
 import os
 import re
 import sys
-import time
 
+import debtcollector.moves
 import fixtures
 from oslo_log import log as logging
 from oslo_serialization import jsonutils as json
@@ -38,6 +38,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
@@ -866,22 +867,6 @@
     return klass
 
 
-def call_until_true(func, duration, sleep_for):
-    """Call the given function until it returns True (and return True)
-
-    or until the specified duration (in seconds) elapses (and return False).
-
-    :param func: A zero argument callable that returns True on success.
-    :param duration: The number of seconds for which to attempt a
-        successful call of the function.
-    :param sleep_for: The number of seconds to sleep after an unsuccessful
-                      invocation of the function.
-    """
-    now = time.time()
-    timeout = now + duration
-    while now < timeout:
-        if func():
-            return True
-        time.sleep(sleep_for)
-        now = time.time()
-    return False
+call_until_true = debtcollector.moves.moved_function(
+    test_utils.call_until_true, 'call_until_true', __name__,
+    version='Newton', removal_version='Ocata')
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index cfb0c7f..eb50126 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -88,7 +88,7 @@
             >>>     'client_names': ['API1Client', 'API2Client'],
             >>>  }
             >>>  params.update(myservice_config)
-            >>> return [params]
+            >>>  return [params]
 
             >>>  # Example implementation with two service clients
             >>>  foo1_config = config.service_client_config('foo')
@@ -107,7 +107,7 @@
             >>>     'client_names': ['API1Client', 'API2Client'],
             >>>  }
             >>>  params_foo2.update(foo2_config)
-            >>> return [params_foo1, params_foo2]
+            >>>  return [params_foo1, params_foo2]
         """
         return []
 
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 031bf4d..2844371 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -45,6 +45,7 @@
         init_cmd = init.TempestInit(None, None)
         local_sample_conf_file = os.path.join(etc_dir_path,
                                               'tempest.conf.sample')
+
         # Verify no sample config file exist
         self.assertFalse(os.path.isfile(local_sample_conf_file))
         init_cmd.generate_sample_config(local_dir.path)
@@ -53,6 +54,52 @@
         self.assertTrue(os.path.isfile(local_sample_conf_file))
         self.assertGreater(os.path.getsize(local_sample_conf_file), 0)
 
+    def test_update_local_conf(self):
+        local_dir = self.useFixture(fixtures.TempDir())
+        etc_dir_path = os.path.join(local_dir.path, 'etc/')
+        os.mkdir(etc_dir_path)
+        lock_dir = os.path.join(local_dir.path, 'tempest_lock')
+        config_path = os.path.join(etc_dir_path, 'tempest.conf')
+        log_dir = os.path.join(local_dir.path, 'logs')
+
+        init_cmd = init.TempestInit(None, None)
+
+        # Generate the config file
+        init_cmd.generate_sample_config(local_dir.path)
+
+        # Create a conf file with populated values
+        config_parser_pre = init_cmd.get_configparser(config_path)
+        with open(config_path, 'w+') as conf_file:
+            # create the same section init will check for and add values to
+            config_parser_pre.add_section('oslo_concurrency')
+            config_parser_pre.set('oslo_concurrency', 'TEST', local_dir.path)
+            # create a new section
+            config_parser_pre.add_section('TEST')
+            config_parser_pre.set('TEST', 'foo', "bar")
+            config_parser_pre.write(conf_file)
+
+        # Update the config file the same way tempest init does
+        init_cmd.update_local_conf(config_path, lock_dir, log_dir)
+
+        # parse the new config file to verify it
+        config_parser_post = init_cmd.get_configparser(config_path)
+
+        # check that our value in oslo_concurrency wasn't overwritten
+        self.assertTrue(config_parser_post.has_section('oslo_concurrency'))
+        self.assertEqual(config_parser_post.get('oslo_concurrency', 'TEST'),
+                         local_dir.path)
+        # check that the lock directory was set correctly
+        self.assertEqual(config_parser_post.get('oslo_concurrency',
+                                                'lock_path'), lock_dir)
+
+        # check that our new section still exists and wasn't modified
+        self.assertTrue(config_parser_post.has_section('TEST'))
+        self.assertEqual(config_parser_post.get('TEST', 'foo'), 'bar')
+
+        # check that the DEFAULT values are correct
+        # NOTE(auggy): has_section ignores DEFAULT
+        self.assertEqual(config_parser_post.get('DEFAULT', 'log_dir'), log_dir)
+
     def test_create_working_dir_with_existing_local_dir_non_empty(self):
         fake_local_dir = self.useFixture(fixtures.TempDir())
         fake_local_conf_dir = self.useFixture(fixtures.TempDir())
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 70cbf87..00b4542 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -188,34 +188,54 @@
                                            False, True)
 
     @mock.patch('tempest.lib.common.http.ClosingHttp.request')
-    def test_verify_cinder_api_versions_no_v2(self, mock_request):
+    def test_verify_cinder_api_versions_no_v3(self, mock_request):
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, '_get_unversioned_endpoint',
             return_value='http://fake_endpoint:5000'))
-        fake_resp = {'versions': [{'id': 'v1.0'}]}
+        fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v2.0'}]}
         fake_resp = json.dumps(fake_resp)
         mock_request.return_value = (None, fake_resp)
         fake_os = mock.MagicMock()
         with mock.patch.object(verify_tempest_config,
                                'print_and_or_update') as print_mock:
             verify_tempest_config.verify_cinder_api_versions(fake_os, True)
-        print_mock.assert_called_once_with('api_v2', 'volume-feature-enabled',
-                                           False, True)
+        print_mock.assert_not_called()
+
+    @mock.patch('tempest.lib.common.http.ClosingHttp.request')
+    def test_verify_cinder_api_versions_no_v2(self, mock_request):
+        self.useFixture(mockpatch.PatchObject(
+            verify_tempest_config, '_get_unversioned_endpoint',
+            return_value='http://fake_endpoint:5000'))
+        fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v3.0'}]}
+        fake_resp = json.dumps(fake_resp)
+        mock_request.return_value = (None, fake_resp)
+        fake_os = mock.MagicMock()
+        with mock.patch.object(verify_tempest_config,
+                               'print_and_or_update') as print_mock:
+            verify_tempest_config.verify_cinder_api_versions(fake_os, True)
+        print_mock.assert_any_call('api_v2', 'volume-feature-enabled',
+                                   False, True)
+        print_mock.assert_any_call('api_v3', 'volume-feature-enabled',
+                                   True, True)
+        self.assertEqual(2, print_mock.call_count)
 
     @mock.patch('tempest.lib.common.http.ClosingHttp.request')
     def test_verify_cinder_api_versions_no_v1(self, mock_request):
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, '_get_unversioned_endpoint',
             return_value='http://fake_endpoint:5000'))
-        fake_resp = {'versions': [{'id': 'v2.0'}]}
+        fake_resp = {'versions': [{'id': 'v2.0'}, {'id': 'v3.0'}]}
         fake_resp = json.dumps(fake_resp)
         mock_request.return_value = (None, fake_resp)
         fake_os = mock.MagicMock()
         with mock.patch.object(verify_tempest_config,
                                'print_and_or_update') as print_mock:
             verify_tempest_config.verify_cinder_api_versions(fake_os, True)
-        print_mock.assert_called_once_with('api_v1', 'volume-feature-enabled',
-                                           False, True)
+        print_mock.assert_any_call('api_v1', 'volume-feature-enabled',
+                                   False, True)
+        print_mock.assert_any_call('api_v3', 'volume-feature-enabled',
+                                   True, True)
+        self.assertEqual(2, print_mock.call_count)
 
     def test_verify_glance_version_no_v2_with_v1_1(self):
         def fake_get_versions():
diff --git a/tempest/tests/cmd/test_workspace.py b/tempest/tests/cmd/test_workspace.py
index 2639d93..6ca4d42 100644
--- a/tempest/tests/cmd/test_workspace.py
+++ b/tempest/tests/cmd/test_workspace.py
@@ -17,7 +17,7 @@
 import subprocess
 import tempfile
 
-from tempest.cmd.workspace import WorkspaceManager
+from tempest.cmd import workspace
 from tempest.lib.common.utils import data_utils
 from tempest.tests import base
 
@@ -31,7 +31,8 @@
         store_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, store_dir, ignore_errors=True)
         self.store_file = os.path.join(store_dir, 'workspace.yaml')
-        self.workspace_manager = WorkspaceManager(path=self.store_file)
+        self.workspace_manager = workspace.WorkspaceManager(
+            path=self.store_file)
         self.workspace_manager.register_new_workspace(self.name, self.path)
 
 
@@ -92,7 +93,8 @@
         store_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, store_dir, ignore_errors=True)
         self.store_file = os.path.join(store_dir, 'workspace.yaml')
-        self.workspace_manager = WorkspaceManager(path=self.store_file)
+        self.workspace_manager = workspace.WorkspaceManager(
+            path=self.store_file)
         self.workspace_manager.register_new_workspace(self.name, self.path)
 
     def test_workspace_manager_get(self):
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index b7cc05d..8c74d9c 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -22,18 +22,18 @@
 from tempest import exceptions
 from tempest.lib.common import rest_client
 from tempest.lib import exceptions as lib_exc
+from tempest.lib.services.identity.v2 import identity_client as v2_iden_client
 from tempest.lib.services.identity.v2 import roles_client as v2_roles_client
 from tempest.lib.services.identity.v2 import tenants_client as \
     v2_tenants_client
 from tempest.lib.services.identity.v2 import token_client as v2_token_client
 from tempest.lib.services.identity.v2 import users_client as v2_users_client
+from tempest.lib.services.identity.v3 import projects_client as \
+    v3_projects_client
 from tempest.lib.services.identity.v3 import token_client as v3_token_client
 from tempest.lib.services.network import routers_client
-from tempest.services.identity.v2.json import identity_client as v2_iden_client
 from tempest.services.identity.v3.json import domains_client
 from tempest.services.identity.v3.json import identity_client as v3_iden_client
-from tempest.services.identity.v3.json import projects_client as \
-    v3_projects_client
 from tempest.services.identity.v3.json import roles_client as v3_roles_client
 from tempest.services.identity.v3.json import users_clients as v3_users_client
 from tempest.tests import base
diff --git a/tempest/tests/lib/common/utils/test_data_utils.py b/tempest/tests/lib/common/utils/test_data_utils.py
index 399c4af..94a4847 100644
--- a/tempest/tests/lib/common/utils/test_data_utils.py
+++ b/tempest/tests/lib/common/utils/test_data_utils.py
@@ -59,7 +59,7 @@
     def test_rand_password(self):
         actual = data_utils.rand_password()
         self.assertIsInstance(actual, str)
-        self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{15,}")
+        self.assertRegex(actual, "[A-Za-z0-9~!@#%^&*_=+]{15,}")
         actual2 = data_utils.rand_password()
         self.assertNotEqual(actual, actual2)
 
@@ -67,7 +67,7 @@
         actual = data_utils.rand_password(8)
         self.assertIsInstance(actual, str)
         self.assertEqual(len(actual), 8)
-        self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{8}")
+        self.assertRegex(actual, "[A-Za-z0-9~!@#%^&*_=+]{8}")
         actual2 = data_utils.rand_password(8)
         self.assertNotEqual(actual, actual2)
 
@@ -75,7 +75,7 @@
         actual = data_utils.rand_password(2)
         self.assertIsInstance(actual, str)
         self.assertEqual(len(actual), 3)
-        self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{3}")
+        self.assertRegex(actual, "[A-Za-z0-9~!@#%^&*_=+]{3}")
         actual2 = data_utils.rand_password(2)
         self.assertNotEqual(actual, actual2)
 
diff --git a/tempest/tests/lib/common/utils/test_test_utils.py b/tempest/tests/lib/common/utils/test_test_utils.py
index 919e219..29c5684 100644
--- a/tempest/tests/lib/common/utils/test_test_utils.py
+++ b/tempest/tests/lib/common/utils/test_test_utils.py
@@ -17,6 +17,7 @@
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 from tempest.tests import base
+from tempest.tests import utils
 
 
 class TestTestUtils(base.TestCase):
@@ -76,3 +77,27 @@
         self.assertEqual(
             42, test_utils.call_and_ignore_notfound_exc(m, *args, **kwargs))
         m.assert_called_once_with(*args, **kwargs)
+
+    @mock.patch('time.sleep')
+    @mock.patch('time.time')
+    def test_call_until_true_when_f_never_returns_true(self, m_time, m_sleep):
+        timeout = 42  # The value doesn't matter as we mock time.time()
+        sleep = 60  # The value doesn't matter as we mock time.sleep()
+        m_time.side_effect = utils.generate_timeout_series(timeout)
+        self.assertEqual(
+            False, test_utils.call_until_true(lambda: False, timeout, sleep)
+        )
+        m_sleep.call_args_list = [mock.call(sleep)] * 2
+        m_time.call_args_list = [mock.call()] * 2
+
+    @mock.patch('time.sleep')
+    @mock.patch('time.time')
+    def test_call_until_true_when_f_returns_true(self, m_time, m_sleep):
+        timeout = 42  # The value doesn't matter as we mock time.time()
+        sleep = 60  # The value doesn't matter as we mock time.sleep()
+        m_time.return_value = 0
+        self.assertEqual(
+            True, test_utils.call_until_true(lambda: True, timeout, sleep)
+        )
+        self.assertEqual(0, m_sleep.call_count)
+        self.assertEqual(1, m_time.call_count)
diff --git a/tempest/tests/lib/services/identity/v2/test_identity_client.py b/tempest/tests/lib/services/identity/v2/test_identity_client.py
new file mode 100644
index 0000000..96d50d7
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v2/test_identity_client.py
@@ -0,0 +1,175 @@
+# Copyright 2016 NEC Corporation.  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.lib.services.identity.v2 import identity_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestIdentityClient(base.BaseServiceTest):
+    FAKE_TOKEN = {
+        "tokens": {
+            "id": "cbc36478b0bd8e67e89",
+            "name": "FakeToken",
+            "type": "token",
+        }
+    }
+
+    FAKE_API_INFO = {
+        "name": "API_info",
+        "type": "API",
+        "description": "test_description"
+    }
+
+    FAKE_LIST_EXTENSIONS = {
+        "extensions": {
+            "values": [
+                {
+                    "updated": "2013-07-07T12:00:0-00:00",
+                    "name": "OpenStack S3 API",
+                    "links": [
+                        {
+                            "href": "https://github.com/openstack/" +
+                                    "identity-api",
+                            "type": "text/html",
+                            "rel": "describedby"
+                        }
+                    ],
+                    "namespace": "http://docs.openstack.org/identity/" +
+                                 "api/ext/s3tokens/v1.0",
+                    "alias": "s3tokens",
+                    "description": "OpenStack S3 API."
+                },
+                {
+                    "updated": "2013-12-17T12:00:0-00:00",
+                    "name": "OpenStack Federation APIs",
+                    "links": [
+                        {
+                            "href": "https://github.com/openstack/" +
+                                    "identity-api",
+                            "type": "text/html",
+                            "rel": "describedby"
+                        }
+                    ],
+                    "namespace": "http://docs.openstack.org/identity/" +
+                                 "api/ext/OS-FEDERATION/v1.0",
+                    "alias": "OS-FEDERATION",
+                    "description": "OpenStack Identity Providers Mechanism."
+                },
+                {
+                    "updated": "2014-01-20T12:00:0-00:00",
+                    "name": "OpenStack Simple Certificate API",
+                    "links": [
+                        {
+                            "href": "https://github.com/openstack/" +
+                                    "identity-api",
+                            "type": "text/html",
+                            "rel": "describedby"
+                        }
+                    ],
+                    "namespace": "http://docs.openstack.org/identity/api/" +
+                                 "ext/OS-SIMPLE-CERT/v1.0",
+                    "alias": "OS-SIMPLE-CERT",
+                    "description": "OpenStack simple certificate extension"
+                },
+                {
+                    "updated": "2013-07-07T12:00:0-00:00",
+                    "name": "OpenStack OAUTH1 API",
+                    "links": [
+                        {
+                            "href": "https://github.com/openstack/" +
+                                    "identity-api",
+                            "type": "text/html",
+                            "rel": "describedby"
+                        }
+                    ],
+                    "namespace": "http://docs.openstack.org/identity/" +
+                                 "api/ext/OS-OAUTH1/v1.0",
+                    "alias": "OS-OAUTH1",
+                    "description": "OpenStack OAuth Delegated Auth Mechanism."
+                },
+                {
+                    "updated": "2013-07-07T12:00:0-00:00",
+                    "name": "OpenStack EC2 API",
+                    "links": [
+                        {
+                            "href": "https://github.com/openstack/" +
+                                    "identity-api",
+                            "type": "text/html",
+                            "rel": "describedby"
+                        }
+                    ],
+                    "namespace": "http://docs.openstack.org/identity/api/" +
+                                 "ext/OS-EC2/v1.0",
+                    "alias": "OS-EC2",
+                    "description": "OpenStack EC2 Credentials backend."
+                }
+            ]
+        }
+    }
+
+    def setUp(self):
+        super(TestIdentityClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = identity_client.IdentityClient(fake_auth,
+                                                     'identity',
+                                                     'regionOne')
+
+    def _test_show_api_description(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_api_description,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_API_INFO,
+            bytes_body)
+
+    def _test_list_extensions(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_extensions,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_EXTENSIONS,
+            bytes_body)
+
+    def _test_show_token(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_token,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_TOKEN,
+            bytes_body,
+            token_id="cbc36478b0bd8e67e89")
+
+    def test_show_api_description_with_str_body(self):
+        self._test_show_api_description()
+
+    def test_show_api_description_with_bytes_body(self):
+        self._test_show_api_description(bytes_body=True)
+
+    def test_show_list_extensions_with_str_body(self):
+        self._test_list_extensions()
+
+    def test_show_list_extensions_with_bytes_body(self):
+        self._test_list_extensions(bytes_body=True)
+
+    def test_show_token_with_str_body(self):
+        self._test_show_token()
+
+    def test_show_token_with_bytes_body(self):
+        self._test_show_token(bytes_body=True)
+
+    def test_delete_token(self):
+        self.check_service_client_function(
+            self.client.delete_token,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            token_id="cbc36478b0bd8e67e89",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_projects_client.py b/tempest/tests/lib/services/identity/v3/test_projects_client.py
new file mode 100644
index 0000000..6ffbcde
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_projects_client.py
@@ -0,0 +1,178 @@
+# Copyright 2016 Red Hat, 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.
+
+from tempest.lib.services.identity.v3 import projects_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestProjectsClient(base.BaseServiceTest):
+    FAKE_CREATE_PROJECT = {
+        "project": {
+            "description": "My new project",
+            "domain_id": "default",
+            "enabled": True,
+            "is_domain": False,
+            "name": "myNewProject"
+        }
+    }
+
+    FAKE_PROJECT_INFO = {
+        "project": {
+            "is_domain": False,
+            "description": None,
+            "domain_id": "default",
+            "enabled": True,
+            "id": "0c4e939acacf4376bdcd1129f1a054ad",
+            "links": {
+                "self": "http://example.com/identity/v3/projects/0c4e" +
+                        "939acacf4376bdcd1129f1a054ad"
+            },
+            "name": "admin",
+            "parent_id": "default"
+        }
+    }
+
+    FAKE_LIST_PROJECTS = {
+        "links": {
+            "next": None,
+            "previous": None,
+            "self": "http://example.com/identity/v3/projects"
+        },
+        "projects": [
+            {
+                "is_domain": False,
+                "description": None,
+                "domain_id": "default",
+                "enabled": True,
+                "id": "0c4e939acacf4376bdcd1129f1a054ad",
+                "links": {
+                    "self": "http://example.com/identity/v3/projects" +
+                            "/0c4e939acacf4376bdcd1129f1a054ad"
+                },
+                "name": "admin",
+                "parent_id": None
+            },
+            {
+                "is_domain": False,
+                "description": None,
+                "domain_id": "default",
+                "enabled": True,
+                "id": "0cbd49cbf76d405d9c86562e1d579bd3",
+                "links": {
+                    "self": "http://example.com/identity/v3/projects" +
+                            "/0cbd49cbf76d405d9c86562e1d579bd3"
+                },
+                "name": "demo",
+                "parent_id": None
+            },
+            {
+                "is_domain": False,
+                "description": None,
+                "domain_id": "default",
+                "enabled": True,
+                "id": "2db68fed84324f29bb73130c6c2094fb",
+                "links": {
+                    "self": "http://example.com/identity/v3/projects" +
+                            "/2db68fed84324f29bb73130c6c2094fb"
+                },
+                "name": "swifttenanttest2",
+                "parent_id": None
+            },
+            {
+                "is_domain": False,
+                "description": None,
+                "domain_id": "default",
+                "enabled": True,
+                "id": "3d594eb0f04741069dbbb521635b21c7",
+                "links": {
+                    "self": "http://example.com/identity/v3/projects" +
+                            "/3d594eb0f04741069dbbb521635b21c7"
+                },
+                "name": "service",
+                "parent_id": None
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestProjectsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = projects_client.ProjectsClient(fake_auth,
+                                                     'identity',
+                                                     'regionOne')
+
+    def _test_create_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_project,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_PROJECT,
+            bytes_body,
+            name=self.FAKE_CREATE_PROJECT["project"]["name"],
+            status=201)
+
+    def _test_show_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_project,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_PROJECT_INFO,
+            bytes_body,
+            project_id="0c4e939acacf4376bdcd1129f1a054ad")
+
+    def _test_list_projects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_projects,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_PROJECTS,
+            bytes_body)
+
+    def _test_update_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_project,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_PROJECT_INFO,
+            bytes_body,
+            project_id="0c4e939acacf4376bdcd1129f1a054ad")
+
+    def test_create_project_with_str_body(self):
+        self._test_create_project()
+
+    def test_create_project_with_bytes_body(self):
+        self._test_create_project(bytes_body=True)
+
+    def test_show_project_with_str_body(self):
+        self._test_show_project()
+
+    def test_show_project_with_bytes_body(self):
+        self._test_show_project(bytes_body=True)
+
+    def test_list_projects_with_str_body(self):
+        self._test_list_projects()
+
+    def test_list_projects_with_bytes_body(self):
+        self._test_list_projects(bytes_body=True)
+
+    def test_update_project_with_str_body(self):
+        self._test_update_project()
+
+    def test_update_project_with_bytes_body(self):
+        self._test_update_project(bytes_body=True)
+
+    def test_delete_project(self):
+        self.check_service_client_function(
+            self.client.delete_project,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            project_id="0c4e939acacf4376bdcd1129f1a054ad",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_regions_client.py b/tempest/tests/lib/services/identity/v3/test_regions_client.py
new file mode 100644
index 0000000..a2cb86f
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_regions_client.py
@@ -0,0 +1,125 @@
+# Copyright 2016 Red Hat, 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.
+
+from tempest.lib.services.identity.v3 import regions_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestRegionsClient(base.BaseServiceTest):
+    FAKE_CREATE_REGION = {
+        "region": {
+            "description": "My subregion",
+            "id": "RegionOneSubRegion",
+            "parent_region_id": "RegionOne"
+            }
+        }
+
+    FAKE_REGION_INFO = {
+        "region": {
+            "description": "My subregion 3",
+            "id": "RegionThree",
+            "links": {
+                "self": "http://example.com/identity/v3/regions/RegionThree"
+                },
+            "parent_region_id": "RegionOne"
+            }
+        }
+
+    FAKE_LIST_REGIONS = {
+        "links": {
+            "next": None,
+            "previous": None,
+            "self": "http://example.com/identity/v3/regions"
+            },
+        "regions": [
+            {
+                "description": "",
+                "id": "RegionOne",
+                "links": {
+                    "self": "http://example.com/identity/v3/regions/RegionOne"
+                    },
+                "parent_region_id": None
+                }
+            ]
+        }
+
+    def setUp(self):
+        super(TestRegionsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = regions_client.RegionsClient(fake_auth, 'identity',
+                                                   'regionOne')
+
+    def _test_create_region(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_region,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_REGION,
+            bytes_body,
+            status=201)
+
+    def _test_show_region(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_region,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_REGION_INFO,
+            bytes_body,
+            region_id="RegionThree")
+
+    def _test_list_regions(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_regions,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_REGIONS,
+            bytes_body)
+
+    def _test_update_region(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_region,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_REGION_INFO,
+            bytes_body,
+            region_id="RegionThree")
+
+    def test_create_region_with_str_body(self):
+        self._test_create_region()
+
+    def test_create_region_with_bytes_body(self):
+        self._test_create_region(bytes_body=True)
+
+    def test_show_region_with_str_body(self):
+        self._test_show_region()
+
+    def test_show_region_with_bytes_body(self):
+        self._test_show_region(bytes_body=True)
+
+    def test_list_regions_with_str_body(self):
+        self._test_list_regions()
+
+    def test_list_regions_with_bytes_body(self):
+        self._test_list_regions(bytes_body=True)
+
+    def test_update_region_with_str_body(self):
+        self._test_update_region()
+
+    def test_update_region_with_bytes_body(self):
+        self._test_update_region(bytes_body=True)
+
+    def test_delete_region(self):
+        self.check_service_client_function(
+            self.client.delete_region,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            region_id="RegionThree",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_services_client.py b/tempest/tests/lib/services/identity/v3/test_services_client.py
new file mode 100644
index 0000000..f87fcce
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_services_client.py
@@ -0,0 +1,149 @@
+# Copyright 2016 Red Hat, 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.
+
+from tempest.lib.services.identity.v3 import services_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestServicesClient(base.BaseServiceTest):
+    FAKE_CREATE_SERVICE = {
+        "service": {
+            "type": "compute",
+            "name": "compute2",
+            "description": "Compute service 2"
+            }
+        }
+
+    FAKE_SERVICE_INFO = {
+        "service": {
+            "description": "Keystone Identity Service",
+            "enabled": True,
+            "id": "686766",
+            "links": {
+                "self": "http://example.com/identity/v3/services/686766"
+                },
+            "name": "keystone",
+            "type": "identity"
+            }
+        }
+
+    FAKE_LIST_SERVICES = {
+        "links": {
+            "next": None,
+            "previous": None,
+            "self": "http://example.com/identity/v3/services"
+            },
+        "services": [
+            {
+                "description": "Nova Compute Service",
+                "enabled": True,
+                "id": "1999c3",
+                "links": {
+                    "self": "http://example.com/identity/v3/services/1999c3"
+                    },
+                "name": "nova",
+                "type": "compute"
+                },
+            {
+                "description": "Cinder Volume Service V2",
+                "enabled": True,
+                "id": "392166",
+                "links": {
+                    "self": "http://example.com/identity/v3/services/392166"
+                    },
+                "name": "cinderv2",
+                "type": "volumev2"
+                },
+            {
+                "description": "Neutron Service",
+                "enabled": True,
+                "id": "4fe41a",
+                "links": {
+                    "self": "http://example.com/identity/v3/services/4fe41a"
+                    },
+                "name": "neutron",
+                "type": "network"
+                }
+        ]
+    }
+
+    def setUp(self):
+        super(TestServicesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = services_client.ServicesClient(fake_auth, 'identity',
+                                                     'regionOne')
+
+    def _test_create_service(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_service,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SERVICE,
+            bytes_body,
+            status=201)
+
+    def _test_show_service(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_service,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_SERVICE_INFO,
+            bytes_body,
+            service_id="686766")
+
+    def _test_list_services(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_services,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_SERVICES,
+            bytes_body)
+
+    def _test_update_service(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_service,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_SERVICE_INFO,
+            bytes_body,
+            service_id="686766")
+
+    def test_create_service_with_str_body(self):
+        self._test_create_service()
+
+    def test_create_service_with_bytes_body(self):
+        self._test_create_service(bytes_body=True)
+
+    def test_show_service_with_str_body(self):
+        self._test_show_service()
+
+    def test_show_service_with_bytes_body(self):
+        self._test_show_service(bytes_body=True)
+
+    def test_list_services_with_str_body(self):
+        self._test_list_services()
+
+    def test_list_services_with_bytes_body(self):
+        self._test_list_services(bytes_body=True)
+
+    def test_update_service_with_str_body(self):
+        self._test_update_service()
+
+    def test_update_service_with_bytes_body(self):
+        self._test_update_service(bytes_body=True)
+
+    def test_delete_service(self):
+        self.check_service_client_function(
+            self.client.delete_service,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            service_id="686766",
+            status=204)
diff --git a/tempest/tests/lib/services/network/test_versions_client.py b/tempest/tests/lib/services/network/test_versions_client.py
index 715176b..ae52c8a 100644
--- a/tempest/tests/lib/services/network/test_versions_client.py
+++ b/tempest/tests/lib/services/network/test_versions_client.py
@@ -14,7 +14,7 @@
 
 import copy
 
-from tempest.lib.services.network.versions_client import NetworkVersionsClient
+from tempest.lib.services.network import versions_client
 from tempest.tests.lib import fake_auth_provider
 from tempest.tests.lib.services import base
 
@@ -59,7 +59,7 @@
         super(TestNetworkVersionsClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
         self.versions_client = (
-            NetworkVersionsClient
+            versions_client.NetworkVersionsClient
             (fake_auth, 'compute', 'regionOne'))
 
     def _test_versions_client(self, bytes_body=False):
diff --git a/tempest/tests/test_service_clients.py b/tempest/tests/lib/services/test_clients.py
similarity index 87%
rename from tempest/tests/test_service_clients.py
rename to tempest/tests/lib/services/test_clients.py
index b0aa456..5db932c 100644
--- a/tempest/tests/test_service_clients.py
+++ b/tempest/tests/lib/services/test_clients.py
@@ -19,7 +19,7 @@
 
 from tempest.lib import auth
 from tempest.lib import exceptions
-from tempest import service_clients
+from tempest.lib.services import clients
 from tempest.tests import base
 from tempest.tests.lib import fake_auth_provider
 from tempest.tests.lib import fake_credentials
@@ -54,14 +54,14 @@
     def test___init___one_class(self):
         fake_partial = 'fake_partial'
         partial_mock = self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory._get_partial_class',
+            'tempest.lib.services.clients.ClientsFactory._get_partial_class',
             return_value=fake_partial)).mock
         class_names = ['FakeServiceClient1']
         mock_importlib = self._setup_fake_module(class_names=class_names)
         auth_provider = fake_auth_provider.FakeAuthProvider()
         params = {'k1': 'v1', 'k2': 'v2'}
-        factory = service_clients.ClientsFactory('fake_path', class_names,
-                                                 auth_provider, **params)
+        factory = clients.ClientsFactory('fake_path', class_names,
+                                         auth_provider, **params)
         # Assert module has been imported
         mock_importlib.assert_called_once_with('fake_path')
         # All attributes have been created
@@ -77,14 +77,14 @@
     def test___init___two_classes(self):
         fake_partial = 'fake_partial'
         partial_mock = self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory._get_partial_class',
+            'tempest.lib.services.clients.ClientsFactory._get_partial_class',
             return_value=fake_partial)).mock
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
         mock_importlib = self._setup_fake_module(class_names=class_names)
         auth_provider = fake_auth_provider.FakeAuthProvider()
         params = {'k1': 'v1', 'k2': 'v2'}
-        factory = service_clients.ClientsFactory('fake_path', class_names,
-                                                 auth_provider, **params)
+        factory = clients.ClientsFactory('fake_path', class_names,
+                                         auth_provider, **params)
         # Assert module has been imported
         mock_importlib.assert_called_once_with('fake_path')
         # All attributes have been created
@@ -100,8 +100,8 @@
         auth_provider = fake_auth_provider.FakeAuthProvider()
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
         with testtools.ExpectedException(ImportError, '.*fake_module.*'):
-            service_clients.ClientsFactory('fake_module', class_names,
-                                           auth_provider)
+            clients.ClientsFactory('fake_module', class_names,
+                                   auth_provider)
 
     def test___init___not_a_class(self):
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
@@ -111,8 +111,8 @@
         auth_provider = fake_auth_provider.FakeAuthProvider()
         expected_msg = '.*not_really_a_class.*str.*'
         with testtools.ExpectedException(TypeError, expected_msg):
-            service_clients.ClientsFactory('fake_module', extended_class_names,
-                                           auth_provider)
+            clients.ClientsFactory('fake_module', extended_class_names,
+                                   auth_provider)
 
     def test___init___class_not_found(self):
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
@@ -121,15 +121,15 @@
         auth_provider = fake_auth_provider.FakeAuthProvider()
         expected_msg = '.*not_really_a_class.*fake_service_client.*'
         with testtools.ExpectedException(AttributeError, expected_msg):
-            service_clients.ClientsFactory('fake_module', extended_class_names,
-                                           auth_provider)
+            clients.ClientsFactory('fake_module', extended_class_names,
+                                   auth_provider)
 
     def test__get_partial_class_no_later_kwargs(self):
         expected_fake_client = 'not_really_a_client'
         self._setup_fake_module(class_names=[])
         auth_provider = fake_auth_provider.FakeAuthProvider()
         params = {'k1': 'v1', 'k2': 'v2'}
-        factory = service_clients.ClientsFactory(
+        factory = clients.ClientsFactory(
             'fake_path', [], auth_provider, **params)
         klass_mock = mock.Mock(return_value=expected_fake_client)
         partial = factory._get_partial_class(klass_mock, auth_provider, params)
@@ -147,7 +147,7 @@
         auth_provider = fake_auth_provider.FakeAuthProvider()
         params = {'k1': 'v1', 'k2': 'v2'}
         later_params = {'k2': 'v4', 'k3': 'v3'}
-        factory = service_clients.ClientsFactory(
+        factory = clients.ClientsFactory(
             'fake_path', [], auth_provider, **params)
         klass_mock = mock.Mock(return_value=expected_fake_client)
         partial = factory._get_partial_class(klass_mock, auth_provider, params)
@@ -167,7 +167,7 @@
         auth_provider = fake_auth_provider.FakeAuthProvider()
         params = {'k1': 'v1', 'k2': 'v2'}
         later_params = {'k2': 'v4', 'k3': 'v3'}
-        factory = service_clients.ClientsFactory(
+        factory = clients.ClientsFactory(
             'fake_path', [], auth_provider, **params)
         klass_mock = mock.Mock(return_value=expected_fake_client)
         partial = factory._get_partial_class(klass_mock, auth_provider, params)
@@ -188,15 +188,17 @@
     def setUp(self):
         super(TestServiceClients, self).setUp()
         self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.tempest_modules',
-            return_value=set(['fake_service1', 'fake_service2'])))
+            'tempest.lib.services.clients.tempest_modules', return_value={}))
+        self.useFixture(fixtures.MockPatch(
+            'tempest.lib.services.clients._tempest_internal_modules',
+            return_value=set(['fake_service1'])))
 
     def test___init___creds_v2_uri(self):
         # Verify that no API request is made, since no mock
         # is required to run the test successfully
         creds = fake_credentials.FakeKeystoneV2Credentials()
         uri = 'fake_uri'
-        _manager = service_clients.ServiceClients(creds, identity_uri=uri)
+        _manager = clients.ServiceClients(creds, identity_uri=uri)
         self.assertIsInstance(_manager.auth_provider,
                               auth.KeystoneV2AuthProvider)
 
@@ -205,7 +207,7 @@
         # is required to run the test successfully
         creds = fake_credentials.FakeKeystoneV3Credentials()
         uri = 'fake_uri'
-        _manager = service_clients.ServiceClients(creds, identity_uri=uri)
+        _manager = clients.ServiceClients(creds, identity_uri=uri)
         self.assertIsInstance(_manager.auth_provider,
                               auth.KeystoneV3AuthProvider)
 
@@ -213,14 +215,14 @@
         creds = fake_credentials.FakeCredentials()
         uri = 'fake_uri'
         with testtools.ExpectedException(exceptions.InvalidCredentials):
-            service_clients.ServiceClients(creds, identity_uri=uri)
+            clients.ServiceClients(creds, identity_uri=uri)
 
     def test___init___invalid_creds_uri(self):
         creds = fake_credentials.FakeKeystoneV2Credentials()
         delattr(creds, 'username')
         uri = 'fake_uri'
         with testtools.ExpectedException(exceptions.InvalidCredentials):
-            service_clients.ServiceClients(creds, identity_uri=uri)
+            clients.ServiceClients(creds, identity_uri=uri)
 
     def test___init___creds_uri_none(self):
         creds = fake_credentials.FakeKeystoneV2Credentials()
@@ -228,7 +230,7 @@
                "non-empty")
         with testtools.ExpectedException(exceptions.InvalidCredentials,
                                          value_re=msg):
-            service_clients.ServiceClients(creds, None)
+            clients.ServiceClients(creds, None)
 
     def test___init___creds_uri_params(self):
         creds = fake_credentials.FakeKeystoneV2Credentials()
@@ -236,8 +238,8 @@
                           'fake_param2': 'fake_value2'}
         params = {'fake_service1': expeted_params}
         uri = 'fake_uri'
-        _manager = service_clients.ServiceClients(creds, identity_uri=uri,
-                                                  client_parameters=params)
+        _manager = clients.ServiceClients(creds, identity_uri=uri,
+                                          client_parameters=params)
         self.assertIn('fake_service1', _manager.parameters)
         for _key in expeted_params:
             self.assertIn(_key, _manager.parameters['fake_service1'].keys())
@@ -253,14 +255,14 @@
         msg = "(?=.*{0})(?=.*{1})".format(*list(params.keys()))
         with testtools.ExpectedException(
                 exceptions.UnknownServiceClient, value_re=msg):
-            service_clients.ServiceClients(creds, identity_uri=uri,
-                                           client_parameters=params)
+            clients.ServiceClients(creds, identity_uri=uri,
+                                   client_parameters=params)
 
     def _get_manager(self, init_region='fake_region'):
         # Get a manager to invoke _setup_parameters on
         creds = fake_credentials.FakeKeystoneV2Credentials()
-        return service_clients.ServiceClients(creds, identity_uri='fake_uri',
-                                              region=init_region)
+        return clients.ServiceClients(creds, identity_uri='fake_uri',
+                                      region=init_region)
 
     def test__setup_parameters_none_no_region(self):
         kwargs = {}
@@ -292,7 +294,7 @@
         _manager = self._get_manager(init_region='fake_region_default')
         # Mock after the _manager is setup to preserve the call count
         factory_mock = self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory')).mock
+            'tempest.lib.services.clients.ClientsFactory')).mock
         _manager.register_service_client_module(
             name='fake_module',
             service_version='fake_service',
@@ -321,7 +323,7 @@
         _manager = self._get_manager(init_region='fake_region_default')
         # Mock after the _manager is setup to preserve the call count
         factory_mock = self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory')).mock
+            'tempest.lib.services.clients.ClientsFactory')).mock
         _manager.register_service_client_module(
             name='fake_module',
             service_version='fake_service',
@@ -344,7 +346,7 @@
 
     def test_register_service_client_module_duplicate_name(self):
         self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory'))
+            'tempest.lib.services.clients.ClientsFactory')).mock
         _manager = self._get_manager()
         name_owner = 'this_is_a_string'
         setattr(_manager, 'fake_module', name_owner)
@@ -357,7 +359,7 @@
 
     def test_register_service_client_module_duplicate_service(self):
         self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.ClientsFactory'))
+            'tempest.lib.services.clients.ClientsFactory')).mock
         _manager = self._get_manager()
         duplicate_service = 'fake_service1'
         expected_error = '.*' + duplicate_service
diff --git a/tox.ini b/tox.ini
index cff222d..a621492 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = pep8,py34,py27
+envlist = pep8,py35,py34,py27
 minversion = 2.3.1
 skipsdist = True
 
@@ -77,7 +77,7 @@
 # See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
     find . -type f -name "*.pyc" -delete
-    bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
+    bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)) {posargs}'
 
 [testenv:full-serial]
 envdir = .tox/tempest
@@ -88,7 +88,7 @@
 # See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
     find . -type f -name "*.pyc" -delete
-    bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
+    bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario)) {posargs}'
 
 [testenv:smoke]
 envdir = .tox/tempest