Merge "Add python 3.5 classifier and venv"
diff --git a/README.rst b/README.rst
index 53c7de5..13f4f61 100644
--- a/README.rst
+++ b/README.rst
@@ -178,9 +178,8 @@
 is OS_TEST_PATH=./tempest/test_discover which will only run test discover on the
 Tempest suite.
 
-Alternatively, you can use the run_tests.sh script which will create a venv and
-run the unit tests. There are also the py27 and py34 tox jobs which will run
-the unit tests with the corresponding version of python.
+Alternatively, there are the py27 and py34 tox jobs which will run the unit
+tests with the corresponding version of python.
 
 Python 2.6
 ----------
@@ -224,7 +223,7 @@
 
     $ cd $TEMPEST_ROOT_DIR
     $ oslo-config-generator --config-file \
-        etc/config-generator.tempest.conf \
+        tempest/cmd/config-generator.tempest.conf \
         --output-file etc/tempest.conf
 
 After that, open up the ``etc/tempest.conf`` file and edit the
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/index.rst b/doc/source/index.rst
index f1ede06..6abe9dc 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -50,7 +50,6 @@
 
    account_generator
    cleanup
-   javelin
    subunit_describe_calls
    workspace
    run
diff --git a/doc/source/javelin.rst b/doc/source/javelin.rst
deleted file mode 100644
index 01090ca..0000000
--- a/doc/source/javelin.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-----------------------------------------------------------
-Javelin2 - How to check that resources survived an upgrade
-----------------------------------------------------------
-
-.. automodule:: tempest.cmd.javelin
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 17059e4..bff18f8 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -217,3 +217,11 @@
  * `2.20`_
 
  .. _2.20: http://docs.openstack.org/developer/nova/api_microversion_history.html#id18
+
+ * `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/etc/javelin-resources.yaml.sample b/etc/javelin-resources.yaml.sample
deleted file mode 100644
index 1565686..0000000
--- a/etc/javelin-resources.yaml.sample
+++ /dev/null
@@ -1,63 +0,0 @@
-tenants:
-  - javelin
-  - discuss
-
-users:
-  - name: javelin
-    pass: gungnir
-    tenant: javelin
-  - name: javelin2
-    pass: gungnir2
-    tenant: discuss
-
-secgroups:
-  - name: secgroup1
-    owner: javelin
-    description: SecurityGroup1
-    rules:
-      - 'icmp -1 -1 0.0.0.0/0'
-      - 'tcp 22 22 0.0.0.0/0'
-  - name: secgroup2
-    owner: javelin2
-    description: SecurityGroup2
-    rules:
-      - 'tcp 80 80 0.0.0.0/0'
-
-images:
-  - name: cirros1
-    owner: javelin
-    imgdir: images
-    file: cirros.img
-    container_format: bare
-    disk_format: qcow2
-  - name: cirros2
-    owner: javelin2
-    imgdir: files/images/cirros-0.3.2-x86_64-uec
-    file: cirros-0.3.2-x86_64-blank.img
-    container_format: ami
-    disk_format: ami
-    aki: cirros-0.3.2-x86_64-vmlinuz
-    ari: cirros-0.3.2-x86_64-initrd
-
-networks:
-  - name: network1
-    owner: javelin
-  - name: network2
-    owner: javelin2
-
-subnets:
-  - name: net1-subnet1
-    range: 10.1.0.0/24
-    network: network1
-    owner: javelin
-  - name: net2-subnet2
-    range: 192.168.1.0/24
-    network: network2
-    owner: javelin2
-
-objects:
-  - container: container1
-    name: object1
-    owner: javelin
-    file: /etc/hosts
-    swift_role: Member
diff --git a/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml b/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
new file mode 100644
index 0000000..a360f8e
--- /dev/null
+++ b/releasenotes/notes/add-httptimeout-in-restclient-ax78061900e3f3d7.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - RestClient now supports setting timeout in urllib3.poolmanager.
+    Clients will use CONF.service_clients.http_timeout for timeout
+    value to wait for http request to response.
+  - KeystoneAuthProvider will accept http_timeout and will use it in
+    get_credentials.
diff --git a/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml b/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
new file mode 100644
index 0000000..b8dcfce
--- /dev/null
+++ b/releasenotes/notes/add-new-identity-clients-3c3afd674a395bde.yaml
@@ -0,0 +1,10 @@
+---
+features:
+  - |
+    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)
diff --git a/releasenotes/notes/add-new-identity-clients-as-library-3e6559d4bff3e776.yaml b/releasenotes/notes/add-new-identity-clients-as-library-3e6559d4bff3e776.yaml
new file mode 100644
index 0000000..9feb3c3
--- /dev/null
+++ b/releasenotes/notes/add-new-identity-clients-as-library-3e6559d4bff3e776.yaml
@@ -0,0 +1,9 @@
+---
+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.
+
+      * regions_client(v3)
+      * services_client(v3)
diff --git a/releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml b/releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml
index b457ddd..092014e 100644
--- a/releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml
+++ b/releasenotes/notes/add_subunit_describe_calls-5498a37e6cd66c4b.yaml
@@ -1,4 +1,8 @@
 ---
 features:
-  - Adds subunit-describe-calls. A parser for subunit streams to determine what
+  - |
+    Adds subunit-describe-calls. A parser for subunit streams to determine what
     REST API calls are made inside of a test and in what order they are called.
+
+      * Input can be piped in or a file can be specified
+      * Output is shortened for stdout, the output file has more information
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/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/plugin-service-client-registration-00b19a2dd4935ba0.yaml b/releasenotes/notes/plugin-service-client-registration-00b19a2dd4935ba0.yaml
new file mode 100644
index 0000000..64f729a
--- /dev/null
+++ b/releasenotes/notes/plugin-service-client-registration-00b19a2dd4935ba0.yaml
@@ -0,0 +1,12 @@
+---
+features:
+  - A new optional interface `TempestPlugin.get_service_clients`
+    is available to plugins. It allows them to declare
+    any service client they implement. For now this is used by
+    tempest only, for auto-registration of service clients
+    in the new class `ServiceClients`.
+  - A new singleton class `clients.ClientsRegistry` is
+    available. It holds the service clients registration data
+    from all plugins. It is used by `ServiceClients` for
+    auto-registration of the service clients implemented
+    in plugins.
diff --git a/releasenotes/notes/remove-javelin-276f62d04f7e4a1d.yaml b/releasenotes/notes/remove-javelin-276f62d04f7e4a1d.yaml
new file mode 100644
index 0000000..8e893b8
--- /dev/null
+++ b/releasenotes/notes/remove-javelin-276f62d04f7e4a1d.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - The previously deprecated Javelin utility has been removed from Tempest.
+    As an alternative Ansible can be used to construct similar yaml workflows
+    to what Javelin used to provide.
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 216dd50..d698cda 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,18 +8,17 @@
 paramiko>=2.0 # LGPLv2.1+
 netaddr!=0.7.16,>=0.7.12 # BSD
 testrepository>=0.0.18 # Apache-2.0/BSD
-pyOpenSSL>=0.14 # Apache-2.0
 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
-oslo.utils>=3.15.0 # Apache-2.0
+oslo.utils>=3.16.0 # Apache-2.0
 six>=1.9.0 # MIT
 fixtures>=3.0.0 # Apache-2.0/BSD
 testscenarios>=0.4 # Apache-2.0/BSD
 PyYAML>=3.1.0 # MIT
-stevedore>=1.10.0 # Apache-2.0
+stevedore>=1.16.0 # Apache-2.0
 PrettyTable<0.8,>=0.7 # BSD
 os-testr>=0.7.0 # Apache-2.0
 urllib3>=1.15.1 # MIT
diff --git a/run_tests.sh b/run_tests.sh
index 22314b6..a856bb4 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -17,6 +17,44 @@
   echo "  -- [TESTROPTIONS]        After the first '--' you can pass arbitrary arguments to testr "
 }
 
+function deprecation_warning {
+  cat <<EOF
+-------------------------------------------------------------------------
+WARNING: run_tests.sh is deprecated and this script will be removed after
+the Newton release. All tests should be run through testr/ostestr or tox.
+
+To run style checks:
+
+ tox -e pep8
+
+To run python 2.7 unit tests
+
+ tox -e py27
+
+To run unit tests and generate coverage report
+
+ tox -e cover
+
+To run a subset of any of these tests:
+
+ tox -e py27 someregex
+
+ i.e.: tox -e py27 test_servers
+
+Additional tox targets are available in tox.ini. For more information
+see:
+http://docs.openstack.org/project-team-guide/project-setup/python.html
+
+NOTE: if you want to use testr to run tests, you can instead use:
+
+ OS_TEST_PATH=./tempest/tests testr run
+
+Documentation on using testr directly can be found at
+http://testrepository.readthedocs.org/en/latest/MANUAL.html
+-------------------------------------------------------------------------
+EOF
+}
+
 testrargs=""
 just_pep8=0
 venv=${VENV:-.venv}
@@ -32,6 +70,8 @@
 config_file=""
 update=0
 
+deprecation_warning
+
 if ! options=$(getopt -o VNnfuctphd -l virtual-env,no-virtual-env,no-site-packages,force,update,serial,coverage,pep8,help,debug -- "$@")
 then
     # parse error
diff --git a/setup.cfg b/setup.cfg
index 76bed2b..50bf891 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -28,7 +28,6 @@
 [entry_points]
 console_scripts =
     verify-tempest-config = tempest.cmd.verify_tempest_config:main
-    javelin2 = tempest.cmd.javelin:main
     run-tempest-stress = tempest.cmd.run_stress:main
     tempest-cleanup = tempest.cmd.cleanup:main
     tempest-account-generator = tempest.cmd.account_generator:main
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 f7891dd..ac5986c 100644
--- a/tempest/api/baremetal/admin/base.py
+++ b/tempest/api/baremetal/admin/base.py
@@ -96,10 +96,10 @@
 
     @classmethod
     @creates('chassis')
-    def create_chassis(cls, description=None, expect_errors=False):
+    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 84b00a7..ac1bfee 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -181,7 +181,7 @@
                         host=self.host)
 
         aggregates = self.client.list_aggregates()['aggregates']
-        aggs = filter(lambda x: x['id'] == aggregate['id'], aggregates)
+        aggs = [agg for agg in aggregates if agg['id'] == aggregate['id']]
         self.assertEqual(1, len(aggs))
         agg = aggs[0]
         self.assertEqual(aggregate_name, agg['name'])
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 6b75aee..3c4e313 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -36,8 +36,8 @@
         cls.az_name_prefix = 'test_az'
 
         hosts_all = cls.os_adm.hosts_client.list_hosts()['hosts']
-        hosts = map(lambda x: x['host_name'],
-                    filter(lambda y: y['service'] == 'compute', hosts_all))
+        hosts = ([host['host_name']
+                 for host in hosts_all if host['service'] == 'compute'])
         cls.host = hosts[0]
 
     @test.attr(type=['negative'])
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..052c17d
--- /dev/null
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -0,0 +1,205 @@
+# 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 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()
+        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 94635ff..dd7beaa 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -27,6 +27,8 @@
 
 class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
     _host_key = 'OS-EXT-SRV-ATTR:host'
+    max_microversion = '2.24'
+    block_migration = None
 
     @classmethod
     def skip_checks(cls):
@@ -64,12 +66,16 @@
         return self._get_server_details(server_id)[self._host_key]
 
     def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
-        block_migration = (CONF.compute_feature_enabled.
-                           block_migration_for_live_migration and
-                           not volume_backed)
+        kwargs = dict()
+        block_migration = getattr(self, 'block_migration', None)
+        if self.block_migration is None:
+            kwargs['disk_over_commit'] = False
+            block_migration = (CONF.compute_feature_enabled.
+                               block_migration_for_live_migration and
+                               not volume_backed)
         body = self.admin_servers_client.live_migrate_server(
             server_id, host=dest_host, block_migration=block_migration,
-            disk_over_commit=False)
+            **kwargs)
         return body
 
     def _get_host_other_than(self, host):
@@ -167,3 +173,9 @@
         waiters.wait_for_server_status(self.servers_client,
                                        server_id, 'ACTIVE')
         self.assertEqual(target_host, self._get_host_for_server(server_id))
+
+
+class LiveAutoBlockMigrationV225TestJSON(LiveBlockMigrationTestJSON):
+    min_microversion = '2.25'
+    max_microversion = 'latest'
+    block_migration = 'auto'
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 1494745..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):
 
@@ -65,7 +62,7 @@
         # Fetch all security groups based on 'all_tenants' search filter
         fetched_list = self.adm_client.list_security_groups(
             all_tenants='true')['security_groups']
-        sec_group_id_list = map(lambda sg: sg['id'], fetched_list)
+        sec_group_id_list = [sg['id'] for sg in fetched_list]
         # Now check if all created Security Groups are present in fetched list
         for sec_group in security_group_list:
             self.assertIn(sec_group['id'], sec_group_id_list)
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 3eb6d94..dd4a533
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -37,12 +37,12 @@
     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']
@@ -70,6 +70,13 @@
         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('9f5579ae-19b4-4985-a091-2a5d56106580')
     def test_list_servers_by_admin_with_all_tenants(self):
         # Listing servers by admin user with all tenants parameter
@@ -77,7 +84,7 @@
         params = {'all_tenants': ''}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        servers_name = map(lambda x: x['name'], servers)
+        servers_name = [server['name'] for server in servers]
 
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
@@ -103,7 +110,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
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..5ff5d58
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -40,7 +40,7 @@
         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']
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 37aa5ac..5e75493 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -359,7 +359,7 @@
             for address in addresses:
                 if address['version'] == CONF.validation.ip_version_for_ssh:
                     return address['addr']
-            raise exceptions.ServerUnreachable()
+            raise exceptions.ServerUnreachable(server_id=server['id'])
         else:
             raise exceptions.InvalidConfiguration()
 
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/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index 5125e2b..e6abf28 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -44,9 +44,11 @@
             security_group_id.append(body[i]['id'])
         # Generate a non-existent security group id
         while True:
-            non_exist_id = data_utils.rand_int_id(start=999)
-            if self.neutron_available:
+            if (self.neutron_available and
+                test.is_extension_enabled('security-group', 'network')):
                 non_exist_id = data_utils.rand_uuid()
+            else:
+                non_exist_id = data_utils.rand_int_id(start=999)
             if non_exist_id not in security_group_id:
                 break
         return non_exist_id
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index fdf55e5..7c12bf9 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -16,9 +16,12 @@
 import time
 
 from tempest.api.compute import base
+from tempest.common import compute
 from tempest.common.utils import net_utils
+from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -48,6 +51,7 @@
         cls.networks_client = cls.os.networks_client
         cls.subnets_client = cls.os.subnets_client
         cls.ports_client = cls.os.ports_client
+        cls.servers_client = cls.servers_client
 
     def wait_for_interface_status(self, server, port_id, status):
         """Waits for an interface to reach a given status."""
@@ -73,6 +77,34 @@
 
         return body
 
+    # TODO(mriedem): move this into a common waiters utility module
+    def wait_for_port_detach(self, port_id):
+        """Waits for the port's device_id to be unset.
+
+        :param port_id: The id of the port being detached.
+        :returns: The final port dict from the show_port response.
+        """
+        port = self.ports_client.show_port(port_id)['port']
+        device_id = port['device_id']
+        start = int(time.time())
+
+        # NOTE(mriedem): Nova updates the port's device_id to '' rather than
+        # None, but it's not contractual so handle Falsey either way.
+        while device_id:
+            time.sleep(self.build_interval)
+            port = self.ports_client.show_port(port_id)['port']
+            device_id = port['device_id']
+
+            timed_out = int(time.time()) - start >= self.build_timeout
+
+            if device_id and timed_out:
+                message = ('Port %s failed to detach (device_id %s) within '
+                           'the required time (%s s).' %
+                           (port_id, device_id, self.build_timeout))
+                raise exceptions.TimeoutException(message)
+
+        return port
+
     def _check_interface(self, iface, port_id=None, network_id=None,
                          fixed_ip=None, mac_addr=None):
         self.assertIn('port_state', iface)
@@ -240,3 +272,41 @@
             if fixed_ip is not None:
                 break
         self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
+
+    @decorators.skip_because(bug='1607714')
+    @test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
+    def test_reassign_port_between_servers(self):
+        """Tests the following:
+
+        1. Create a port in Neutron.
+        2. Create two servers in Nova.
+        3. Attach the port to the first server.
+        4. Detach the port from the first server.
+        5. Attach the port to the second server.
+        6. Detach the port from the second server.
+        """
+        network = self.get_tenant_network()
+        network_id = network['id']
+        port = self.ports_client.create_port(network_id=network_id)
+        port_id = port['port']['id']
+        self.addCleanup(self.ports_client.delete_port, port_id)
+
+        # create two servers
+        _, servers = compute.create_test_server(
+            self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
+        # add our cleanups for the servers since we bypassed the base class
+        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'])
+
+        for server in servers:
+            # attach the port to the server
+            iface = self.client.create_interface(
+                server['id'], port_id=port_id)['interfaceAttachment']
+            self._check_interface(iface, port_id=port_id)
+
+            # detach the port from the server; this is a cast in the compute
+            # API so we have to poll the port until the device_id is unset.
+            self.client.delete_interface(server['id'], port_id)
+            self.wait_for_port_detach(port_id)
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..e8df52d
--- 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(
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 0d06119..062e920
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -110,6 +110,10 @@
                 servers_client=self.client)
             boot_time = linux_client.get_boot_time()
 
+            # NOTE: This sync is for avoiding the loss of pub key data
+            # in a server
+            linux_client.exec_command("sync")
+
         self.client.reboot_server(self.server_id, type=reboot_type)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
@@ -151,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,
@@ -266,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')
 
@@ -281,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.')
@@ -305,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/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 05c23ee..a5c303c 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -84,19 +84,21 @@
                                        self.volume['id'], 'available')
 
         if shelve_server:
-            # NOTE(andreaf) If we are going to shelve a server, we should
-            # check first whether the server is ssh-able. Otherwise we won't
-            # be able to distinguish failures introduced by shelve from
-            # pre-existing ones. Also it's good to wait for cloud-init to be
-            # done and sshd server to be running before shelving to avoid
-            # breaking the VM
-            linux_client = remote_client.RemoteClient(
-                self.get_server_ip(self.server),
-                self.image_ssh_user,
-                self.admin_pass,
-                self.validation_resources['keypair']['private_key'])
-            linux_client.validate_authentication()
-            # If validation went ok, shelve the server
+            if CONF.validation.run_validation:
+                # NOTE(andreaf) If we are going to shelve a server, we should
+                # check first whether the server is ssh-able. Otherwise we
+                # won't be able to distinguish failures introduced by shelve
+                # from pre-existing ones. Also it's good to wait for cloud-init
+                # to be done and sshd server to be running before shelving to
+                # avoid breaking the VM
+                linux_client = remote_client.RemoteClient(
+                    self.get_server_ip(self.server),
+                    self.image_ssh_user,
+                    self.admin_pass,
+                    self.validation_resources['keypair']['private_key'])
+                linux_client.validate_authentication()
+
+            # If validation went ok, or it was skipped, shelve the server
             compute.shelve_server(self.servers_client, self.server['id'])
 
         # Attach the volume to the server
@@ -110,8 +112,6 @@
         self.addCleanup(self._detach, self.server['id'], self.volume['id'])
 
     @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
-    @testtools.skipUnless(CONF.validation.run_validation,
-                          'SSH required for this test')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
@@ -125,16 +125,17 @@
         waiters.wait_for_server_status(self.servers_client, self.server['id'],
                                        'ACTIVE')
 
-        linux_client = remote_client.RemoteClient(
-            self.get_server_ip(self.server),
-            self.image_ssh_user,
-            self.admin_pass,
-            self.validation_resources['keypair']['private_key'],
-            server=self.server,
-            servers_client=self.servers_client)
+        if CONF.validation.run_validation:
+            linux_client = remote_client.RemoteClient(
+                self.get_server_ip(self.server),
+                self.image_ssh_user,
+                self.admin_pass,
+                self.validation_resources['keypair']['private_key'],
+                server=self.server,
+                servers_client=self.servers_client)
 
-        partitions = linux_client.get_partitions()
-        self.assertIn(self.device, partitions)
+            partitions = linux_client.get_partitions()
+            self.assertIn(self.device, partitions)
 
         self._detach(self.server['id'], self.volume['id'])
         self.attachment = None
@@ -146,16 +147,17 @@
         waiters.wait_for_server_status(self.servers_client, self.server['id'],
                                        'ACTIVE')
 
-        linux_client = remote_client.RemoteClient(
-            self.get_server_ip(self.server),
-            self.image_ssh_user,
-            self.admin_pass,
-            self.validation_resources['keypair']['private_key'],
-            server=self.server,
-            servers_client=self.servers_client)
+        if CONF.validation.run_validation:
+            linux_client = remote_client.RemoteClient(
+                self.get_server_ip(self.server),
+                self.image_ssh_user,
+                self.admin_pass,
+                self.validation_resources['keypair']['private_key'],
+                server=self.server,
+                servers_client=self.servers_client)
 
-        partitions = linux_client.get_partitions()
-        self.assertNotIn(self.device, partitions)
+            partitions = linux_client.get_partitions()
+            self.assertNotIn(self.device, partitions)
 
     @test.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
     def test_list_get_volume_attachments(self):
@@ -192,23 +194,22 @@
         waiters.wait_for_server_status(self.servers_client,
                                        self.server['id'],
                                        'ACTIVE')
-        linux_client = remote_client.RemoteClient(
-            self.get_server_ip(self.server['id']),
-            self.image_ssh_user,
-            self.admin_pass,
-            self.validation_resources['keypair']['private_key'],
-            server=self.server,
-            servers_client=self.servers_client)
+        if CONF.validation.run_validation:
+            linux_client = remote_client.RemoteClient(
+                self.get_server_ip(self.server['id']),
+                self.image_ssh_user,
+                self.admin_pass,
+                self.validation_resources['keypair']['private_key'],
+                server=self.server,
+                servers_client=self.servers_client)
 
-        command = 'grep [vs]d /proc/partitions | wc -l'
-        nb_partitions = linux_client.exec_command(command).strip()
-        self.assertEqual(number_of_partition, nb_partitions)
+            command = 'grep [vs]d /proc/partitions | wc -l'
+            nb_partitions = linux_client.exec_command(command).strip()
+            self.assertEqual(number_of_partition, nb_partitions)
 
     @test.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @testtools.skipUnless(CONF.validation.run_validation,
-                          'SSH required for this test')
     def test_attach_volume_shelved_or_offload_server(self):
         self._create_and_attach(shelve_server=True)
 
@@ -228,8 +229,6 @@
     @test.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @testtools.skipUnless(CONF.validation.run_validation,
-                          'SSH required for this test')
     def test_detach_volume_shelved_or_offload_server(self):
         self._create_and_attach(shelve_server=True)
 
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/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 0924619..380920f 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -17,6 +17,7 @@
 
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest import test
 
 
@@ -25,17 +26,22 @@
     @classmethod
     def resource_setup(cls):
         super(RolesTestJSON, cls).resource_setup()
+        cls.roles = list()
         for _ in moves.xrange(5):
             role_name = data_utils.rand_name(name='role')
             role = cls.roles_client.create_role(name=role_name)['role']
-            cls.data.roles.append(role)
+            cls.roles.append(role)
+
+    @classmethod
+    def resource_cleanup(cls):
+        super(RolesTestJSON, cls).resource_cleanup()
+        for role in cls.roles:
+            cls.roles_client.delete_role(role['id'])
 
     def _get_role_params(self):
-        self.data.setup_test_user()
-        self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.user['name'])
-        tenant = self.get_tenant_by_name(self.data.tenant['name'])
-        role = self.get_role_by_name(self.data.role['name'])
+        user = self.setup_test_user()
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        role = self.setup_test_role()
         return (user, tenant, role)
 
     def assert_role_in_role_list(self, role, roles):
@@ -49,15 +55,17 @@
     def test_list_roles(self):
         """Return a list of all roles."""
         body = self.roles_client.list_roles()['roles']
-        found = [role for role in body if role in self.data.roles]
+        found = [role for role in body if role in self.roles]
         self.assertTrue(any(found))
-        self.assertEqual(len(found), len(self.data.roles))
+        self.assertEqual(len(found), len(self.roles))
 
     @test.idempotent_id('c62d909d-6c21-48c0-ae40-0a0760e6db5e')
     def test_role_create_delete(self):
         """Role should be created, verified, and deleted."""
         role_name = data_utils.rand_name(name='role-test')
         body = self.roles_client.create_role(name=role_name)['role']
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.roles_client.delete_role, body['id'])
         self.assertEqual(role_name, body['name'])
 
         body = self.roles_client.list_roles()['roles']
@@ -73,9 +81,9 @@
     @test.idempotent_id('db6870bd-a6ed-43be-a9b1-2f10a5c9994f')
     def test_get_role_by_id(self):
         """Get a role by its id."""
-        self.data.setup_test_role()
-        role_id = self.data.role['id']
-        role_name = self.data.role['name']
+        role = self.setup_test_role()
+        role_id = role['id']
+        role_name = role['name']
         body = self.roles_client.show_role(role_id)['role']
         self.assertEqual(role_id, body['id'])
         self.assertEqual(role_name, body['name'])
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index 770bb14..7116913 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -22,11 +22,9 @@
 class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
 
     def _get_role_params(self):
-        self.data.setup_test_user()
-        self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.user['name'])
-        tenant = self.get_tenant_by_name(self.data.tenant['name'])
-        role = self.get_role_by_name(self.data.role['name'])
+        user = self.setup_test_user()
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        role = self.setup_test_role()
         return (user, tenant, role)
 
     @test.attr(type=['negative'])
@@ -89,7 +87,7 @@
         # Non-administrator user should not be able to delete role
         role_name = data_utils.rand_name(name='role')
         body = self.roles_client.create_role(name=role_name)['role']
-        self.data.roles.append(body)
+        self.addCleanup(self.roles_client.delete_role, body['id'])
         role_id = body.get('id')
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_roles_client.delete_role, role_id)
@@ -100,7 +98,7 @@
         # Request to delete role without a valid token should fail
         role_name = data_utils.rand_name(name='role')
         body = self.roles_client.create_role(name=role_name)['role']
-        self.data.roles.append(body)
+        self.addCleanup(self.roles_client.delete_role, body['id'])
         role_id = body.get('id')
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 6c9b564..94291f8 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -93,7 +93,7 @@
                 name=name, type=s_type,
                 description=description)['OS-KSADM:service']
             services.append(service)
-        service_ids = map(lambda x: x['id'], services)
+        service_ids = [svc['id'] for svc in services]
 
         def delete_services():
             for service_id in service_ids:
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index d1e0217..baa78e9 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -44,7 +44,7 @@
         # Non-administrator user should not be able to delete a tenant
         tenant_name = data_utils.rand_name(name='tenant')
         tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.data.tenants.append(tenant)
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.delete_tenant,
                           tenant['id'])
@@ -55,7 +55,7 @@
         # Request to delete a tenant without a valid token should fail
         tenant_name = data_utils.rand_name(name='tenant')
         tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.data.tenants.append(tenant)
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
         self.assertRaises(lib_exc.Unauthorized,
@@ -76,12 +76,9 @@
         # Tenant names should be unique
         tenant_name = data_utils.rand_name(name='tenant')
         body = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        tenant = body
-        self.data.tenants.append(tenant)
         tenant1_id = body.get('id')
 
         self.addCleanup(self.tenants_client.delete_tenant, tenant1_id)
-        self.addCleanup(self.data.tenants.remove, tenant)
         self.assertRaises(lib_exc.Conflict, self.tenants_client.create_tenant,
                           name=tenant_name)
 
@@ -136,7 +133,7 @@
         # Non-administrator user should not be able to update a tenant
         tenant_name = data_utils.rand_name(name='tenant')
         tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.data.tenants.append(tenant)
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.update_tenant,
                           tenant['id'])
@@ -147,7 +144,7 @@
         # Request to update a tenant without a valid token should fail
         tenant_name = data_utils.rand_name(name='tenant')
         tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.data.tenants.append(tenant)
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
         self.assertRaises(lib_exc.Unauthorized,
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index 1aa80df..4faf184 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -17,6 +17,7 @@
 
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest import test
 
 
@@ -30,16 +31,17 @@
             tenant_name = data_utils.rand_name(name='tenant-new')
             tenant = self.tenants_client.create_tenant(
                 name=tenant_name)['tenant']
-            self.data.tenants.append(tenant)
+            # Add the tenant to the cleanup list
+            self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                            self.tenants_client.delete_tenant, tenant['id'])
             tenants.append(tenant)
-        tenant_ids = map(lambda x: x['id'], tenants)
+        tenant_ids = [tn['id'] for tn in tenants]
         body = self.tenants_client.list_tenants()['tenants']
         found = [t for t in body if t['id'] in tenant_ids]
         self.assertEqual(len(found), len(tenants), 'Tenants not created')
 
         for tenant in tenants:
             self.tenants_client.delete_tenant(tenant['id'])
-            self.data.tenants.remove(tenant)
 
         body = self.tenants_client.list_tenants()['tenants']
         found = [tenant for tenant in body if tenant['id'] in tenant_ids]
@@ -53,7 +55,9 @@
         body = self.tenants_client.create_tenant(name=tenant_name,
                                                  description=tenant_desc)
         tenant = body['tenant']
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
         tenant_id = tenant['id']
         desc1 = tenant['description']
         self.assertEqual(desc1, tenant_desc, 'Description should have '
@@ -63,7 +67,6 @@
         self.assertEqual(desc2, tenant_desc, 'Description does not appear'
                          'to be set')
         self.tenants_client.delete_tenant(tenant_id)
-        self.data.tenants.remove(tenant)
 
     @test.idempotent_id('670bdddc-1cd7-41c7-b8e2-751cfb67df50')
     def test_tenant_create_enabled(self):
@@ -72,7 +75,9 @@
         body = self.tenants_client.create_tenant(name=tenant_name,
                                                  enabled=True)
         tenant = body['tenant']
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
         tenant_id = tenant['id']
         en1 = tenant['enabled']
         self.assertTrue(en1, 'Enable should be True in response')
@@ -80,7 +85,6 @@
         en2 = body['enabled']
         self.assertTrue(en2, 'Enable should be True in lookup')
         self.tenants_client.delete_tenant(tenant_id)
-        self.data.tenants.remove(tenant)
 
     @test.idempotent_id('3be22093-b30f-499d-b772-38340e5e16fb')
     def test_tenant_create_not_enabled(self):
@@ -89,7 +93,9 @@
         body = self.tenants_client.create_tenant(name=tenant_name,
                                                  enabled=False)
         tenant = body['tenant']
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
         tenant_id = tenant['id']
         en1 = tenant['enabled']
         self.assertEqual('false', str(en1).lower(),
@@ -99,7 +105,6 @@
         self.assertEqual('false', str(en2).lower(),
                          'Enable should be False in lookup')
         self.tenants_client.delete_tenant(tenant_id)
-        self.data.tenants.remove(tenant)
 
     @test.idempotent_id('781f2266-d128-47f3-8bdb-f70970add238')
     def test_tenant_update_name(self):
@@ -107,7 +112,9 @@
         t_name1 = data_utils.rand_name(name='tenant')
         body = self.tenants_client.create_tenant(name=t_name1)['tenant']
         tenant = body
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
 
         t_id = body['id']
         resp1_name = body['name']
@@ -125,7 +132,6 @@
         self.assertEqual(resp2_name, resp3_name)
 
         self.tenants_client.delete_tenant(t_id)
-        self.data.tenants.remove(tenant)
 
     @test.idempotent_id('859fcfe1-3a03-41ef-86f9-b19a47d1cd87')
     def test_tenant_update_desc(self):
@@ -135,7 +141,9 @@
         body = self.tenants_client.create_tenant(name=t_name,
                                                  description=t_desc)
         tenant = body['tenant']
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
 
         t_id = tenant['id']
         resp1_desc = tenant['description']
@@ -154,7 +162,6 @@
         self.assertEqual(resp2_desc, resp3_desc)
 
         self.tenants_client.delete_tenant(t_id)
-        self.data.tenants.remove(tenant)
 
     @test.idempotent_id('8fc8981f-f12d-4c66-9972-2bdcf2bc2e1a')
     def test_tenant_update_enable(self):
@@ -163,7 +170,9 @@
         t_en = False
         body = self.tenants_client.create_tenant(name=t_name, enabled=t_en)
         tenant = body['tenant']
-        self.data.tenants.append(tenant)
+        # Add the tenant to the cleanup list
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.tenants_client.delete_tenant, tenant['id'])
 
         t_id = tenant['id']
         resp1_en = tenant['enabled']
@@ -182,4 +191,3 @@
         self.assertEqual(resp2_en, resp3_en)
 
         self.tenants_client.delete_tenant(t_id)
-        self.data.tenants.remove(tenant)
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index 5cf337b..2f7e941 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -28,13 +28,15 @@
         # first:create a tenant
         tenant_name = data_utils.rand_name(name='tenant')
         tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.data.tenants.append(tenant)
+        # Delete the tenant at the end of the test
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
         # second:create a user
         user = self.users_client.create_user(name=user_name,
                                              password=user_password,
                                              tenantId=tenant['id'],
                                              email='')['user']
-        self.data.users.append(user)
+        # Delete the user at the end of the test
+        self.addCleanup(self.users_client.delete_user, user['id'])
         # then get a token for the user
         body = self.token_client.auth(user_name,
                                       user_password,
@@ -68,23 +70,27 @@
                                              password=user_password,
                                              tenantId=tenant_id,
                                              email=email)['user']
-        self.data.users.append(user)
+        # Delete the user at the end of the test
+        self.addCleanup(self.users_client.delete_user, user['id'])
 
         # Create a couple tenants.
         tenant1_name = data_utils.rand_name(name='tenant')
         tenant1 = self.tenants_client.create_tenant(
             name=tenant1_name)['tenant']
-        self.data.tenants.append(tenant1)
+        # Delete the tenant at the end of the test
+        self.addCleanup(self.tenants_client.delete_tenant, tenant1['id'])
 
         tenant2_name = data_utils.rand_name(name='tenant')
         tenant2 = self.tenants_client.create_tenant(
             name=tenant2_name)['tenant']
-        self.data.tenants.append(tenant2)
+        # Delete the tenant at the end of the test
+        self.addCleanup(self.tenants_client.delete_tenant, tenant2['id'])
 
         # Create a role
         role_name = data_utils.rand_name(name='role')
         role = self.roles_client.create_role(name=role_name)['role']
-        self.data.roles.append(role)
+        # Delete the role at the end of the test
+        self.addCleanup(self.roles_client.delete_role, role['id'])
 
         # Grant the user the role on the tenants.
         self.roles_client.create_user_role_on_project(tenant1['id'],
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 167cbc7..8e63498 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -19,6 +19,7 @@
 
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 from tempest import test
 
 
@@ -35,25 +36,27 @@
     @test.idempotent_id('2d55a71e-da1d-4b43-9c03-d269fd93d905')
     def test_create_user(self):
         # Create a user
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         user = self.users_client.create_user(name=self.alt_user,
                                              password=self.alt_password,
-                                             tenantId=self.data.tenant['id'],
+                                             tenantId=tenant['id'],
                                              email=self.alt_email)['user']
-        self.data.users.append(user)
+        # Delete the User at the end of the test
+        self.addCleanup(self.users_client.delete_user, user['id'])
         self.assertEqual(self.alt_user, user['name'])
 
     @test.idempotent_id('89d9fdb8-15c2-4304-a429-48715d0af33d')
     def test_create_user_with_enabled(self):
         # Create a user with enabled : False
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         name = data_utils.rand_name('test_user')
         user = self.users_client.create_user(name=name,
                                              password=self.alt_password,
-                                             tenantId=self.data.tenant['id'],
+                                             tenantId=tenant['id'],
                                              email=self.alt_email,
                                              enabled=False)['user']
-        self.data.users.append(user)
+        # Delete the User at the end of the test
+        self.addCleanup(self.users_client.delete_user, user['id'])
         self.assertEqual(name, user['name'])
         self.assertEqual(False, user['enabled'])
         self.assertEqual(self.alt_email, user['email'])
@@ -62,10 +65,10 @@
     def test_update_user(self):
         # Test case to check if updating of user attributes is successful.
         test_user = data_utils.rand_name('test_user')
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         user = self.users_client.create_user(name=test_user,
                                              password=self.alt_password,
-                                             tenantId=self.data.tenant['id'],
+                                             tenantId=tenant['id'],
                                              email=self.alt_email)['user']
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user['id'])
@@ -89,76 +92,85 @@
     def test_delete_user(self):
         # Delete a user
         test_user = data_utils.rand_name('test_user')
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         user = self.users_client.create_user(name=test_user,
                                              password=self.alt_password,
-                                             tenantId=self.data.tenant['id'],
+                                             tenantId=tenant['id'],
                                              email=self.alt_email)['user']
+        # Delete the User at the end of the test
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.users_client.delete_user, user['id'])
         self.users_client.delete_user(user['id'])
 
     @test.idempotent_id('aca696c3-d645-4f45-b728-63646045beb1')
     def test_user_authentication(self):
         # Valid user's token is authenticated
-        self.data.setup_test_user()
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
         # Get a token
-        self.token_client.auth(self.data.user['name'],
-                               self.data.user_password,
-                               self.data.tenant['name'])
+        self.token_client.auth(user['name'],
+                               password,
+                               tenant['name'])
         # Re-auth
-        self.token_client.auth(self.data.user['name'],
-                               self.data.user_password,
-                               self.data.tenant['name'])
+        self.token_client.auth(user['name'],
+                               password,
+                               tenant['name'])
 
     @test.idempotent_id('5d1fa498-4c2d-4732-a8fe-2b054598cfdd')
     def test_authentication_request_without_token(self):
         # Request for token authentication with a valid token in header
-        self.data.setup_test_user()
-        self.token_client.auth(self.data.user['name'],
-                               self.data.user_password,
-                               self.data.tenant['name'])
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        self.token_client.auth(user['name'],
+                               password,
+                               tenant['name'])
         # Get the token of the current client
         token = self.client.auth_provider.get_token()
         # Delete the token from database
         self.client.delete_token(token)
         # Re-auth
-        self.token_client.auth(self.data.user['name'],
-                               self.data.user_password,
-                               self.data.tenant['name'])
+        self.token_client.auth(user['name'],
+                               password,
+                               tenant['name'])
         self.client.auth_provider.clear_auth()
 
     @test.idempotent_id('a149c02e-e5e0-4b89-809e-7e8faf33ccda')
     def test_get_users(self):
         # Get a list of users and find the test user
-        self.data.setup_test_user()
+        user = self.setup_test_user()
         users = self.users_client.list_users()['users']
         self.assertThat([u['name'] for u in users],
-                        matchers.Contains(self.data.user['name']),
-                        "Could not find %s" % self.data.user['name'])
+                        matchers.Contains(user['name']),
+                        "Could not find %s" % user['name'])
 
     @test.idempotent_id('6e317209-383a-4bed-9f10-075b7c82c79a')
     def test_list_users_for_tenant(self):
         # Return a list of all users for a tenant
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         user_ids = list()
         fetched_user_ids = list()
         password1 = data_utils.rand_password()
         alt_tenant_user1 = data_utils.rand_name('tenant_user1')
         user1 = self.users_client.create_user(name=alt_tenant_user1,
                                               password=password1,
-                                              tenantId=self.data.tenant['id'],
+                                              tenantId=tenant['id'],
                                               email='user1@123')['user']
         user_ids.append(user1['id'])
-        self.data.users.append(user1)
+        # Delete the User at the end of the test
+        self.addCleanup(self.users_client.delete_user, user1['id'])
         password2 = data_utils.rand_password()
         alt_tenant_user2 = data_utils.rand_name('tenant_user2')
         user2 = self.users_client.create_user(name=alt_tenant_user2,
                                               password=password2,
-                                              tenantId=self.data.tenant['id'],
+                                              tenantId=tenant['id'],
                                               email='user2@123')['user']
         user_ids.append(user2['id'])
-        self.data.users.append(user2)
+        # Delete the User at the end of the test
+        self.addCleanup(self.users_client.delete_user, user2['id'])
         # List of users for the respective tenant ID
-        body = (self.tenants_client.list_tenant_users(self.data.tenant['id'])
+        body = (self.tenants_client.list_tenant_users(tenant['id'])
                 ['users'])
         for i in body:
             fetched_user_ids.append(i['id'])
@@ -172,11 +184,9 @@
     @test.idempotent_id('a8b54974-40e1-41c0-b812-50fc90827971')
     def test_list_users_with_roles_for_tenant(self):
         # Return list of users on tenant when roles are assigned to users
-        self.data.setup_test_user()
-        self.data.setup_test_role()
-        user = self.get_user_by_name(self.data.user['name'])
-        tenant = self.get_tenant_by_name(self.data.tenant['name'])
-        role = self.get_role_by_name(self.data.role['name'])
+        user = self.setup_test_user()
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        role = self.setup_test_role()
         # Assigning roles to two users
         user_ids = list()
         fetched_user_ids = list()
@@ -189,15 +199,15 @@
         second_user = self.users_client.create_user(
             name=alt_user2,
             password=alt_password2,
-            tenantId=self.data.tenant['id'],
+            tenantId=tenant['id'],
             email='user2@123')['user']
         user_ids.append(second_user['id'])
-        self.data.users.append(second_user)
+        # Delete the User at the end of the test
+        self.addCleanup(self.users_client.delete_user, second_user['id'])
         role = self.roles_client.create_user_role_on_project(
             tenant['id'], second_user['id'], role['id'])['role']
         # List of users with roles for the respective tenant ID
-        body = (self.tenants_client.list_tenant_users(self.data.tenant['id'])
-                ['users'])
+        body = (self.tenants_client.list_tenant_users(tenant['id'])['users'])
         for i in body:
             fetched_user_ids.append(i['id'])
         # verifying the user Id in the list
@@ -210,17 +220,18 @@
     @test.idempotent_id('1aeb25ac-6ec5-4d8b-97cb-7ac3567a989f')
     def test_update_user_password(self):
         # Test case to check if updating of user password is successful.
-        self.data.setup_test_user()
+        user = self.setup_test_user()
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
         # Updating the user with new password
         new_pass = data_utils.rand_password()
         update_user = self.users_client.update_user_password(
-            self.data.user['id'], password=new_pass)['user']
-        self.assertEqual(update_user['id'], self.data.user['id'])
+            user['id'], password=new_pass)['user']
+        self.assertEqual(update_user['id'], user['id'])
         # NOTE(morganfainberg): Fernet tokens are not subsecond aware and
         # Keystone should only be precise to the second. Sleep to ensure
         # we are passing the second boundary.
         time.sleep(1)
         # Validate the updated password through getting a token.
-        body = self.token_client.auth(self.data.user['name'], new_pass,
-                                      self.data.tenant['name'])
+        body = self.token_client.auth(user['name'], new_pass,
+                                      tenant['name'])
         self.assertTrue('id' in body['token'])
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index 78b89fa..597413e 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -32,43 +32,45 @@
     @test.idempotent_id('60a1f5fa-5744-4cdf-82bf-60b7de2d29a4')
     def test_create_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to create a user
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.create_user,
                           name=self.alt_user, password=self.alt_password,
-                          tenantId=self.data.tenant['id'],
+                          tenantId=tenant['id'],
                           email=self.alt_email)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('d80d0c2f-4514-4d1e-806d-0930dfc5a187')
     def test_create_user_with_empty_name(self):
         # User with an empty name should not be created
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
                           name='', password=self.alt_password,
-                          tenantId=self.data.tenant['id'],
+                          tenantId=tenant['id'],
                           email=self.alt_email)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('7704b4f3-3b75-4b82-87cc-931d41c8f780')
     def test_create_user_with_name_length_over_255(self):
         # Length of user name filed should be restricted to 255 characters
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
                           name='a' * 256, password=self.alt_password,
-                          tenantId=self.data.tenant['id'],
+                          tenantId=tenant['id'],
                           email=self.alt_email)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('57ae8558-120c-4723-9308-3751474e7ecf')
     def test_create_user_with_duplicate_name(self):
         # Duplicate user should not be created
-        self.data.setup_test_user()
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
         self.assertRaises(lib_exc.Conflict, self.users_client.create_user,
-                          name=self.data.user['name'],
-                          password=self.data.user_password,
-                          tenantId=self.data.tenant['id'],
-                          email=self.data.user['email'])
+                          name=user['name'],
+                          password=password,
+                          tenantId=tenant['id'],
+                          email=user['email'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
@@ -84,7 +86,7 @@
     @test.idempotent_id('55bbb103-d1ae-437b-989b-bcdf8175c1f4')
     def test_create_user_request_without_a_token(self):
         # Request to create a user without a valid token should fail
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         # Get the token of the current client
         token = self.client.auth_provider.get_token()
         # Delete the token from database
@@ -95,18 +97,18 @@
 
         self.assertRaises(lib_exc.Unauthorized, self.users_client.create_user,
                           name=self.alt_user, password=self.alt_password,
-                          tenantId=self.data.tenant['id'],
+                          tenantId=tenant['id'],
                           email=self.alt_email)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('23a2f3da-4a1a-41da-abdd-632328a861ad')
     def test_create_user_with_enabled_non_bool(self):
         # Attempt to create a user with valid enabled para should fail
-        self.data.setup_test_tenant()
+        tenant = self.setup_test_tenant()
         name = data_utils.rand_name('test_user')
         self.assertRaises(lib_exc.BadRequest, self.users_client.create_user,
                           name=name, password=self.alt_password,
-                          tenantId=self.data.tenant['id'],
+                          tenantId=tenant['id'],
                           email=self.alt_email, enabled=3)
 
     @test.attr(type=['negative'])
@@ -138,7 +140,6 @@
     @test.idempotent_id('424868d5-18a7-43e1-8903-a64f95ee3aac')
     def test_update_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to update user
-        self.data.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.update_user,
                           self.alt_user)
@@ -147,10 +148,10 @@
     @test.idempotent_id('d45195d5-33ed-41b9-a452-7d0d6a00f6e9')
     def test_delete_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to delete a user
-        self.data.setup_test_user()
+        user = self.setup_test_user()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.delete_user,
-                          self.data.user['id'])
+                          user['id'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('7cc82f7e-9998-4f89-abae-23df36495867')
@@ -179,57 +180,62 @@
     @test.idempotent_id('593a4981-f6d4-460a-99a1-57a78bf20829')
     def test_authentication_for_disabled_user(self):
         # Disabled user's token should not get authenticated
-        self.data.setup_test_user()
-        self.disable_user(self.data.user['name'])
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        self.disable_user(user['name'])
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.user['name'],
-                          self.data.user_password,
-                          self.data.tenant['name'])
+                          user['name'],
+                          password,
+                          tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('440a7a8d-9328-4b7b-83e0-d717010495e4')
     def test_authentication_when_tenant_is_disabled(self):
         # User's token for a disabled tenant should not be authenticated
-        self.data.setup_test_user()
-        self.disable_tenant(self.data.tenant['name'])
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
+        self.disable_tenant(tenant['name'])
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.user['name'],
-                          self.data.user_password,
-                          self.data.tenant['name'])
+                          user['name'],
+                          password,
+                          tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('921f1ad6-7907-40b8-853f-637e7ee52178')
     def test_authentication_with_invalid_tenant(self):
         # User's token for an invalid tenant should not be authenticated
-        self.data.setup_test_user()
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.user['name'],
-                          self.data.user_password,
+                          user['name'],
+                          password,
                           'junktenant1234')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('bde9aecd-3b1c-4079-858f-beb5deaa5b5e')
     def test_authentication_with_invalid_username(self):
         # Non-existent user's token should not get authenticated
-        self.data.setup_test_user()
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          'junkuser123', self.data.user_password,
-                          self.data.tenant['name'])
+                          'junkuser123', password, tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('d5308b33-3574-43c3-8d87-1c090c5e1eca')
     def test_authentication_with_invalid_password(self):
         # User's token with invalid password should not be authenticated
-        self.data.setup_test_user()
+        user = self.setup_test_user()
+        tenant = self.tenants_client.show_tenant(user['tenantId'])['tenant']
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
-                          self.data.user['name'], 'junkpass1234',
-                          self.data.tenant['name'])
+                          user['name'], 'junkpass1234', tenant['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('284192ce-fb7c-4909-a63b-9a502e0ddd11')
     def test_get_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to get user list
-        self.data.setup_test_user()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.list_users)
 
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 a3ada21..48e5f02 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -23,14 +23,21 @@
     @classmethod
     def resource_setup(cls):
         super(GroupsV3TestJSON, cls).resource_setup()
-        cls.data.setup_test_domain()
+        cls.domain = cls.create_domain()
+
+    @classmethod
+    def resource_cleanup(cls):
+        # Cleanup the domains created in the setup
+        cls.domains_client.update_domain(cls.domain['id'], enabled=False)
+        cls.domains_client.delete_domain(cls.domain['id'])
+        super(GroupsV3TestJSON, cls).resource_cleanup()
 
     @test.idempotent_id('2e80343b-6c81-4ac3-88c7-452f3e9d5129')
     def test_group_create_update_get(self):
         name = data_utils.rand_name('Group')
         description = data_utils.rand_name('Description')
         group = self.groups_client.create_group(
-            name=name, domain_id=self.data.domain['id'],
+            name=name, domain_id=self.domain['id'],
             description=description)['group']
         self.addCleanup(self.groups_client.delete_group, group['id'])
         self.assertEqual(group['name'], name)
@@ -53,7 +60,7 @@
         name = data_utils.rand_name('Group')
         old_description = data_utils.rand_name('Description')
         group = self.groups_client.create_group(
-            name=name, domain_id=self.data.domain['id'],
+            name=name, domain_id=self.domain['id'],
             description=old_description)['group']
         self.addCleanup(self.groups_client.delete_group, group['id'])
 
@@ -69,14 +76,15 @@
     def test_group_users_add_list_delete(self):
         name = data_utils.rand_name('Group')
         group = self.groups_client.create_group(
-            name=name, domain_id=self.data.domain['id'])['group']
+            name=name, domain_id=self.domain['id'])['group']
         self.addCleanup(self.groups_client.delete_group, group['id'])
         # add user into group
         users = []
         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'])
@@ -96,14 +104,15 @@
     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 = []
         for i in range(2):
             name = data_utils.rand_name('Group')
             group = self.groups_client.create_group(
-                name=name, domain_id=self.data.domain['id'])['group']
+                name=name, domain_id=self.domain['id'])['group']
             groups.append(group)
             self.addCleanup(self.groups_client.delete_group, group['id'])
             self.groups_client.add_group_user(group['id'], user['id'])
@@ -121,7 +130,7 @@
             name = data_utils.rand_name('Group')
             description = data_utils.rand_name('Description')
             group = self.groups_client.create_group(
-                name=name, domain_id=self.data.domain['id'],
+                name=name, domain_id=self.domain['id'],
                 description=description)['group']
             self.addCleanup(self.groups_client.delete_group, group['id'])
             group_ids.append(group['id'])
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_projects.py b/tempest/api/identity/admin/v3/test_list_projects.py
index 86f6b12..7d9e41b 100644
--- a/tempest/api/identity/admin/v3/test_list_projects.py
+++ b/tempest/api/identity/admin/v3/test_list_projects.py
@@ -24,26 +24,38 @@
     def resource_setup(cls):
         super(ListProjectsTestJSON, cls).resource_setup()
         cls.project_ids = list()
-        cls.data.setup_test_domain()
+        # Create a domain
+        cls.domain = cls.create_domain()
         # Create project with domain
+        cls.projects = list()
         cls.p1_name = data_utils.rand_name('project')
         cls.p1 = cls.projects_client.create_project(
             cls.p1_name, enabled=False,
-            domain_id=cls.data.domain['id'])['project']
-        cls.data.projects.append(cls.p1)
+            domain_id=cls.domain['id'])['project']
+        cls.projects.append(cls.p1)
         cls.project_ids.append(cls.p1['id'])
         # Create default project
         p2_name = data_utils.rand_name('project')
         cls.p2 = cls.projects_client.create_project(p2_name)['project']
-        cls.data.projects.append(cls.p2)
+        cls.projects.append(cls.p2)
         cls.project_ids.append(cls.p2['id'])
         # Create a new project (p3) using p2 as parent project
         p3_name = data_utils.rand_name('project')
         cls.p3 = cls.projects_client.create_project(
             p3_name, parent_id=cls.p2['id'])['project']
-        cls.data.projects.append(cls.p3)
+        cls.projects.append(cls.p3)
         cls.project_ids.append(cls.p3['id'])
 
+    @classmethod
+    def resource_cleanup(cls):
+        # Cleanup the projects created during setup in inverse order
+        for project in reversed(cls.projects):
+            cls.projects_client.delete_project(project['id'])
+        # Cleanup the domain created during setup
+        cls.domains_client.update_domain(cls.domain['id'], enabled=False)
+        cls.domains_client.delete_domain(cls.domain['id'])
+        super(ListProjectsTestJSON, cls).resource_cleanup()
+
     @test.idempotent_id('1d830662-22ad-427c-8c3e-4ec854b0af44')
     def test_list_projects(self):
         # List projects
@@ -57,7 +69,7 @@
     def test_list_projects_with_domains(self):
         # List projects with domain
         self._list_projects_with_params(
-            {'domain_id': self.data.domain['id']}, 'domain_id')
+            {'domain_id': self.domain['id']}, 'domain_id')
 
     @test.idempotent_id('0fe7a334-675a-4509-b00e-1c4b95d5dae8')
     def test_list_projects_with_enabled(self):
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index 5b27ab1..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))
@@ -36,24 +36,36 @@
         alt_user = data_utils.rand_name('test_user')
         alt_password = data_utils.rand_password()
         cls.alt_email = alt_user + '@testmail.tm'
-        cls.data.setup_test_domain()
+        # Create a domain
+        cls.domain = cls.create_domain()
         # Create user with Domain
+        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,
-            email=cls.alt_email, domain_id=cls.data.domain['id'])['user']
-        cls.data.users.append(cls.domain_enabled_user)
+            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.data.users.append(cls.non_domain_enabled_user)
+        cls.users.append(cls.non_domain_enabled_user)
+
+    @classmethod
+    def resource_cleanup(cls):
+        # Cleanup the users created during setup
+        for user in cls.users:
+            cls.users_client.delete_user(user['id'])
+        # Cleanup the domain created during setup
+        cls.domains_client.update_domain(cls.domain['id'], enabled=False)
+        cls.domains_client.delete_domain(cls.domain['id'])
+        super(UsersV3TestJSON, cls).resource_cleanup()
 
     @test.idempotent_id('08f9aabb-dcfe-41d0-8172-82b5fa0bd73d')
     def test_list_user_domains(self):
         # List users with domain
-        params = {'domain_id': self.data.domain['id']}
+        params = {'domain_id': self.domain['id']}
         self._list_users_with_params(params, 'domain_id',
                                      self.domain_enabled_user,
                                      self.non_domain_enabled_user)
@@ -79,7 +91,7 @@
         # List users
         body = self.users_client.list_users()['users']
         fetched_ids = [u['id'] for u in body]
-        missing_users = [u['id'] for u in self.data.users
+        missing_users = [u['id'] for u in self.users
                          if u['id'] not in fetched_ids]
         self.assertEqual(0, len(missing_users),
                          "Failed to find user %s in fetched list" %
@@ -88,8 +100,8 @@
     @test.idempotent_id('b4baa3ae-ac00-4b4e-9e27-80deaad7771f')
     def test_get_user(self):
         # Get a user detail
-        user = self.users_client.show_user(self.data.users[0]['id'])['user']
-        self.assertEqual(self.data.users[0]['id'], user['id'])
-        self.assertEqual(self.data.users[0]['name'], user['name'])
+        user = self.users_client.show_user(self.users[0]['id'])['user']
+        self.assertEqual(self.users[0]['id'], user['id'])
+        self.assertEqual(self.users[0]['name'], user['name'])
         self.assertEqual(self.alt_email, user['email'])
-        self.assertEqual(self.data.domain['id'], user['domain_id'])
+        self.assertEqual(self.domain['id'], user['domain_id'])
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index bee77df..1137191 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack, LLC
+# Copyright 2013 OpenStack Foundation
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -32,7 +32,7 @@
         project_desc = data_utils.rand_name('desc')
         project = self.projects_client.create_project(
             project_name, description=project_desc)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         project_id = project['id']
         desc1 = project['description']
         self.assertEqual(desc1, project_desc, 'Description should have '
@@ -45,25 +45,25 @@
     @test.idempotent_id('5f50fe07-8166-430b-a882-3b2ee0abe26f')
     def test_project_create_with_domain(self):
         # Create project with a domain
-        self.data.setup_test_domain()
+        domain = self.setup_test_domain()
         project_name = data_utils.rand_name('project')
         project = self.projects_client.create_project(
-            project_name, domain_id=self.data.domain['id'])['project']
-        self.data.projects.append(project)
+            project_name, domain_id=domain['id'])['project']
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         project_id = project['id']
         self.assertEqual(project_name, project['name'])
-        self.assertEqual(self.data.domain['id'], project['domain_id'])
+        self.assertEqual(domain['id'], project['domain_id'])
         body = self.projects_client.show_project(project_id)['project']
         self.assertEqual(project_name, body['name'])
-        self.assertEqual(self.data.domain['id'], body['domain_id'])
+        self.assertEqual(domain['id'], body['domain_id'])
 
     @testtools.skipUnless(CONF.identity_feature_enabled.reseller,
                           'Reseller not available.')
     @test.idempotent_id('1854f9c0-70bc-4d11-a08a-1c789d339e3d')
     def test_project_create_with_parent(self):
         # Create root project without providing a parent_id
-        self.data.setup_test_domain()
-        domain_id = self.data.domain['id']
+        domain = self.setup_test_domain()
+        domain_id = domain['id']
 
         root_project_name = data_utils.rand_name('root_project')
         root_project = self.projects_client.create_project(
@@ -94,7 +94,7 @@
         project_name = data_utils.rand_name('project')
         project = self.projects_client.create_project(
             project_name, enabled=True)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         project_id = project['id']
         en1 = project['enabled']
         self.assertTrue(en1, 'Enable should be True in response')
@@ -108,7 +108,7 @@
         project_name = data_utils.rand_name('project')
         project = self.projects_client.create_project(
             project_name, enabled=False)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         en1 = project['enabled']
         self.assertEqual('false', str(en1).lower(),
                          'Enable should be False in response')
@@ -122,7 +122,7 @@
         # Update name attribute of a project
         p_name1 = data_utils.rand_name('project')
         project = self.projects_client.create_project(p_name1)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
 
         resp1_name = project['name']
 
@@ -146,7 +146,7 @@
         p_desc = data_utils.rand_name('desc')
         project = self.projects_client.create_project(
             p_name, description=p_desc)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         resp1_desc = project['description']
 
         p_desc2 = data_utils.rand_name('desc2')
@@ -169,7 +169,7 @@
         p_en = False
         project = self.projects_client.create_project(p_name,
                                                       enabled=p_en)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
 
         resp1_en = project['enabled']
 
@@ -192,7 +192,7 @@
         # Create a Project
         p_name = data_utils.rand_name('project')
         project = self.projects_client.create_project(p_name)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
 
         # Create a User
         u_name = data_utils.rand_name('user')
@@ -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_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index fb4a8cf..c76b9ee 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack, LLC
+# Copyright 2013 OpenStack Foundation
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -34,7 +34,7 @@
         # Project names should be unique
         project_name = data_utils.rand_name('project-dup')
         project = self.projects_client.create_project(project_name)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
 
         self.assertRaises(lib_exc.Conflict,
                           self.projects_client.create_project, project_name)
@@ -69,7 +69,7 @@
         # Non-admin user should not be able to delete a project
         project_name = data_utils.rand_name('project')
         project = self.projects_client.create_project(project_name)['project']
-        self.data.projects.append(project)
+        self.addCleanup(self.projects_client.delete_project, project['id'])
         self.assertRaises(
             lib_exc.Forbidden, self.non_admin_projects_client.delete_project,
             project['id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 12ef369..4ecf0a5 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -23,10 +23,11 @@
     @classmethod
     def resource_setup(cls):
         super(RolesV3TestJSON, cls).resource_setup()
+        cls.roles = list()
         for _ in range(3):
             role_name = data_utils.rand_name(name='role')
             role = cls.roles_client.create_role(name=role_name)['role']
-            cls.data.roles.append(role)
+            cls.roles.append(role)
         cls.fetched_role_ids = list()
         u_name = data_utils.rand_name('user')
         u_desc = '%s description' % u_name
@@ -43,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(
@@ -59,6 +60,8 @@
         # before deleting,or else it would result in unauthorized error
         cls.domains_client.update_domain(cls.domain['id'], enabled=False)
         cls.domains_client.delete_domain(cls.domain['id'])
+        for role in cls.roles:
+            cls.roles_client.delete_role(role['id'])
         super(RolesV3TestJSON, cls).resource_cleanup()
 
     def _list_assertions(self, body, fetched_role_ids, role_id):
@@ -189,5 +192,5 @@
     def test_list_roles(self):
         # Return a list of all roles
         body = self.roles_client.list_roles()['roles']
-        found = [role for role in body if role in self.data.roles]
-        self.assertEqual(len(found), len(self.data.roles))
+        found = [role for role in body if role in self.roles]
+        self.assertEqual(len(found), len(self.roles))
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 371da9c..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'])
@@ -149,6 +149,6 @@
     @test.idempotent_id('c10dcd90-461d-4b16-8e23-4eb836c00644')
     def test_get_user(self):
         # Get a user detail
-        self.data.setup_test_user()
-        user = self.users_client.show_user(self.data.user['id'])['user']
-        self.assertEqual(self.data.user['id'], user['id'])
+        user = self.setup_test_user()
+        fetched_user = self.users_client.show_user(user['id'])['user']
+        self.assertEqual(user['id'], fetched_user['id'])
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 1375db1..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())
 
@@ -37,9 +37,10 @@
     @test.idempotent_id('b3c9fccc-4134-46f5-b600-1da6fb0a3b1f')
     def test_authentication_for_disabled_user(self):
         # Attempt to authenticate for disabled user should fail
-        self.data.setup_test_user()
-        self.disable_user(self.data.user['name'], self.data.user['domain_id'])
+        password = data_utils.rand_password()
+        user = self.setup_test_user(password)
+        self.disable_user(user['name'], user['domain_id'])
         self.assertRaises(lib_exc.Unauthorized, self.token.auth,
-                          username=self.data.user['name'],
-                          password=self.data.user_password,
+                          username=user['name'],
+                          password=password,
                           user_domain_id='default')
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index df39390..deb5413 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -13,15 +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
-from tempest.lib.common.utils import test_utils
 import tempest.test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class BaseIdentityTest(tempest.test.BaseTestCase):
@@ -40,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]
@@ -64,6 +60,23 @@
         if len(role) > 0:
             return role[0]
 
+    def _create_test_user(self, **kwargs):
+        if kwargs['password'] is None:
+            user_password = data_utils.rand_password()
+            kwargs['password'] = user_password
+        user = self.users_client.create_user(**kwargs)['user']
+        # Delete the user at the end of the test
+        self.addCleanup(self.users_client.delete_user, user['id'])
+        return user
+
+    def setup_test_role(self):
+        """Set up a test role."""
+        role = self.roles_client.create_role(
+            name=data_utils.rand_name('test_role'))['role']
+        # Delete the role at the end of the test
+        self.addCleanup(self.roles_client.delete_role, role['id'])
+        return role
+
 
 class BaseIdentityV2Test(BaseIdentityTest):
 
@@ -104,14 +117,30 @@
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityV2AdminTest, cls).resource_setup()
-        cls.data = DataGeneratorV2(cls.tenants_client, cls.users_client,
-                                   cls.roles_client)
+        cls.projects_client = cls.tenants_client
 
     @classmethod
     def resource_cleanup(cls):
-        cls.data.teardown_all()
         super(BaseIdentityV2AdminTest, cls).resource_cleanup()
 
+    def setup_test_user(self, password=None):
+        """Set up a test user."""
+        tenant = self.setup_test_tenant()
+        username = data_utils.rand_name('test_user')
+        email = username + '@testmail.tm'
+        user = self._create_test_user(name=username, email=email,
+                                      tenantId=tenant['id'], password=password)
+        return user
+
+    def setup_test_tenant(self):
+        """Set up a test tenant."""
+        tenant = self.projects_client.create_tenant(
+            name=data_utils.rand_name('test_tenant'),
+            description=data_utils.rand_name('desc'))['tenant']
+        # Delete the tenant at the end of the test
+        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        return tenant
+
 
 class BaseIdentityV3Test(BaseIdentityTest):
 
@@ -160,18 +189,23 @@
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityV3AdminTest, cls).resource_setup()
-        cls.data = DataGeneratorV3(cls.projects_client, cls.users_client,
-                                   cls.roles_client, cls.domains_client)
 
     @classmethod
     def resource_cleanup(cls):
-        cls.data.teardown_all()
         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):
+        """Create a domain."""
+        domain = cls.domains_client.create_domain(
+            name=data_utils.rand_name('test_domain'),
+            description=data_utils.rand_name('desc'))['domain']
+        return domain
 
     def delete_domain(self, domain_id):
         # NOTE(mpavlase) It is necessary to disable the domain before deleting
@@ -179,100 +213,28 @@
         self.domains_client.update_domain(domain_id, enabled=False)
         self.domains_client.delete_domain(domain_id)
 
-
-class BaseDataGenerator(object):
-
-    def __init__(self, projects_client, users_client, roles_client,
-                 domains_client=None):
-        self.projects_client = projects_client
-        self.users_client = users_client
-        self.roles_client = roles_client
-        self.domains_client = domains_client
-
-        self.user_password = None
-        self.user = None
-        self.tenant = None
-        self.project = None
-        self.role = None
-        self.domain = None
-
-        self.users = []
-        self.tenants = []
-        self.projects = []
-        self.roles = []
-        self.domains = []
-
-    def _create_test_user(self, **kwargs):
-        self.user_password = data_utils.rand_password()
-        self.user = self.users_client.create_user(
-            password=self.user_password,
-            **kwargs)['user']
-        self.users.append(self.user)
-
-    def setup_test_role(self):
-        """Set up a test role."""
-        self.role = self.roles_client.create_role(
-            name=data_utils.rand_name('test_role'))['role']
-        self.roles.append(self.role)
-
-    def teardown_all(self):
-        for user in self.users:
-            test_utils.call_and_ignore_notfound_exc(
-                self.users_client.delete_user, user['id'])
-        for tenant in self.tenants:
-            test_utils.call_and_ignore_notfound_exc(
-                self.projects_client.delete_tenant, tenant['id'])
-        for project in reversed(self.projects):
-            test_utils.call_and_ignore_notfound_exc(
-                self.projects_client.delete_project, project['id'])
-        for role in self.roles:
-            test_utils.call_and_ignore_notfound_exc(
-                self.roles_client.delete_role, role['id'])
-        for domain in self.domains:
-            test_utils.call_and_ignore_notfound_exc(
-                self.domains_client.update_domain, domain['id'], enabled=False)
-            test_utils.call_and_ignore_notfound_exc(
-                self.domains_client.delete_domain, domain['id'])
-
-
-class DataGeneratorV2(BaseDataGenerator):
-
-    def setup_test_user(self):
+    def setup_test_user(self, password=None):
         """Set up a test user."""
-        self.setup_test_tenant()
+        project = self.setup_test_project()
         username = data_utils.rand_name('test_user')
         email = username + '@testmail.tm'
-        self._create_test_user(name=username, email=email,
-                               tenantId=self.tenant['id'])
-
-    def setup_test_tenant(self):
-        """Set up a test tenant."""
-        self.tenant = self.projects_client.create_tenant(
-            name=data_utils.rand_name('test_tenant'),
-            description=data_utils.rand_name('desc'))['tenant']
-        self.tenants.append(self.tenant)
-
-
-class DataGeneratorV3(BaseDataGenerator):
-
-    def setup_test_user(self):
-        """Set up a test user."""
-        self.setup_test_project()
-        username = data_utils.rand_name('test_user')
-        email = username + '@testmail.tm'
-        self._create_test_user(user_name=username, email=email,
-                               project_id=self.project['id'])
+        user = self._create_test_user(name=username, email=email,
+                                      project_id=project['id'],
+                                      password=password)
+        return user
 
     def setup_test_project(self):
         """Set up a test project."""
-        self.project = self.projects_client.create_project(
+        project = self.projects_client.create_project(
             name=data_utils.rand_name('test_project'),
             description=data_utils.rand_name('desc'))['project']
-        self.projects.append(self.project)
+        # Delete the project at the end of the test
+        self.addCleanup(self.projects_client.delete_project, project['id'])
+        return project
 
     def setup_test_domain(self):
         """Set up a test domain."""
-        self.domain = self.domains_client.create_domain(
-            name=data_utils.rand_name('test_domain'),
-            description=data_utils.rand_name('desc'))['domain']
-        self.domains.append(self.domain)
+        domain = self.create_domain()
+        # Delete the domain at the end of the test
+        self.addCleanup(self.delete_domain, domain['id'])
+        return domain
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 3c379f0..8f493aa 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -51,7 +51,6 @@
     def test_list_ec2_credentials(self):
         """Get the list of user ec2 credentials."""
         created_creds = []
-        fetched_creds = []
         # create first ec2 credentials
         creds1 = self.non_admin_users_client.create_user_ec2_credential(
             self.creds.user_id,
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_image_members.py b/tempest/api/image/v1/test_image_members.py
index 94edb6c..50f0926 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -25,7 +25,7 @@
         self.image_member_client.create_image_member(image, self.alt_tenant_id)
         body = self.image_member_client.list_image_members(image)
         members = body['members']
-        members = map(lambda x: x['member_id'], members)
+        members = [member['member_id'] for member in members]
         self.assertIn(self.alt_tenant_id, members)
         # get image as alt user
         self.alt_img_cli.show_image(image)
@@ -40,7 +40,7 @@
         body = self.image_member_client.list_shared_images(
             self.alt_tenant_id)
         images = body['shared_images']
-        images = map(lambda x: x['image_id'], images)
+        images = [img['image_id'] for img in images]
         self.assertIn(share_image, images)
         self.assertIn(image, images)
 
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index def7750..694408d 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -212,7 +212,7 @@
     def test_index_no_params(self):
         # Simple test to see all fixture images returned
         images_list = self.client.list_images()['images']
-        image_list = map(lambda x: x['id'], images_list)
+        image_list = [image['id'] for image in images_list]
         for image_id in self.created_images:
             self.assertIn(image_id, image_list)
 
@@ -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.py b/tempest/api/image/v2/test_images.py
index 1fb9c52..42a4352 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -185,7 +185,7 @@
     def test_list_no_params(self):
         # Simple test to see all fixture images returned
         images_list = self.client.list_images()['images']
-        image_list = map(lambda x: x['id'], images_list)
+        image_list = [image['id'] for image in images_list]
 
         for image in self.created_images:
             self.assertIn(image, image_list)
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/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 14de8fd..f60fb0c 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -29,7 +29,7 @@
         ** get image with image_id=NULL
         ** get the deleted image
         ** delete non-existent image
-        ** delete rimage with  image_id=NULL
+        ** delete image with image_id=NULL
         ** delete the deleted image
      """
 
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/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 2abbf93..c64b01e 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -54,7 +54,7 @@
 
         # Create network, subnet, router and add interface
         cls.network = cls.create_network()
-        cls.subnet = cls.create_subnet(cls.network)
+        cls.subnet = cls.create_subnet(cls.network, enable_dhcp=False)
         cls.router = cls.create_router(data_utils.rand_name('router-'),
                                        external_network_id=cls.ext_net_id)
         cls.create_router_interface(cls.router['id'], cls.subnet['id'])
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index bf80ff5..3825f84 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -127,7 +127,7 @@
     def _get_allocation_pools_from_gateway(cls, ip_version):
         """Return allocation range for subnet of given gateway"""
         gateway = cls._get_gateway_from_tempest_conf(ip_version)
-        return [{'start': str(gateway + 2), 'end': str(gateway + 3)}]
+        return [{'start': str(gateway + 2), 'end': str(gateway + 6)}]
 
     def subnet_dict(self, include_keys):
         # Return a subnet dict which has include_keys and their corresponding
@@ -559,7 +559,7 @@
         # Verifies Subnet GW is set in IPv6
         self.assertEqual(subnet1['gateway_ip'], ipv6_gateway)
         # Verifies Subnet GW is None in IPv4
-        self.assertEqual(subnet2['gateway_ip'], None)
+        self.assertIsNone(subnet2['gateway_ip'])
         # Verifies all 2 subnets in the same network
         body = self.subnets_client.list_subnets()
         subnets = [sub['id'] for sub in body['subnets']
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 97d9eed..85026af 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -15,6 +15,7 @@
 
 from tempest.common import custom_matchers
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
@@ -57,16 +58,41 @@
         cls.container_client.auth_provider.clear_auth()
         cls.account_client.auth_provider.clear_auth()
 
+        cls.containers = []
+
     @classmethod
-    def delete_containers(cls, containers, container_client=None,
+    def create_container(cls):
+        # wrapper that returns a test container
+        container_name = data_utils.rand_name(name='TestContainer')
+        cls.container_client.create_container(container_name)
+        cls.containers.append(container_name)
+
+        return container_name
+
+    @classmethod
+    def create_object(cls, container_name, object_name=None,
+                      data=None, metadata=None):
+        # wrapper that returns a test object
+        if object_name is None:
+            object_name = data_utils.rand_name(name='TestObject')
+        if data is None:
+            data = data_utils.arbitrary_string()
+        cls.object_client.create_object(container_name,
+                                        object_name,
+                                        data,
+                                        metadata=metadata)
+
+        return object_name, data
+
+    @classmethod
+    def delete_containers(cls, container_client=None,
                           object_client=None):
-        """Remove given containers and all objects in them.
+        """Remove containers and all objects in them.
 
         The containers should be visible from the container_client given.
         Will not throw any error if the containers don't exist.
         Will not check that object and container deletions succeed.
 
-        :param containers: list of container names to remove
         :param container_client: if None, use cls.container_client, this means
             that the default testing user will be used (see 'username' in
             'etc/tempest.conf')
@@ -76,7 +102,7 @@
             container_client = cls.container_client
         if object_client is None:
             object_client = cls.object_client
-        for cont in containers:
+        for cont in cls.containers:
             try:
                 objlist = container_client.list_all_container_objects(cont)
                 # delete every object in the container
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index da4c80c..7292ee9 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -27,7 +27,7 @@
         self.containers = []
 
     def tearDown(self):
-        self.delete_containers(self.containers)
+        self.delete_containers()
         super(BulkTest, self).tearDown()
 
     def _create_archive(self):
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 0f6a330..fcbd6eb 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -34,8 +34,7 @@
     @classmethod
     def resource_setup(cls):
         super(AccountQuotasTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name="TestContainer")
-        cls.container_client.create_container(cls.container_name)
+        cls.container_name = cls.create_container()
 
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
@@ -73,8 +72,7 @@
 
     @classmethod
     def resource_cleanup(cls):
-        if hasattr(cls, "container_name"):
-            cls.delete_containers([cls.container_name])
+        cls.delete_containers()
         super(AccountQuotasTest, cls).resource_cleanup()
 
     @test.attr(type="smoke")
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 546bb06..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
 
@@ -36,8 +34,7 @@
     @classmethod
     def resource_setup(cls):
         super(AccountQuotasNegativeTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name="TestContainer")
-        cls.container_client.create_container(cls.container_name)
+        cls.container_name = cls.create_container()
 
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
@@ -74,8 +71,7 @@
 
     @classmethod
     def resource_cleanup(cls):
-        if hasattr(cls, "container_name"):
-            cls.delete_containers([cls.container_name])
+        cls.delete_containers()
         super(AccountQuotasNegativeTest, cls).resource_cleanup()
 
     @test.attr(type=["negative"])
@@ -93,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_account_services.py b/tempest/api/object_storage/test_account_services.py
index 5983c1f..723b870 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -50,7 +50,7 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
         super(AccountTest, cls).resource_cleanup()
 
     @test.attr(type='smoke')
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index c1b6711..ffdd1de 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -39,11 +39,10 @@
 
     def setUp(self):
         super(ObjectTestACLs, self).setUp()
-        self.container_name = data_utils.rand_name(name='TestContainer')
-        self.container_client.create_container(self.container_name)
+        self.container_name = self.create_container()
 
     def tearDown(self):
-        self.delete_containers([self.container_name])
+        self.delete_containers()
         super(ObjectTestACLs, self).tearDown()
 
     @test.idempotent_id('a3270f3f-7640-4944-8448-c7ea783ea5b6')
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 01e5389..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
 
@@ -38,8 +36,7 @@
                      Maximum object count of the container.
         """
         super(ContainerQuotasTest, self).setUp()
-        self.container_name = data_utils.rand_name(name="TestContainer")
-        self.container_client.create_container(self.container_name)
+        self.container_name = self.create_container()
         metadata = {"quota-bytes": str(QUOTA_BYTES),
                     "quota-count": str(QUOTA_COUNT), }
         self.container_client.update_container_metadata(
@@ -47,7 +44,7 @@
 
     def tearDown(self):
         """Cleans the container of any object after each test."""
-        self.delete_containers([self.container_name])
+        self.delete_containers()
         super(ContainerQuotasTest, self).tearDown()
 
     @test.idempotent_id('9a0fb034-86af-4df0-86fa-f8bd7db21ae0')
@@ -71,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 9d043e5..8522269 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -19,33 +19,10 @@
 
 
 class ContainerTest(base.BaseObjectTest):
-    def setUp(self):
-        super(ContainerTest, self).setUp()
-        self.containers = []
-
     def tearDown(self):
-        self.delete_containers(self.containers)
+        self.delete_containers()
         super(ContainerTest, self).tearDown()
 
-    def _create_container(self):
-        # setup container
-        container_name = data_utils.rand_name(name='TestContainer')
-        self.container_client.create_container(container_name)
-        self.containers.append(container_name)
-
-        return container_name
-
-    def _create_object(self, container_name, object_name=None):
-        # setup object
-        if object_name is None:
-            object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
-        self.object_client.create_object(container_name,
-                                         object_name,
-                                         data)
-
-        return object_name
-
     @test.attr(type='smoke')
     @test.idempotent_id('92139d73-7819-4db1-85f8-3f2f22a8d91f')
     def test_create_container(self):
@@ -140,18 +117,17 @@
     @test.idempotent_id('95d3a249-b702-4082-a2c4-14bb860cf06a')
     def test_delete_container(self):
         # create a container
-        container_name = self._create_container()
+        container_name = self.create_container()
         # 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')
     def test_list_container_contents(self):
         # get container contents list
-        container_name = self._create_container()
-        object_name = self._create_object(container_name)
+        container_name = self.create_container()
+        object_name, _ = self.create_object(container_name)
 
         resp, object_list = self.container_client.list_container_contents(
             container_name)
@@ -161,7 +137,7 @@
     @test.idempotent_id('4646ac2d-9bfb-4c7d-a3c5-0f527402b3df')
     def test_list_container_contents_with_no_object(self):
         # get empty container contents list
-        container_name = self._create_container()
+        container_name = self.create_container()
 
         resp, object_list = self.container_client.list_container_contents(
             container_name)
@@ -171,9 +147,9 @@
     @test.idempotent_id('fe323a32-57b9-4704-a996-2e68f83b09bc')
     def test_list_container_contents_with_delimiter(self):
         # get container contents list using delimiter param
-        container_name = self._create_container()
+        container_name = self.create_container()
         object_name = data_utils.rand_name(name='TestObject/')
-        self._create_object(container_name, object_name)
+        self.create_object(container_name, object_name)
 
         params = {'delimiter': '/'}
         resp, object_list = self.container_client.list_container_contents(
@@ -185,8 +161,8 @@
     @test.idempotent_id('55b4fa5c-e12e-4ca9-8fcf-a79afe118522')
     def test_list_container_contents_with_end_marker(self):
         # get container contents list using end_marker param
-        container_name = self._create_container()
-        object_name = self._create_object(container_name)
+        container_name = self.create_container()
+        object_name, _ = self.create_object(container_name)
 
         params = {'end_marker': 'ZzzzObject1234567890'}
         resp, object_list = self.container_client.list_container_contents(
@@ -198,8 +174,8 @@
     @test.idempotent_id('196f5034-6ab0-4032-9da9-a937bbb9fba9')
     def test_list_container_contents_with_format_json(self):
         # get container contents list using format_json param
-        container_name = self._create_container()
-        self._create_object(container_name)
+        container_name = self.create_container()
+        self.create_object(container_name)
 
         params = {'format': 'json'}
         resp, object_list = self.container_client.list_container_contents(
@@ -217,8 +193,8 @@
     @test.idempotent_id('655a53ca-4d15-408c-a377-f4c6dbd0a1fa')
     def test_list_container_contents_with_format_xml(self):
         # get container contents list using format_xml param
-        container_name = self._create_container()
-        self._create_object(container_name)
+        container_name = self.create_container()
+        self.create_object(container_name)
 
         params = {'format': 'xml'}
         resp, object_list = self.container_client.list_container_contents(
@@ -241,8 +217,8 @@
     @test.idempotent_id('297ec38b-2b61-4ff4-bcd1-7fa055e97b61')
     def test_list_container_contents_with_limit(self):
         # get container contents list using limit param
-        container_name = self._create_container()
-        object_name = self._create_object(container_name)
+        container_name = self.create_container()
+        object_name, _ = self.create_object(container_name)
 
         params = {'limit': data_utils.rand_int_id(1, 10000)}
         resp, object_list = self.container_client.list_container_contents(
@@ -254,8 +230,8 @@
     @test.idempotent_id('c31ddc63-2a58-4f6b-b25c-94d2937e6867')
     def test_list_container_contents_with_marker(self):
         # get container contents list using marker param
-        container_name = self._create_container()
-        object_name = self._create_object(container_name)
+        container_name = self.create_container()
+        object_name, _ = self.create_object(container_name)
 
         params = {'marker': 'AaaaObject1234567890'}
         resp, object_list = self.container_client.list_container_contents(
@@ -267,9 +243,9 @@
     @test.idempotent_id('58ca6cc9-6af0-408d-aaec-2a6a7b2f0df9')
     def test_list_container_contents_with_path(self):
         # get container contents list using path param
-        container_name = self._create_container()
+        container_name = self.create_container()
         object_name = data_utils.rand_name(name='Swift/TestObject')
-        self._create_object(container_name, object_name)
+        self.create_object(container_name, object_name)
 
         params = {'path': 'Swift'}
         resp, object_list = self.container_client.list_container_contents(
@@ -281,8 +257,8 @@
     @test.idempotent_id('77e742c7-caf2-4ec9-8aa4-f7d509a3344c')
     def test_list_container_contents_with_prefix(self):
         # get container contents list using prefix param
-        container_name = self._create_container()
-        object_name = self._create_object(container_name)
+        container_name = self.create_container()
+        object_name, _ = self.create_object(container_name)
 
         prefix_key = object_name[0:8]
         params = {'prefix': prefix_key}
@@ -296,7 +272,7 @@
     @test.idempotent_id('96e68f0e-19ec-4aa2-86f3-adc6a45e14dd')
     def test_list_container_metadata(self):
         # List container metadata
-        container_name = self._create_container()
+        container_name = self.create_container()
 
         metadata = {'name': 'Pictures'}
         self.container_client.update_container_metadata(
@@ -312,7 +288,7 @@
     @test.idempotent_id('a2faf936-6b13-4f8d-92a2-c2278355821e')
     def test_list_no_container_metadata(self):
         # HEAD container without metadata
-        container_name = self._create_container()
+        container_name = self.create_container()
 
         resp, _ = self.container_client.list_container_metadata(
             container_name)
@@ -345,7 +321,7 @@
     @test.idempotent_id('2ae5f295-4bf1-4e04-bfad-21e54b62cec5')
     def test_update_container_metadata_with_create_metadata(self):
         # update container metadata using add metadata
-        container_name = self._create_container()
+        container_name = self.create_container()
 
         metadata = {'test-container-meta1': 'Meta1'}
         resp, _ = self.container_client.update_container_metadata(
@@ -380,7 +356,7 @@
     @test.idempotent_id('31f40a5f-6a52-4314-8794-cd89baed3040')
     def test_update_container_metadata_with_create_metadata_key(self):
         # update container metadata with a blank value of metadata
-        container_name = self._create_container()
+        container_name = self.create_container()
 
         metadata = {'test-container-meta1': ''}
         resp, _ = self.container_client.update_container_metadata(
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 5b3ce79..47ef0d3 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -24,18 +24,14 @@
     @classmethod
     def resource_setup(cls):
         super(StaticWebTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name="TestContainer")
 
         # This header should be posted on the container before every test
         cls.headers_public_read_acl = {'Read': '.r:*,.rlistings'}
 
         # Create test container and create one object in it
-        cls.container_client.create_container(cls.container_name)
-        cls.object_name = data_utils.rand_name(name="TestObject")
-        cls.object_data = data_utils.arbitrary_string()
-        cls.object_client.create_object(cls.container_name,
-                                        cls.object_name,
-                                        cls.object_data)
+        cls.container_name = cls.create_container()
+        cls.object_name, cls.object_data = cls.create_object(
+            cls.container_name)
 
         cls.container_client.update_container_metadata(
             cls.container_name,
@@ -44,8 +40,7 @@
 
     @classmethod
     def resource_cleanup(cls):
-        if hasattr(cls, "container_name"):
-            cls.delete_containers([cls.container_name])
+        cls.delete_containers()
         super(StaticWebTest, cls).resource_cleanup()
 
     @test.idempotent_id('c1f055ab-621d-4a6a-831f-846fcb578b8b')
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 2a5cec6..e10b900 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -80,7 +80,7 @@
     @classmethod
     def resource_cleanup(cls):
         for client in cls.clients.values():
-            cls.delete_containers(cls.containers, client[0], client[1])
+            cls.delete_containers(client[0], client[1])
         super(ContainerSyncTest, cls).resource_cleanup()
 
     def _test_container_synchronization(self, make_headers):
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 9db8bde..11acb31 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -16,7 +16,6 @@
 import time
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -25,19 +24,17 @@
     @classmethod
     def resource_setup(cls):
         super(ObjectExpiryTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name='TestContainer')
-        cls.container_client.create_container(cls.container_name)
+        cls.container_name = cls.create_container()
 
     def setUp(self):
         super(ObjectExpiryTest, self).setUp()
         # create object
-        self.object_name = data_utils.rand_name(name='TestObject')
-        resp, _ = self.object_client.create_object(self.container_name,
-                                                   self.object_name, '')
+        self.object_name, _ = self.create_object(
+            self.container_name)
 
     @classmethod
     def resource_cleanup(cls):
-        cls.delete_containers([cls.container_name])
+        cls.delete_containers()
         super(ObjectExpiryTest, cls).resource_cleanup()
 
     def _test_object_expiry(self, metadata):
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 356f560..102ec2f 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -31,12 +31,9 @@
     @classmethod
     def resource_setup(cls):
         super(ObjectFormPostTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name='TestContainer')
+        cls.container_name = cls.create_container()
         cls.object_name = data_utils.rand_name(name='ObjectTemp')
 
-        cls.container_client.create_container(cls.container_name)
-        cls.containers = [cls.container_name]
-
         cls.key = 'Meta'
         cls.metadata = {'Temp-URL-Key': cls.key}
         cls.account_client.create_account_metadata(metadata=cls.metadata)
@@ -56,7 +53,7 @@
     @classmethod
     def resource_cleanup(cls):
         cls.account_client.delete_account_metadata(metadata=cls.metadata)
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
         super(ObjectFormPostTest, cls).resource_cleanup()
 
     def get_multipart_form(self, expires=600):
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index cb13271..8ff5d82 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -32,12 +32,9 @@
     @classmethod
     def resource_setup(cls):
         super(ObjectFormPostNegativeTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name='TestContainer')
+        cls.container_name = cls.create_container()
         cls.object_name = data_utils.rand_name(name='ObjectTemp')
 
-        cls.container_client.create_container(cls.container_name)
-        cls.containers = [cls.container_name]
-
         cls.key = 'Meta'
         cls.metadata = {'Temp-URL-Key': cls.key}
         cls.account_client.create_account_metadata(metadata=cls.metadata)
@@ -57,7 +54,7 @@
     @classmethod
     def resource_cleanup(cls):
         cls.account_client.delete_account_metadata(metadata=cls.metadata)
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
         super(ObjectFormPostNegativeTest, cls).resource_cleanup()
 
     def get_multipart_form(self, expires=600):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index a88e4f4..a707ebb 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -35,24 +35,13 @@
     @classmethod
     def resource_setup(cls):
         super(ObjectTest, cls).resource_setup()
-        cls.container_name = data_utils.rand_name(name='TestContainer')
-        cls.container_client.create_container(cls.container_name)
-        cls.containers = [cls.container_name]
+        cls.container_name = cls.create_container()
 
     @classmethod
     def resource_cleanup(cls):
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
         super(ObjectTest, cls).resource_cleanup()
 
-    def _create_object(self, metadata=None):
-        # setup object
-        object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
-        self.object_client.create_object(self.container_name,
-                                         object_name, data, metadata=metadata)
-
-        return object_name, data
-
     def _upload_segments(self):
         # create object
         object_name = data_utils.rand_name(name='LObject')
@@ -335,7 +324,7 @@
     @test.idempotent_id('7a94c25d-66e6-434c-9c38-97d4e2c29945')
     def test_update_object_metadata(self):
         # update object metadata
-        object_name, data = self._create_object()
+        object_name, _ = self.create_object(self.container_name)
 
         metadata = {'X-Object-Meta-test-meta': 'Meta'}
         resp, _ = self.object_client.update_object_metadata(
@@ -431,8 +420,8 @@
 
     @test.idempotent_id('0dbbe89c-6811-4d84-a2df-eca2bdd40c0e')
     def test_update_object_metadata_with_x_object_metakey(self):
-        # update object metadata with a blenk value of metadata
-        object_name, data = self._create_object()
+        # update object metadata with a blank value of metadata
+        object_name, _ = self.create_object(self.container_name)
 
         update_metadata = {'X-Object-Meta-test-meta': ''}
         resp, _ = self.object_client.update_object_metadata(
@@ -494,7 +483,7 @@
     @test.idempotent_id('170fb90e-f5c3-4b1f-ae1b-a18810821172')
     def test_list_no_object_metadata(self):
         # get empty list of object metadata
-        object_name, data = self._create_object()
+        object_name, _ = self.create_object(self.container_name)
 
         resp, _ = self.object_client.list_object_metadata(
             self.container_name,
@@ -548,7 +537,7 @@
         # retrieve object's data (in response body)
 
         # create object
-        object_name, data = self._create_object()
+        object_name, data = self.create_object(self.container_name)
         # get object
         resp, body = self.object_client.get_object(self.container_name,
                                                    object_name)
@@ -701,7 +690,7 @@
     @test.idempotent_id('0aa1201c-10aa-467a-bee7-63cbdd463152')
     def test_get_object_with_if_unmodified_since(self):
         # get object with if_unmodified_since
-        object_name, data = self._create_object()
+        object_name, data = self.create_object(self.container_name)
 
         time_now = time.time()
         http_date = time.ctime(time_now + 86400)
@@ -716,7 +705,7 @@
     @test.idempotent_id('94587078-475f-48f9-a40f-389c246e31cd')
     def test_get_object_with_x_newest(self):
         # get object with x_newest
-        object_name, data = self._create_object()
+        object_name, data = self.create_object(self.container_name)
 
         list_metadata = {'X-Newest': 'true'}
         resp, body = self.object_client.get_object(
@@ -757,7 +746,7 @@
         # change the content type of an existing object
 
         # create object
-        object_name, data = self._create_object()
+        object_name, _ = self.create_object(self.container_name)
         # get the old content type
         resp_tmp, _ = self.object_client.list_object_metadata(
             self.container_name, object_name)
@@ -843,7 +832,8 @@
     def test_copy_object_with_x_fresh_metadata(self):
         # create source object
         metadata = {'x-object-meta-src': 'src_value'}
-        src_object_name, data = self._create_object(metadata)
+        src_object_name, data = self.create_object(self.container_name,
+                                                   metadata=metadata)
 
         # copy source object with x_fresh_metadata header
         metadata = {'X-Fresh-Metadata': 'true'}
@@ -863,7 +853,8 @@
     def test_copy_object_with_x_object_metakey(self):
         # create source object
         metadata = {'x-object-meta-src': 'src_value'}
-        src_obj_name, data = self._create_object(metadata)
+        src_obj_name, data = self.create_object(self.container_name,
+                                                metadata=metadata)
 
         # copy source object to destination with x-object-meta-key
         metadata = {'x-object-meta-test': ''}
@@ -885,7 +876,8 @@
     def test_copy_object_with_x_object_meta(self):
         # create source object
         metadata = {'x-object-meta-src': 'src_value'}
-        src_obj_name, data = self._create_object(metadata)
+        src_obj_name, data = self.create_object(self.container_name,
+                                                metadata=metadata)
 
         # copy source object to destination with object metadata
         metadata = {'x-object-meta-test': 'value'}
@@ -951,7 +943,7 @@
         # Make a conditional request for an object using the If-None-Match
         # header, it should get downloaded only if the local file is different,
         # otherwise the response code should be 304 Not Modified
-        object_name, data = self._create_object()
+        object_name, data = self.create_object(self.container_name)
         # local copy is identical, no download
         md5 = hashlib.md5(data).hexdigest()
         headers = {'If-None-Match': md5}
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 867159b..e00bbab 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -30,8 +30,7 @@
 
     def setUp(self):
         super(ObjectSloTest, self).setUp()
-        self.container_name = data_utils.rand_name(name='TestContainer')
-        self.container_client.create_container(self.container_name)
+        self.container_name = self.create_container()
         self.objects = []
 
     def tearDown(self):
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 3d28f6e..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):
 
@@ -32,9 +29,7 @@
     def resource_setup(cls):
         super(ObjectTempUrlTest, cls).resource_setup()
         # create a container
-        cls.container_name = data_utils.rand_name(name='TestContainer')
-        cls.container_client.create_container(cls.container_name)
-        cls.containers = [cls.container_name]
+        cls.container_name = cls.create_container()
 
         # update account metadata
         cls.key = 'Meta'
@@ -44,11 +39,7 @@
         cls.account_client.create_account_metadata(metadata=metadata)
 
         # create an object
-        cls.object_name = data_utils.rand_name(name='ObjectTemp')
-        cls.content = data_utils.arbitrary_string(size=len(cls.object_name),
-                                                  base_text=cls.object_name)
-        cls.object_client.create_object(cls.container_name,
-                                        cls.object_name, cls.content)
+        cls.object_name, cls.content = cls.create_object(cls.container_name)
 
     @classmethod
     def resource_cleanup(cls):
@@ -56,7 +47,7 @@
             cls.account_client.delete_account_metadata(
                 metadata=metadata)
 
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
 
         super(ObjectTempUrlTest, cls).resource_cleanup()
 
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index 38fe697..577f3bd 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -33,9 +33,7 @@
     def resource_setup(cls):
         super(ObjectTempUrlNegativeTest, cls).resource_setup()
 
-        cls.container_name = data_utils.rand_name(name='TestContainer')
-        cls.container_client.create_container(cls.container_name)
-        cls.containers = [cls.container_name]
+        cls.container_name = cls.create_container()
 
         # update account metadata
         cls.key = 'Meta'
@@ -49,7 +47,7 @@
         resp, _ = cls.account_client.delete_account_metadata(
             metadata=cls.metadata)
 
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
 
         super(ObjectTempUrlNegativeTest, cls).resource_cleanup()
 
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 24ec3f5..3f6623b 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -31,7 +31,7 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.delete_containers(cls.containers)
+        cls.delete_containers()
         super(ContainerTest, cls).resource_cleanup()
 
     def assertContainer(self, container, count, byte, versioned):
diff --git a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml b/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
index be33c94..ccb1b54 100644
--- a/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
+++ b/tempest/api/orchestration/stacks/templates/neutron_basic.yaml
@@ -58,7 +58,7 @@
             #!/bin/sh -v
 
             SIGNAL_DATA='{"Status": "SUCCESS", "Reason": "SmokeServerNeutron created", "Data": "Application has completed configuration.", "UniqueId": "00000"}'
-            while ! curl --fail -X PUT -H 'Content-Type:' --data-binary "$SIGNAL_DATA" \
+            while ! curl --insecure --fail -X PUT -H 'Content-Type:' --data-binary "$SIGNAL_DATA" \
             'wait_handle' ; do sleep 3; done
           params:
             wait_handle: {get_resource: WaitHandleNeutron}
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_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index 3be5bb6..4ead084 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -125,7 +125,7 @@
                                        'resource_status_reason',
                                        'resource_status', 'event_time')
 
-        resource_statuses = map(lambda event: event['resource_status'], events)
+        resource_statuses = [event['resource_status'] for event in events]
         self.assertIn('CREATE_IN_PROGRESS', resource_statuses)
         self.assertIn('CREATE_COMPLETE', resource_statuses)
 
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..f665e69 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}
+        params = {cls.name_field: vol_name, 'volume_type': type_name}
 
-        self.volume = self.admin_volume_client.create_volume(
+        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..f1101e1
--- 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']:
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.py b/tempest/api/volume/admin/test_volume_quotas.py
index ba17d9c..fe105e8 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -73,8 +73,9 @@
 
     @test.idempotent_id('18c51ae9-cb03-48fc-b234-14a19374dbed')
     def test_show_quota_usage(self):
-        quota_usage = self.admin_quotas_client.show_quota_usage(
-            self.os_adm.credentials.tenant_id)['quota_set']
+        quota_usage = self.admin_quotas_client.show_quota_set(
+            self.os_adm.credentials.tenant_id,
+            params={'usage': True})['quota_set']
         for key in QUOTA_KEYS:
             self.assertIn(key, quota_usage)
             for usage_key in QUOTA_USAGE_KEYS:
@@ -82,15 +83,15 @@
 
     @test.idempotent_id('ae8b6091-48ad-4bfa-a188-bbf5cc02115f')
     def test_quota_usage(self):
-        quota_usage = self.admin_quotas_client.show_quota_usage(
-            self.demo_tenant_id)['quota_set']
+        quota_usage = self.admin_quotas_client.show_quota_set(
+            self.demo_tenant_id, params={'usage': True})['quota_set']
 
         volume = self.create_volume()
         self.addCleanup(self.delete_volume,
                         self.admin_volume_client, volume['id'])
 
-        new_quota_usage = self.admin_quotas_client.show_quota_usage(
-            self.demo_tenant_id)['quota_set']
+        new_quota_usage = self.admin_quotas_client.show_quota_set(
+            self.demo_tenant_id, params={'usage': True})['quota_set']
 
         self.assertEqual(quota_usage['volumes']['in_use'] + 1,
                          new_quota_usage['volumes']['in_use'])
@@ -128,11 +129,11 @@
                         self.admin_volume_client, volume['id'])
 
         # List of tenants quota usage pre-transfer
-        primary_quota = self.admin_quotas_client.show_quota_usage(
-            self.demo_tenant_id)['quota_set']
+        primary_quota = self.admin_quotas_client.show_quota_set(
+            self.demo_tenant_id, params={'usage': True})['quota_set']
 
-        alt_quota = self.admin_quotas_client.show_quota_usage(
-            self.alt_client.tenant_id)['quota_set']
+        alt_quota = self.admin_quotas_client.show_quota_set(
+            self.alt_client.tenant_id, params={'usage': True})['quota_set']
 
         # Creates a volume transfer
         transfer = self.volumes_client.create_volume_transfer(
@@ -149,11 +150,11 @@
             self.alt_client, volume['id'], 'available')
 
         # List of tenants quota usage post transfer
-        new_primary_quota = self.admin_quotas_client.show_quota_usage(
-            self.demo_tenant_id)['quota_set']
+        new_primary_quota = self.admin_quotas_client.show_quota_set(
+            self.demo_tenant_id, params={'usage': True})['quota_set']
 
-        new_alt_quota = self.admin_quotas_client.show_quota_usage(
-            self.alt_client.tenant_id)['quota_set']
+        new_alt_quota = self.admin_quotas_client.show_quota_set(
+            self.alt_client.tenant_id, params={'usage': True})['quota_set']
 
         # Verify tenants quota usage was updated
         self.assertEqual(primary_quota['volumes']['in_use'] -
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index dde8915..89e4d18 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -14,12 +14,9 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
-CONF = config.CONF
-
 
 class BaseVolumeQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
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 27f6ccb..7b4379b
--- 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,7 +43,8 @@
                        "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)
@@ -87,19 +88,22 @@
     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
         extra_specs = {"storage_protocol": proto,
                        "vendor_name": vendor}
-        body = self.create_volume_type(
-            name=name,
-            extra_specs=extra_specs)
+        body = self.create_volume_type(description=description, name=name,
+                                       extra_specs=extra_specs)
         self.assertIn('id', body)
         self.assertIn('name', body)
-        self.assertEqual(body['name'], name,
+        self.assertEqual(name, body['name'],
                          "The created volume_type name is not equal "
                          "to the requested name")
+        self.assertEqual(description, body['description'],
+                         "The created volume_type_description name is "
+                         "not equal to the requested name")
         self.assertTrue(body['id'] is not None,
                         "Field volume_type id is empty or not found.")
         fetched_volume_type = self.admin_volume_types_client.show_volume_type(
@@ -119,7 +123,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 = \
@@ -158,6 +162,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..03927e6
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -59,7 +59,7 @@
 
     def _create_temp_volume(self):
         # Create a temp volume for force delete tests
-        vol_name = utils.rand_name('Volume')
+        vol_name = utils.rand_name(self.__class__.__name__ + '-Volume')
         params = {self.name_field: vol_name}
         temp_volume = self.client.create_volume(**params)['volume']
         waiters.wait_for_volume_status(self.client,
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 b6dc488..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'])
@@ -166,6 +128,24 @@
         self.admin_backups_client.wait_for_backup_status(import_backup['id'],
                                                          'available')
 
+    @test.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
+    def test_volume_backup_reset_status(self):
+        # Create a 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,
+                        backup['id'])
+        self.assertEqual(backup_name, backup['name'])
+        self.admin_backups_client.wait_for_backup_status(backup['id'],
+                                                         'available')
+        # Reset backup status to error
+        self.admin_backups_client.reset_backup_status(backup_id=backup['id'],
+                                                      status="error")
+        self.admin_backups_client.wait_for_backup_status(backup['id'],
+                                                         'error')
+
 
 class VolumesBackupsAdminV1Test(VolumesBackupsAdminV2Test):
     _api_version = 1
diff --git a/tempest/api/volume/admin/test_volumes_list.py b/tempest/api/volume/admin/test_volumes_list.py
index 64041b8..70c16f3 100644
--- a/tempest/api/volume/admin/test_volumes_list.py
+++ b/tempest/api/volume/admin/test_volumes_list.py
@@ -53,7 +53,7 @@
         self.assertEqual(sorted(expected_list_ids), sorted(fetched_list_ids))
         # Verifying tenant id of volumes fetched list is related to
         # primary tenant
-        fetched_tenant_id = map(operator.itemgetter(
-            'os-vol-tenant-attr:tenant_id'), fetched_list)
+        fetched_tenant_id = [operator.itemgetter(
+            'os-vol-tenant-attr:tenant_id')(item) for item in fetched_list]
         expected_tenant_id = [self.volumes_client.tenant_id] * 3
         self.assertEqual(expected_tenant_id, fetched_tenant_id)
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 087b9a8..ef28add 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -110,7 +110,7 @@
     @classmethod
     def create_volume(cls, **kwargs):
         """Wrapper utility that returns a test volume."""
-        name = data_utils.rand_name('Volume')
+        name = data_utils.rand_name(cls.__name__ + '-Volume')
 
         name_field = cls.special_fields['name_field']
 
@@ -236,7 +236,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'])
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..d5e1e6b
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -129,7 +129,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_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..7a1c0a1
--- 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,7 +103,6 @@
         # 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']}
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index a93025d..b5ef7c0 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -33,8 +33,9 @@
 
     def assertVolumesIn(self, fetched_list, expected_list, fields=None):
         if fields:
-            expected_list = map(operator.itemgetter(*fields), expected_list)
-            fetched_list = map(operator.itemgetter(*fields), fetched_list)
+            fieldsgetter = operator.itemgetter(*fields)
+            expected_list = map(fieldsgetter, expected_list)
+            fetched_list = [fieldsgetter(item) for item in fetched_list]
 
         missing_vols = [v for v in expected_list if v not in fetched_list]
         if len(missing_vols) == 0:
@@ -60,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..d2c05ae
--- 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']
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 5117e6c..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
@@ -174,9 +167,9 @@
 
             # If cannot follow make sure it's because we have finished
             else:
-                self.assertListEqual([], remaining or [],
-                                     'No more pages reported, but still '
-                                     'missing ids %s' % remaining)
+                self.assertEqual([], remaining or [],
+                                 'No more pages reported, but still '
+                                 'missing ids %s' % remaining)
                 break
 
     @test.idempotent_id('e9138a2c-f67b-4796-8efa-635c196d01de')
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..517c8d7
--- a/tempest/api/volume/v3/admin/test_user_messages.py
+++ b/tempest/api/volume/v3/admin/test_user_messages.py
@@ -42,7 +42,8 @@
         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']
diff --git a/tempest/clients.py b/tempest/clients.py
index fd010f2..e14f6f8 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -14,18 +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.lib.services import compute
-from tempest.lib.services import image
-from tempest.lib.services import network
-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
@@ -37,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()
@@ -102,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.
@@ -127,133 +121,84 @@
         return configuration
 
     def _set_network_clients(self):
-        params = self.parameters['network']
-        self.network_agents_client = network.AgentsClient(
-            self.auth_provider, **params)
-        self.network_extensions_client = network.ExtensionsClient(
-            self.auth_provider, **params)
-        self.networks_client = network.NetworksClient(
-            self.auth_provider, **params)
-        self.subnetpools_client = network.SubnetpoolsClient(
-            self.auth_provider, **params)
-        self.subnets_client = network.SubnetsClient(
-            self.auth_provider, **params)
-        self.ports_client = network.PortsClient(
-            self.auth_provider, **params)
-        self.network_quotas_client = network.QuotasClient(
-            self.auth_provider, **params)
-        self.floating_ips_client = network.FloatingIPsClient(
-            self.auth_provider, **params)
-        self.metering_labels_client = network.MeteringLabelsClient(
-            self.auth_provider, **params)
-        self.metering_label_rules_client = network.MeteringLabelRulesClient(
-            self.auth_provider, **params)
-        self.routers_client = network.RoutersClient(
-            self.auth_provider, **params)
-        self.security_group_rules_client = network.SecurityGroupRulesClient(
-            self.auth_provider, **params)
-        self.security_groups_client = network.SecurityGroupsClient(
-            self.auth_provider, **params)
-        self.network_versions_client = network.NetworkVersionsClient(
-            self.auth_provider, **params)
+        self.network_agents_client = self.network.AgentsClient()
+        self.network_extensions_client = self.network.ExtensionsClient()
+        self.networks_client = self.network.NetworksClient()
+        self.subnetpools_client = self.network.SubnetpoolsClient()
+        self.subnets_client = self.network.SubnetsClient()
+        self.ports_client = self.network.PortsClient()
+        self.network_quotas_client = self.network.QuotasClient()
+        self.floating_ips_client = self.network.FloatingIPsClient()
+        self.metering_labels_client = self.network.MeteringLabelsClient()
+        self.metering_label_rules_client = (
+            self.network.MeteringLabelRulesClient())
+        self.routers_client = self.network.RoutersClient()
+        self.security_group_rules_client = (
+            self.network.SecurityGroupRulesClient())
+        self.security_groups_client = self.network.SecurityGroupsClient()
+        self.network_versions_client = self.network.NetworkVersionsClient()
 
     def _set_image_clients(self):
         if CONF.service_available.glance:
-            params = self.parameters['image']
-            self.image_client = image.v1.ImagesClient(
-                self.auth_provider, **params)
-            self.image_member_client = image.v1.ImageMembersClient(
-                self.auth_provider, **params)
-
-            self.image_client_v2 = image.v2.ImagesClient(
-                self.auth_provider, **params)
-            self.image_member_client_v2 = image.v2.ImageMembersClient(
-                self.auth_provider, **params)
-            self.namespaces_client = image.v2.NamespacesClient(
-                self.auth_provider, **params)
-            self.resource_types_client = image.v2.ResourceTypesClient(
-                self.auth_provider, **params)
-            self.schemas_client = image.v2.SchemasClient(
-                self.auth_provider, **params)
+            self.image_client = self.image_v1.ImagesClient()
+            self.image_member_client = self.image_v1.ImageMembersClient()
+            self.image_client_v2 = self.image_v2.ImagesClient()
+            self.image_member_client_v2 = self.image_v2.ImageMembersClient()
+            self.namespaces_client = self.image_v2.NamespacesClient()
+            self.resource_types_client = self.image_v2.ResourceTypesClient()
+            self.schemas_client = self.image_v2.SchemasClient()
 
     def _set_compute_clients(self):
-        params = self.parameters['compute']
-
-        self.agents_client = compute.AgentsClient(self.auth_provider, **params)
-        self.compute_networks_client = compute.NetworksClient(
-            self.auth_provider, **params)
-        self.migrations_client = compute.MigrationsClient(self.auth_provider,
-                                                          **params)
+        self.agents_client = self.compute.AgentsClient()
+        self.compute_networks_client = self.compute.NetworksClient()
+        self.migrations_client = self.compute.MigrationsClient()
         self.security_group_default_rules_client = (
-            compute.SecurityGroupDefaultRulesClient(self.auth_provider,
-                                                    **params))
-        self.certificates_client = compute.CertificatesClient(
-            self.auth_provider, **params)
-        self.servers_client = compute.ServersClient(
-            self.auth_provider,
-            enable_instance_password=CONF.compute_feature_enabled
-                .enable_instance_password,
-            **params)
-        self.server_groups_client = compute.ServerGroupsClient(
-            self.auth_provider, **params)
-        self.limits_client = compute.LimitsClient(self.auth_provider, **params)
-        self.compute_images_client = compute.ImagesClient(self.auth_provider,
-                                                          **params)
-        self.keypairs_client = compute.KeyPairsClient(self.auth_provider,
-                                                      **params)
-        self.quotas_client = compute.QuotasClient(self.auth_provider, **params)
-        self.quota_classes_client = compute.QuotaClassesClient(
-            self.auth_provider, **params)
-        self.flavors_client = compute.FlavorsClient(self.auth_provider,
-                                                    **params)
-        self.extensions_client = compute.ExtensionsClient(self.auth_provider,
-                                                          **params)
-        self.floating_ip_pools_client = compute.FloatingIPPoolsClient(
-            self.auth_provider, **params)
-        self.floating_ips_bulk_client = compute.FloatingIPsBulkClient(
-            self.auth_provider, **params)
-        self.compute_floating_ips_client = compute.FloatingIPsClient(
-            self.auth_provider, **params)
+            self.compute.SecurityGroupDefaultRulesClient())
+        self.certificates_client = self.compute.CertificatesClient()
+        eip = CONF.compute_feature_enabled.enable_instance_password
+        self.servers_client = self.compute.ServersClient(
+            enable_instance_password=eip)
+        self.server_groups_client = self.compute.ServerGroupsClient()
+        self.limits_client = self.compute.LimitsClient()
+        self.compute_images_client = self.compute.ImagesClient()
+        self.keypairs_client = self.compute.KeyPairsClient()
+        self.quotas_client = self.compute.QuotasClient()
+        self.quota_classes_client = self.compute.QuotaClassesClient()
+        self.flavors_client = self.compute.FlavorsClient()
+        self.extensions_client = self.compute.ExtensionsClient()
+        self.floating_ip_pools_client = self.compute.FloatingIPPoolsClient()
+        self.floating_ips_bulk_client = self.compute.FloatingIPsBulkClient()
+        self.compute_floating_ips_client = self.compute.FloatingIPsClient()
         self.compute_security_group_rules_client = (
-            compute.SecurityGroupRulesClient(self.auth_provider, **params))
-        self.compute_security_groups_client = compute.SecurityGroupsClient(
-            self.auth_provider, **params)
-        self.interfaces_client = compute.InterfacesClient(self.auth_provider,
-                                                          **params)
-        self.fixed_ips_client = compute.FixedIPsClient(self.auth_provider,
-                                                       **params)
-        self.availability_zone_client = compute.AvailabilityZoneClient(
-            self.auth_provider, **params)
-        self.aggregates_client = compute.AggregatesClient(self.auth_provider,
-                                                          **params)
-        self.services_client = compute.ServicesClient(self.auth_provider,
-                                                      **params)
-        self.tenant_usages_client = compute.TenantUsagesClient(
-            self.auth_provider, **params)
-        self.hosts_client = compute.HostsClient(self.auth_provider, **params)
-        self.hypervisor_client = compute.HypervisorClient(self.auth_provider,
-                                                          **params)
+            self.compute.SecurityGroupRulesClient())
+        self.compute_security_groups_client = (
+            self.compute.SecurityGroupsClient())
+        self.interfaces_client = self.compute.InterfacesClient()
+        self.fixed_ips_client = self.compute.FixedIPsClient()
+        self.availability_zone_client = self.compute.AvailabilityZoneClient()
+        self.aggregates_client = self.compute.AggregatesClient()
+        self.services_client = self.compute.ServicesClient()
+        self.tenant_usages_client = self.compute.TenantUsagesClient()
+        self.hosts_client = self.compute.HostsClient()
+        self.hypervisor_client = self.compute.HypervisorClient()
         self.instance_usages_audit_log_client = (
-            compute.InstanceUsagesAuditLogClient(self.auth_provider, **params))
-        self.tenant_networks_client = compute.TenantNetworksClient(
-            self.auth_provider, **params)
-        self.baremetal_nodes_client = compute.BaremetalNodesClient(
-            self.auth_provider, **params)
+            self.compute.InstanceUsagesAuditLogClient())
+        self.tenant_networks_client = self.compute.TenantNetworksClient()
+        self.baremetal_nodes_client = self.compute.BaremetalNodesClient()
 
         # NOTE: The following client needs special timeout values because
         # the API is a proxy for the other component.
-        params_volume = copy.deepcopy(params)
-        # Optional parameters
+        params_volume = {}
         for _key in ('build_interval', 'build_timeout'):
             _value = self.parameters['volume'].get(_key)
             if _value:
                 params_volume[_key] = _value
-        self.volumes_extensions_client = compute.VolumesClient(
-            self.auth_provider, **params_volume)
-        self.compute_versions_client = compute.VersionsClient(
-            self.auth_provider, **params_volume)
-        self.snapshots_extensions_client = compute.SnapshotsClient(
-            self.auth_provider, **params_volume)
+        self.volumes_extensions_client = self.compute.VolumesClient(
+            **params_volume)
+        self.compute_versions_client = self.compute.VersionsClient(
+            **params_volume)
+        self.snapshots_extensions_client = self.compute.SnapshotsClient(
+            **params_volume)
 
     def _set_identity_clients(self):
         params = self.parameters['identity']
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 8d2cfdc..9758061 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -67,11 +67,8 @@
     CONF_PRIV_NETWORK_NAME = CONF.compute.fixed_network_name
     CONF_PUB_NETWORK = CONF.network.public_network_id
     CONF_PUB_ROUTER = CONF.network.public_router_id
-    CONF_TENANTS = [CONF.auth.admin_project_name,
-                    CONF.identity.project_name,
-                    CONF.identity.alt_project_name]
-    CONF_USERS = [CONF.auth.admin_username, CONF.identity.username,
-                  CONF.identity.alt_username]
+    CONF_TENANTS = [CONF.auth.admin_project_name]
+    CONF_USERS = [CONF.auth.admin_username]
 
     if IS_NEUTRON:
         CONF_PRIV_NETWORK = _get_network_id(CONF.compute.fixed_network_name,
@@ -352,7 +349,8 @@
             LOG.exception("Delete Volume Quotas exception.")
 
     def dry_run(self):
-        quotas = self.client.show_quota_usage(self.tenant_id)['quota_set']
+        quotas = self.client.show_quota_set(
+            self.tenant_id, params={'usage': True})['quota_set']
         self.data['volume_quotas'] = quotas
 
 
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/javelin.py b/tempest/cmd/javelin.py
deleted file mode 100755
index a9e5167..0000000
--- a/tempest/cmd/javelin.py
+++ /dev/null
@@ -1,1131 +0,0 @@
-#!/usr/bin/env python
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Javelin is a tool for creating, verifying, and deleting a small set of
-resources in a declarative way.
-
-Javelin is meant to be used as a way to validate quickly that resources can
-survive an upgrade process.
-
-Authentication
---------------
-
-Javelin will be creating (and removing) users and tenants so it needs the admin
-credentials of your cloud to operate properly. The corresponding info can be
-given the usual way, either through CLI options or environment variables.
-
-You're probably familiar with these, but just in case::
-
-    +----------+------------------+----------------------+
-    | Param    | CLI              | Environment Variable |
-    +----------+------------------+----------------------+
-    | Username | --os-username    | OS_USERNAME          |
-    | Password | --os-password    | OS_PASSWORD          |
-    | Tenant   | --os-tenant-name | OS_TENANT_NAME       |
-    +----------+------------------+----------------------+
-
-
-Runtime Arguments
------------------
-
-**-m/--mode**: (Required) Has to be one of 'check', 'create' or 'destroy'. It
-indicates which actions javelin is going to perform.
-
-**-r/--resources**: (Required) The path to a YAML file describing the resources
-used by Javelin.
-
-**-d/--devstack-base**: (Required) The path to the devstack repo used to
-retrieve artefacts (like images) that will be referenced in the resource files.
-
-**-c/--config-file**: (Optional) The path to a valid Tempest config file
-describing your cloud. Javelin may use this to determine if certain services
-are enabled and modify its behavior accordingly.
-
-
-Resource file
--------------
-
-The resource file is a valid YAML file describing the resources that will be
-created, checked and destroyed by javelin. Here's a canonical example of a
-resource file::
-
-  tenants:
-    - javelin
-    - discuss
-
-  users:
-    - name: javelin
-      pass: gungnir
-      tenant: javelin
-    - name: javelin2
-      pass: gungnir2
-      tenant: discuss
-
-  # resources that we want to create
-  images:
-    - name: javelin_cirros
-      owner: javelin
-      file: cirros-0.3.2-x86_64-blank.img
-      disk_format: ami
-      container_format: ami
-      aki: cirros-0.3.2-x86_64-vmlinuz
-      ari: cirros-0.3.2-x86_64-initrd
-
-  servers:
-    - name: peltast
-      owner: javelin
-      flavor: m1.small
-      image: javelin_cirros
-      floating_ip_pool: public
-    - name: hoplite
-      owner: javelin
-      flavor: m1.medium
-      image: javelin_cirros
-
-
-An important piece of the resource definition is the *owner* field, which is
-the user (that we've created) that is the owner of that resource. All
-operations on that resource will happen as that regular user to ensure that
-admin level access does not mask issues.
-
-The check phase will act like a unit test, using well known assert methods to
-verify that the correct resources exist.
-
-"""
-
-import argparse
-import collections
-import datetime
-import os
-import sys
-import unittest
-
-import netaddr
-from oslo_log import log as logging
-import six
-import yaml
-
-from tempest.common import identity
-from tempest.common import waiters
-from tempest import config
-from tempest.lib import auth
-from tempest.lib import exceptions as lib_exc
-from tempest.lib.services.compute import flavors_client
-from tempest.lib.services.compute import floating_ips_client
-from tempest.lib.services.compute import security_group_rules_client
-from tempest.lib.services.compute import security_groups_client
-from tempest.lib.services.compute import servers_client
-from tempest.lib.services.identity.v2 import roles_client
-from tempest.lib.services.identity.v2 import tenants_client
-from tempest.lib.services.identity.v2 import users_client
-from tempest.lib.services.image.v2 import images_client
-from tempest.lib.services.network import networks_client
-from tempest.lib.services.network import ports_client
-from tempest.lib.services.network import routers_client
-from tempest.lib.services.network import subnets_client
-from tempest.services.identity.v2.json import identity_client
-from tempest.services.object_storage import container_client
-from tempest.services.object_storage import object_client
-from tempest.services.volume.v1.json import volumes_client
-
-CONF = config.CONF
-OPTS = {}
-USERS = {}
-RES = collections.defaultdict(list)
-
-LOG = None
-
-JAVELIN_START = datetime.datetime.utcnow()
-
-
-class OSClient(object):
-    _creds = None
-    identity = None
-    servers = None
-
-    def __init__(self, user, pw, tenant):
-        default_params = {
-            'disable_ssl_certificate_validation':
-                CONF.identity.disable_ssl_certificate_validation,
-            'ca_certs': CONF.identity.ca_certificates_file,
-            'trace_requests': CONF.debug.trace_requests
-        }
-        default_params_with_timeout_values = {
-            'build_interval': CONF.compute.build_interval,
-            'build_timeout': CONF.compute.build_timeout
-        }
-        default_params_with_timeout_values.update(default_params)
-
-        compute_params = {
-            'service': CONF.compute.catalog_type,
-            'region': CONF.compute.region or CONF.identity.region,
-            'endpoint_type': CONF.compute.endpoint_type,
-            'build_interval': CONF.compute.build_interval,
-            'build_timeout': CONF.compute.build_timeout
-        }
-        compute_params.update(default_params)
-
-        object_storage_params = {
-            'service': CONF.object_storage.catalog_type,
-            'region': CONF.object_storage.region or CONF.identity.region,
-            'endpoint_type': CONF.object_storage.endpoint_type
-        }
-        object_storage_params.update(default_params)
-
-        _creds = auth.KeystoneV2Credentials(
-            username=user,
-            password=pw,
-            tenant_name=tenant)
-        auth_provider_params = {
-            'disable_ssl_certificate_validation':
-                CONF.identity.disable_ssl_certificate_validation,
-            'ca_certs': CONF.identity.ca_certificates_file,
-            'trace_requests': CONF.debug.trace_requests
-        }
-        _auth = auth.KeystoneV2AuthProvider(
-            _creds, CONF.identity.uri, **auth_provider_params)
-        self.identity = identity_client.IdentityClient(
-            _auth,
-            CONF.identity.catalog_type,
-            CONF.identity.region,
-            endpoint_type='adminURL',
-            **default_params_with_timeout_values)
-        self.tenants = tenants_client.TenantsClient(
-            _auth,
-            CONF.identity.catalog_type,
-            CONF.identity.region,
-            endpoint_type='adminURL',
-            **default_params_with_timeout_values)
-        self.roles = roles_client.RolesClient(
-            _auth,
-            CONF.identity.catalog_type,
-            CONF.identity.region,
-            endpoint_type='adminURL',
-            **default_params_with_timeout_values)
-        self.users = users_client.UsersClient(
-            _auth,
-            CONF.identity.catalog_type,
-            CONF.identity.region,
-            endpoint_type='adminURL',
-            **default_params_with_timeout_values)
-        self.servers = servers_client.ServersClient(_auth,
-                                                    **compute_params)
-        self.flavors = flavors_client.FlavorsClient(_auth,
-                                                    **compute_params)
-        self.floating_ips = floating_ips_client.FloatingIPsClient(
-            _auth, **compute_params)
-        self.secgroups = security_groups_client.SecurityGroupsClient(
-            _auth, **compute_params)
-        self.secrules = security_group_rules_client.SecurityGroupRulesClient(
-            _auth, **compute_params)
-        self.objects = object_client.ObjectClient(_auth,
-                                                  **object_storage_params)
-        self.containers = container_client.ContainerClient(
-            _auth, **object_storage_params)
-        self.images = images_client.ImagesClient(
-            _auth,
-            CONF.image.catalog_type,
-            CONF.image.region or CONF.identity.region,
-            endpoint_type=CONF.image.endpoint_type,
-            build_interval=CONF.image.build_interval,
-            build_timeout=CONF.image.build_timeout,
-            **default_params)
-        self.volumes = volumes_client.VolumesClient(
-            _auth,
-            CONF.volume.catalog_type,
-            CONF.volume.region or CONF.identity.region,
-            endpoint_type=CONF.volume.endpoint_type,
-            build_interval=CONF.volume.build_interval,
-            build_timeout=CONF.volume.build_timeout,
-            **default_params)
-        self.networks = networks_client.NetworksClient(
-            _auth,
-            CONF.network.catalog_type,
-            CONF.network.region or CONF.identity.region,
-            endpoint_type=CONF.network.endpoint_type,
-            build_interval=CONF.network.build_interval,
-            build_timeout=CONF.network.build_timeout,
-            **default_params)
-        self.ports = ports_client.PortsClient(
-            _auth,
-            CONF.network.catalog_type,
-            CONF.network.region or CONF.identity.region,
-            endpoint_type=CONF.network.endpoint_type,
-            build_interval=CONF.network.build_interval,
-            build_timeout=CONF.network.build_timeout,
-            **default_params)
-        self.routers = routers_client.RoutersClient(
-            _auth,
-            CONF.network.catalog_type,
-            CONF.network.region or CONF.identity.region,
-            endpoint_type=CONF.network.endpoint_type,
-            build_interval=CONF.network.build_interval,
-            build_timeout=CONF.network.build_timeout,
-            **default_params)
-        self.subnets = subnets_client.SubnetsClient(
-            _auth,
-            CONF.network.catalog_type,
-            CONF.network.region or CONF.identity.region,
-            endpoint_type=CONF.network.endpoint_type,
-            build_interval=CONF.network.build_interval,
-            build_timeout=CONF.network.build_timeout,
-            **default_params)
-
-
-def load_resources(fname):
-    """Load the expected resources from a yaml file."""
-    return yaml.load(open(fname, 'r'))
-
-
-def keystone_admin():
-    return OSClient(OPTS.os_username, OPTS.os_password, OPTS.os_tenant_name)
-
-
-def client_for_user(name):
-    LOG.debug("Entering client_for_user")
-    if name in USERS:
-        user = USERS[name]
-        LOG.debug("Created client for user %s" % user)
-        return OSClient(user['name'], user['pass'], user['tenant'])
-    else:
-        LOG.error("%s not found in USERS: %s" % (name, USERS))
-
-
-###################
-#
-# TENANTS
-#
-###################
-
-
-def create_tenants(tenants):
-    """Create tenants from resource definition.
-
-    Don't create the tenants if they already exist.
-    """
-    admin = keystone_admin()
-    body = admin.tenants.list_tenants()['tenants']
-    existing = [x['name'] for x in body]
-    for tenant in tenants:
-        if tenant not in existing:
-            admin.tenants.create_tenant(name=tenant)['tenant']
-        else:
-            LOG.warning("Tenant '%s' already exists in this environment"
-                        % tenant)
-
-
-def destroy_tenants(tenants):
-    admin = keystone_admin()
-    for tenant in tenants:
-        tenant_id = identity.get_tenant_by_name(admin.tenant, tenant)['id']
-        admin.tenants.delete_tenant(tenant_id)
-
-##############
-#
-# USERS
-#
-##############
-
-
-def _users_for_tenant(users, tenant):
-    u_for_t = []
-    for user in users:
-        for n in user:
-            if user[n]['tenant'] == tenant:
-                u_for_t.append(user[n])
-    return u_for_t
-
-
-def _tenants_from_users(users):
-    tenants = set()
-    for user in users:
-        for n in user:
-            tenants.add(user[n]['tenant'])
-    return tenants
-
-
-def _assign_swift_role(user, swift_role):
-    admin = keystone_admin()
-    roles = admin.roles.list_roles()
-    role = next(r for r in roles if r['name'] == swift_role)
-    LOG.debug(USERS[user])
-    try:
-        admin.roles.create_user_role_on_project(
-            USERS[user]['tenant_id'],
-            USERS[user]['id'],
-            role['id'])
-    except lib_exc.Conflict:
-        # don't care if it's already assigned
-        pass
-
-
-def create_users(users):
-    """Create tenants from resource definition.
-
-    Don't create the tenants if they already exist.
-    """
-    global USERS
-    LOG.info("Creating users")
-    admin = keystone_admin()
-    for u in users:
-        try:
-            tenant = identity.get_tenant_by_name(admin.tenants, u['tenant'])
-        except lib_exc.NotFound:
-            LOG.error("Tenant: %s - not found" % u['tenant'])
-            continue
-        try:
-            identity.get_user_by_username(admin.tenants,
-                                          tenant['id'], u['name'])
-            LOG.warning("User '%s' already exists in this environment"
-                        % u['name'])
-        except lib_exc.NotFound:
-            admin.users.create_user(
-                name=u['name'], password=u['pass'],
-                tenantId=tenant['id'],
-                email="%s@%s" % (u['name'], tenant['id']),
-                enabled=True)
-
-
-def destroy_users(users):
-    admin = keystone_admin()
-    for user in users:
-        tenant_id = identity.get_tenant_by_name(admin.tenants,
-                                                user['tenant'])['id']
-        user_id = identity.get_user_by_username(admin.tenants,
-                                                tenant_id, user['name'])['id']
-        admin.users.delete_user(user_id)
-
-
-def collect_users(users):
-    global USERS
-    LOG.info("Collecting users")
-    admin = keystone_admin()
-    for u in users:
-        tenant = identity.get_tenant_by_name(admin.tenants, u['tenant'])
-        u['tenant_id'] = tenant['id']
-        USERS[u['name']] = u
-        body = identity.get_user_by_username(admin.tenants,
-                                             tenant['id'], u['name'])
-        USERS[u['name']]['id'] = body['id']
-
-
-class JavelinCheck(unittest.TestCase):
-    def __init__(self, users, resources):
-        super(JavelinCheck, self).__init__()
-        self.users = users
-        self.res = resources
-
-    def runTest(self, *args):
-        pass
-
-    def _ping_ip(self, ip_addr, count, namespace=None):
-        if namespace is None:
-            ping_cmd = "ping -c1 " + ip_addr
-        else:
-            ping_cmd = "sudo ip netns exec %s ping -c1 %s" % (namespace,
-                                                              ip_addr)
-        for current in range(count):
-            return_code = os.system(ping_cmd)
-            if return_code is 0:
-                break
-        self.assertNotEqual(current, count - 1,
-                            "Server is not pingable at %s" % ip_addr)
-
-    def check(self):
-        self.check_users()
-        self.check_objects()
-        self.check_servers()
-        self.check_volumes()
-        self.check_secgroups()
-
-        # validate neutron is enabled and ironic disabled:
-        # Tenant network isolation is not supported when using ironic.
-        # "admin" has set up a neutron flat network environment within a shared
-        # fixed network for all tenants to use.
-        # In this case, network/subnet/router creation can be skipped and the
-        # server booted the same as nova network.
-        if (CONF.service_available.neutron and
-                not CONF.baremetal.driver_enabled):
-            self.check_networking()
-
-    def check_users(self):
-        """Check that the users we expect to exist, do.
-
-        We don't use the resource list for this because we need to validate
-        that things like tenantId didn't drift across versions.
-        """
-        LOG.info("checking users")
-        for name, user in six.iteritems(self.users):
-            client = keystone_admin()
-            found = client.users.show_user(user['id'])['user']
-            self.assertEqual(found['name'], user['name'])
-            self.assertEqual(found['tenantId'], user['tenant_id'])
-
-            # also ensure we can auth with that user, and do something
-            # on the cloud. We don't care about the results except that it
-            # remains authorized.
-            client = client_for_user(user['name'])
-            client.servers.list_servers()
-
-    def check_objects(self):
-        """Check that the objects created are still there."""
-        if not self.res.get('objects'):
-            return
-        LOG.info("checking objects")
-        for obj in self.res['objects']:
-            client = client_for_user(obj['owner'])
-            r, contents = client.objects.get_object(
-                obj['container'], obj['name'])
-            source = _file_contents(obj['file'])
-            self.assertEqual(contents, source)
-
-    def check_servers(self):
-        """Check that the servers are still up and running."""
-        if not self.res.get('servers'):
-            return
-        LOG.info("checking servers")
-        for server in self.res['servers']:
-            client = client_for_user(server['owner'])
-            found = _get_server_by_name(client, server['name'])
-            self.assertIsNotNone(
-                found,
-                "Couldn't find expected server %s" % server['name'])
-
-            found = client.servers.show_server(found['id'])['server']
-            # validate neutron is enabled and ironic disabled:
-            if (CONF.service_available.neutron and
-                    not CONF.baremetal.driver_enabled):
-                _floating_is_alive = False
-                for network_name, body in found['addresses'].items():
-                    for addr in body:
-                        ip = addr['addr']
-                        # Use floating IP, fixed IP or other type to
-                        # reach the server.
-                        # This is useful in multi-node environment.
-                        if CONF.validation.connect_method == 'floating':
-                            if addr.get('OS-EXT-IPS:type',
-                                        'floating') == 'floating':
-                                self._ping_ip(ip, 60)
-                                _floating_is_alive = True
-                        elif CONF.validation.connect_method == 'fixed':
-                            if addr.get('OS-EXT-IPS:type',
-                                        'fixed') == 'fixed':
-                                namespace = _get_router_namespace(client,
-                                                                  network_name)
-                                self._ping_ip(ip, 60, namespace)
-                        else:
-                            self._ping_ip(ip, 60)
-                # If CONF.validation.connect_method is floating, validate
-                # that the floating IP is attached to the server and the
-                # the server is pingable.
-                if CONF.validation.connect_method == 'floating':
-                    self.assertTrue(_floating_is_alive,
-                                    "Server %s has no floating IP." %
-                                    server['name'])
-            else:
-                addr = found['addresses']['private'][0]['addr']
-                self._ping_ip(addr, 60)
-
-    def check_secgroups(self):
-        """Check that the security groups still exist."""
-        LOG.info("Checking security groups")
-        for secgroup in self.res['secgroups']:
-            client = client_for_user(secgroup['owner'])
-            found = _get_resource_by_name(client.secgroups, 'security_groups',
-                                          secgroup['name'])
-            self.assertIsNotNone(
-                found,
-                "Couldn't find expected secgroup %s" % secgroup['name'])
-
-    def check_volumes(self):
-        """Check that the volumes are still there and attached."""
-        if not self.res.get('volumes'):
-            return
-        LOG.info("checking volumes")
-        for volume in self.res['volumes']:
-            client = client_for_user(volume['owner'])
-            vol_body = _get_volume_by_name(client, volume['name'])
-            self.assertIsNotNone(
-                vol_body,
-                "Couldn't find expected volume %s" % volume['name'])
-
-            # Verify that a volume's attachment retrieved
-            server_id = _get_server_by_name(client, volume['server'])['id']
-            attachment = client.volumes.get_attachment_from_volume(vol_body)
-            self.assertEqual(vol_body['id'], attachment['volume_id'])
-            self.assertEqual(server_id, attachment['server_id'])
-
-    def check_networking(self):
-        """Check that the networks are still there."""
-        for res_type in ('networks', 'subnets', 'routers'):
-            for res in self.res[res_type]:
-                client = client_for_user(res['owner'])
-                found = _get_resource_by_name(client.networks, res_type,
-                                              res['name'])
-                self.assertIsNotNone(
-                    found,
-                    "Couldn't find expected resource %s" % res['name'])
-
-
-#######################
-#
-# OBJECTS
-#
-#######################
-
-
-def _file_contents(fname):
-    with open(fname, 'r') as f:
-        return f.read()
-
-
-def create_objects(objects):
-    if not objects:
-        return
-    LOG.info("Creating objects")
-    for obj in objects:
-        LOG.debug("Object %s" % obj)
-        swift_role = obj.get('swift_role', 'Member')
-        _assign_swift_role(obj['owner'], swift_role)
-        client = client_for_user(obj['owner'])
-        client.containers.create_container(obj['container'])
-        client.objects.create_object(
-            obj['container'], obj['name'],
-            _file_contents(obj['file']))
-
-
-def destroy_objects(objects):
-    for obj in objects:
-        client = client_for_user(obj['owner'])
-        r, body = client.objects.delete_object(obj['container'], obj['name'])
-        if not (200 <= int(r['status']) < 299):
-            raise ValueError("unable to destroy object: [%s] %s" % (r, body))
-
-
-#######################
-#
-# IMAGES
-#
-#######################
-
-
-def _resolve_image(image, imgtype):
-    name = image[imgtype]
-    fname = os.path.join(OPTS.devstack_base, image['imgdir'], name)
-    return name, fname
-
-
-def _get_image_by_name(client, name):
-    body = client.images.list_images()
-    for image in body:
-        if name == image['name']:
-            return image
-    return None
-
-
-def create_images(images):
-    if not images:
-        return
-    LOG.info("Creating images")
-    for image in images:
-        client = client_for_user(image['owner'])
-
-        # DEPRECATED: 'format' was used for ami images
-        # Use 'disk_format' and 'container_format' instead
-        if 'format' in image:
-            LOG.warning("Deprecated: 'format' is deprecated for images "
-                        "description. Please use 'disk_format' and 'container_"
-                        "format' instead.")
-            image['disk_format'] = image['format']
-            image['container_format'] = image['format']
-
-        # only upload a new image if the name isn't there
-        if _get_image_by_name(client, image['name']):
-            LOG.info("Image '%s' already exists" % image['name'])
-            continue
-
-        # special handling for 3 part image
-        extras = {}
-        if image['disk_format'] == 'ami':
-            name, fname = _resolve_image(image, 'aki')
-            aki = client.images.create_image(
-                'javelin_' + name, 'aki', 'aki')
-            client.images.store_image_file(aki.get('id'), open(fname, 'r'))
-            extras['kernel_id'] = aki.get('id')
-
-            name, fname = _resolve_image(image, 'ari')
-            ari = client.images.create_image(
-                'javelin_' + name, 'ari', 'ari')
-            client.images.store_image_file(ari.get('id'), open(fname, 'r'))
-            extras['ramdisk_id'] = ari.get('id')
-
-        _, fname = _resolve_image(image, 'file')
-        body = client.images.create_image(
-            image['name'], image['container_format'],
-            image['disk_format'], **extras)
-        image_id = body.get('id')
-        client.images.store_image_file(image_id, open(fname, 'r'))
-
-
-def destroy_images(images):
-    if not images:
-        return
-    LOG.info("Destroying images")
-    for image in images:
-        client = client_for_user(image['owner'])
-
-        response = _get_image_by_name(client, image['name'])
-        if not response:
-            LOG.info("Image '%s' does not exist" % image['name'])
-            continue
-        client.images.delete_image(response['id'])
-
-
-#######################
-#
-# NETWORKS
-#
-#######################
-
-def _get_router_namespace(client, network):
-    network_id = _get_resource_by_name(client.networks,
-                                       'networks', network)['id']
-    n_body = client.routers.list_routers()
-    for router in n_body['routers']:
-        router_id = router['id']
-        r_body = client.ports.list_ports(device_id=router_id)
-        for port in r_body['ports']:
-            if port['network_id'] == network_id:
-                return "qrouter-%s" % router_id
-
-
-def _get_resource_by_name(client, resource, name):
-    get_resources = getattr(client, 'list_%s' % resource)
-    if get_resources is None:
-        raise AttributeError("client doesn't have method list_%s" % resource)
-    # Until all tempest client methods are changed to return only one value,
-    # we cannot assume they all have the same signature so we need to discard
-    # the unused response first value it two values are being returned.
-    body = get_resources()
-    if isinstance(body, tuple):
-        body = body[1]
-    if isinstance(body, dict):
-        body = body[resource]
-    for res in body:
-        if name == res['name']:
-            return res
-    raise ValueError('%s not found in %s resources' % (name, resource))
-
-
-def create_networks(networks):
-    LOG.info("Creating networks")
-    for network in networks:
-        client = client_for_user(network['owner'])
-
-        # only create a network if the name isn't here
-        body = client.networks.list_networks()
-        if any(item['name'] == network['name'] for item in body['networks']):
-            LOG.warning("Duplicated network name: %s" % network['name'])
-            continue
-
-        client.networks.create_network(name=network['name'])
-
-
-def destroy_networks(networks):
-    LOG.info("Destroying subnets")
-    for network in networks:
-        client = client_for_user(network['owner'])
-        network_id = _get_resource_by_name(client.networks, 'networks',
-                                           network['name'])['id']
-        client.networks.delete_network(network_id)
-
-
-def create_subnets(subnets):
-    LOG.info("Creating subnets")
-    for subnet in subnets:
-        client = client_for_user(subnet['owner'])
-
-        network = _get_resource_by_name(client.networks, 'networks',
-                                        subnet['network'])
-        ip_version = netaddr.IPNetwork(subnet['range']).version
-        # ensure we don't overlap with another subnet in the network
-        try:
-            client.networks.create_subnet(network_id=network['id'],
-                                          cidr=subnet['range'],
-                                          name=subnet['name'],
-                                          ip_version=ip_version)
-        except lib_exc.BadRequest as e:
-            is_overlapping_cidr = 'overlaps with another subnet' in str(e)
-            if not is_overlapping_cidr:
-                raise
-
-
-def destroy_subnets(subnets):
-    LOG.info("Destroying subnets")
-    for subnet in subnets:
-        client = client_for_user(subnet['owner'])
-        subnet_id = _get_resource_by_name(client.subnets,
-                                          'subnets', subnet['name'])['id']
-        client.subnets.delete_subnet(subnet_id)
-
-
-def create_routers(routers):
-    LOG.info("Creating routers")
-    for router in routers:
-        client = client_for_user(router['owner'])
-
-        # only create a router if the name isn't here
-        body = client.routers.list_routers()
-        if any(item['name'] == router['name'] for item in body['routers']):
-            LOG.warning("Duplicated router name: %s" % router['name'])
-            continue
-
-        client.networks.create_router(name=router['name'])
-
-
-def destroy_routers(routers):
-    LOG.info("Destroying routers")
-    for router in routers:
-        client = client_for_user(router['owner'])
-        router_id = _get_resource_by_name(client.networks,
-                                          'routers', router['name'])['id']
-        for subnet in router['subnet']:
-            subnet_id = _get_resource_by_name(client.networks,
-                                              'subnets', subnet)['id']
-            client.routers.remove_router_interface(router_id,
-                                                   subnet_id=subnet_id)
-        client.routers.delete_router(router_id)
-
-
-def add_router_interface(routers):
-    for router in routers:
-        client = client_for_user(router['owner'])
-        router_id = _get_resource_by_name(client.networks,
-                                          'routers', router['name'])['id']
-
-        for subnet in router['subnet']:
-            subnet_id = _get_resource_by_name(client.networks,
-                                              'subnets', subnet)['id']
-            # connect routers to their subnets
-            client.routers.add_router_interface(router_id,
-                                                subnet_id=subnet_id)
-        # connect routers to external network if set to "gateway"
-        if router['gateway']:
-            if CONF.network.public_network_id:
-                ext_net = CONF.network.public_network_id
-                client.routers.update_router(
-                    router_id, set_enable_snat=True,
-                    external_gateway_info={"network_id": ext_net})
-            else:
-                raise ValueError('public_network_id is not configured.')
-
-
-#######################
-#
-# SERVERS
-#
-#######################
-
-def _get_server_by_name(client, name):
-    body = client.servers.list_servers()
-    for server in body['servers']:
-        if name == server['name']:
-            return server
-    return None
-
-
-def _get_flavor_by_name(client, name):
-    body = client.flavors.list_flavors()['flavors']
-    for flavor in body:
-        if name == flavor['name']:
-            return flavor
-    return None
-
-
-def create_servers(servers):
-    if not servers:
-        return
-    LOG.info("Creating servers")
-    for server in servers:
-        client = client_for_user(server['owner'])
-
-        if _get_server_by_name(client, server['name']):
-            LOG.info("Server '%s' already exists" % server['name'])
-            continue
-
-        image_id = _get_image_by_name(client, server['image'])['id']
-        flavor_id = _get_flavor_by_name(client, server['flavor'])['id']
-        # validate neutron is enabled and ironic disabled
-        kwargs = dict()
-        if (CONF.service_available.neutron and
-                not CONF.baremetal.driver_enabled and server.get('networks')):
-            get_net_id = lambda x: (_get_resource_by_name(
-                client.networks, 'networks', x)['id'])
-            kwargs['networks'] = [{'uuid': get_net_id(network)}
-                                  for network in server['networks']]
-        body = client.servers.create_server(
-            name=server['name'], imageRef=image_id, flavorRef=flavor_id,
-            **kwargs)['server']
-        server_id = body['id']
-        client.servers.wait_for_server_status(server_id, 'ACTIVE')
-        # create security group(s) after server spawning
-        for secgroup in server['secgroups']:
-            client.servers.add_security_group(server_id, name=secgroup)
-        if CONF.validation.connect_method == 'floating':
-            floating_ip_pool = server.get('floating_ip_pool')
-            floating_ip = client.floating_ips.create_floating_ip(
-                pool_name=floating_ip_pool)['floating_ip']
-            client.floating_ips.associate_floating_ip_to_server(
-                floating_ip['ip'], server_id)
-
-
-def destroy_servers(servers):
-    if not servers:
-        return
-    LOG.info("Destroying servers")
-    for server in servers:
-        client = client_for_user(server['owner'])
-
-        response = _get_server_by_name(client, server['name'])
-        if not response:
-            LOG.info("Server '%s' does not exist" % server['name'])
-            continue
-
-        # TODO(EmilienM): disassociate floating IP from server and release it.
-        client.servers.delete_server(response['id'])
-        waiters.wait_for_server_termination(client.servers, response['id'],
-                                            ignore_error=True)
-
-
-def create_secgroups(secgroups):
-    LOG.info("Creating security groups")
-    for secgroup in secgroups:
-        client = client_for_user(secgroup['owner'])
-
-        # only create a security group if the name isn't here
-        # i.e. a security group may be used by another server
-        # only create a router if the name isn't here
-        body = client.secgroups.list_security_groups()['security_groups']
-        if any(item['name'] == secgroup['name'] for item in body):
-            LOG.warning("Security group '%s' already exists" %
-                        secgroup['name'])
-            continue
-
-        body = client.secgroups.create_security_group(
-            name=secgroup['name'],
-            description=secgroup['description'])['security_group']
-        secgroup_id = body['id']
-        # for each security group, create the rules
-        for rule in secgroup['rules']:
-            ip_proto, from_port, to_port, cidr = rule.split()
-            client.secrules.create_security_group_rule(
-                parent_group_id=secgroup_id, ip_protocol=ip_proto,
-                from_port=from_port, to_port=to_port, cidr=cidr)
-
-
-def destroy_secgroups(secgroups):
-    LOG.info("Destroying security groups")
-    for secgroup in secgroups:
-        client = client_for_user(secgroup['owner'])
-        sg_id = _get_resource_by_name(client.secgroups,
-                                      'security_groups',
-                                      secgroup['name'])
-        # sg rules are deleted automatically
-        client.secgroups.delete_security_group(sg_id['id'])
-
-
-#######################
-#
-# VOLUMES
-#
-#######################
-
-def _get_volume_by_name(client, name):
-    body = client.volumes.list_volumes()['volumes']
-    for volume in body:
-        if name == volume['display_name']:
-            return volume
-    return None
-
-
-def create_volumes(volumes):
-    if not volumes:
-        return
-    LOG.info("Creating volumes")
-    for volume in volumes:
-        client = client_for_user(volume['owner'])
-
-        # only create a volume if the name isn't here
-        if _get_volume_by_name(client, volume['name']):
-            LOG.info("volume '%s' already exists" % volume['name'])
-            continue
-
-        size = volume['gb']
-        v_name = volume['name']
-        body = client.volumes.create_volume(size=size,
-                                            display_name=v_name)['volume']
-        waiters.wait_for_volume_status(client.volumes, body['id'], 'available')
-
-
-def destroy_volumes(volumes):
-    for volume in volumes:
-        client = client_for_user(volume['owner'])
-        volume_id = _get_volume_by_name(client, volume['name'])['id']
-        client.volumes.detach_volume(volume_id)
-        client.volumes.delete_volume(volume_id)
-
-
-def attach_volumes(volumes):
-    for volume in volumes:
-        client = client_for_user(volume['owner'])
-        server_id = _get_server_by_name(client, volume['server'])['id']
-        volume_id = _get_volume_by_name(client, volume['name'])['id']
-        device = volume['device']
-        client.volumes.attach_volume(volume_id,
-                                     instance_uuid=server_id,
-                                     mountpoint=device)
-
-
-#######################
-#
-# MAIN LOGIC
-#
-#######################
-
-def create_resources():
-    LOG.info("Creating Resources")
-    # first create keystone level resources, and we need to be admin
-    # for this.
-    create_tenants(RES['tenants'])
-    create_users(RES['users'])
-    collect_users(RES['users'])
-
-    # next create resources in a well known order
-    create_objects(RES['objects'])
-    create_images(RES['images'])
-
-    # validate neutron is enabled and ironic is disabled
-    if CONF.service_available.neutron and not CONF.baremetal.driver_enabled:
-        create_networks(RES['networks'])
-        create_subnets(RES['subnets'])
-        create_routers(RES['routers'])
-        add_router_interface(RES['routers'])
-
-    create_secgroups(RES['secgroups'])
-    create_volumes(RES['volumes'])
-
-    # Only attempt attaching the volumes if servers are defined in the
-    # resource file
-    if 'servers' in RES:
-        create_servers(RES['servers'])
-        attach_volumes(RES['volumes'])
-
-
-def destroy_resources():
-    LOG.info("Destroying Resources")
-    # Destroy in inverse order of create
-    destroy_servers(RES['servers'])
-    destroy_images(RES['images'])
-    destroy_objects(RES['objects'])
-    destroy_volumes(RES['volumes'])
-    if CONF.service_available.neutron and not CONF.baremetal.driver_enabled:
-        destroy_routers(RES['routers'])
-        destroy_subnets(RES['subnets'])
-        destroy_networks(RES['networks'])
-    destroy_secgroups(RES['secgroups'])
-    destroy_users(RES['users'])
-    destroy_tenants(RES['tenants'])
-    LOG.warning("Destroy mode incomplete")
-
-
-def get_options():
-    global OPTS
-    parser = argparse.ArgumentParser(
-        description='Create and validate a fixed set of OpenStack resources')
-    parser.add_argument('-m', '--mode',
-                        metavar='<create|check|destroy>',
-                        required=True,
-                        help=('One of (create, check, destroy)'))
-    parser.add_argument('-r', '--resources',
-                        required=True,
-                        metavar='resourcefile.yaml',
-                        help='Resources definition yaml file')
-
-    parser.add_argument(
-        '-d', '--devstack-base',
-        required=True,
-        metavar='/opt/stack/old',
-        help='Devstack base directory for retrieving artifacts')
-    parser.add_argument(
-        '-c', '--config-file',
-        metavar='/etc/tempest.conf',
-        help='path to javelin2(tempest) config file')
-
-    # auth bits, letting us also just source the devstack openrc
-    parser.add_argument('--os-username',
-                        metavar='<auth-user-name>',
-                        default=os.environ.get('OS_USERNAME'),
-                        help=('Defaults to env[OS_USERNAME].'))
-    parser.add_argument('--os-password',
-                        metavar='<auth-password>',
-                        default=os.environ.get('OS_PASSWORD'),
-                        help=('Defaults to env[OS_PASSWORD].'))
-    parser.add_argument('--os-tenant-name',
-                        metavar='<auth-tenant-name>',
-                        default=os.environ.get('OS_TENANT_NAME'),
-                        help=('Defaults to env[OS_TENANT_NAME].'))
-
-    OPTS = parser.parse_args()
-    if OPTS.mode not in ('create', 'check', 'destroy'):
-        print("ERROR: Unknown mode -m %s\n" % OPTS.mode)
-        parser.print_help()
-        sys.exit(1)
-    if OPTS.config_file:
-        config.CONF.set_config_path(OPTS.config_file)
-
-
-def setup_logging():
-    global LOG
-    logging.setup(CONF, __name__)
-    LOG = logging.getLogger(__name__)
-
-
-def main():
-    print("Javelin is deprecated and will be removed from Tempest in the "
-          "future.")
-    global RES
-    get_options()
-    setup_logging()
-    RES.update(load_resources(OPTS.resources))
-
-    if OPTS.mode == 'create':
-        create_resources()
-        # Make sure the resources we just created actually work
-        checker = JavelinCheck(USERS, RES)
-        checker.check()
-    elif OPTS.mode == 'check':
-        collect_users(RES['users'])
-        checker = JavelinCheck(USERS, RES)
-        checker.check()
-    elif OPTS.mode == 'destroy':
-        collect_users(RES['users'])
-        destroy_resources()
-    else:
-        LOG.error('Unknown mode %s' % OPTS.mode)
-        return 1
-    LOG.info('javelin2 successfully finished')
-    return 0
-
-if __name__ == "__main__":
-    sys.exit(main())
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/resources.yaml b/tempest/cmd/resources.yaml
deleted file mode 100644
index 5c62ee3..0000000
--- a/tempest/cmd/resources.yaml
+++ /dev/null
@@ -1,95 +0,0 @@
-# This is a yaml description for the most basic definitions
-# of what should exist across the resource boundary. Perhaps
-# one day this will grow into a Heat resource template, but as
-# Heat isn't a known working element in the upgrades, we do
-# this much simpler thing for now.
-
-tenants:
-  - javelin
-  - discuss
-
-users:
-  - name: javelin
-    pass: gungnir
-    tenant: javelin
-  - name: javelin2
-    pass: gungnir2
-    tenant: discuss
-
-secgroups:
-  - name: angon
-    owner: javelin
-    description: angon
-    rules:
-      - 'icmp -1 -1 0.0.0.0/0'
-      - 'tcp 22 22 0.0.0.0/0'
-  - name: baobab
-    owner: javelin
-    description: baobab
-    rules:
-      - 'tcp 80 80 0.0.0.0/0'
-
-# resources that we want to create
-images:
-  - name: javelin_cirros
-    owner: javelin
-    imgdir: files/images/cirros-0.3.2-x86_64-uec
-    file: cirros-0.3.2-x86_64-blank.img
-    format: ami
-    aki: cirros-0.3.2-x86_64-vmlinuz
-    ari: cirros-0.3.2-x86_64-initrd
-volumes:
-  - name: assegai
-    server: peltast
-    owner: javelin
-    gb: 1
-    device: /dev/vdb
-  - name: pifpouf
-    server: hoplite
-    owner: javelin
-    gb: 2
-    device: /dev/vdb
-networks:
-  - name: world1
-    owner: javelin
-  - name: world2
-    owner: javelin
-subnets:
-  - name: subnet1
-    range: 10.1.0.0/24
-    network: world1
-    owner: javelin
-  - name: subnet2
-    range: 192.168.1.0/24
-    network: world2
-    owner: javelin
-routers:
-  - name: connector
-    owner: javelin
-    gateway: true
-    subnet:
-      - subnet1
-      - subnet2
-servers:
-  - name: peltast
-    owner: javelin
-    flavor: m1.small
-    image: javelin_cirros
-    networks:
-      - world1
-    secgroups:
-      - angon
-      - baobab
-  - name: hoplite
-    owner: javelin
-    flavor: m1.medium
-    image: javelin_cirros
-    networks:
-      - world2
-    secgroups:
-      - angon
-objects:
-  - container: jc1
-    name: javelin1
-    owner: javelin
-    file: /etc/hosts
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index b6b70d7..fef836c 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -23,9 +23,9 @@
                    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
-seperated regex, with '#' used to signify the start of a comment on a line.
+separated regex, with '#' used to signify the start of a comment on a line.
 For example::
 
     # Regex file
@@ -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 seperate regex on each "
+                                        "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/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index da7f426..0f868a9 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -21,13 +21,14 @@
 Runtime Arguments
 -----------------
 
-**--subunit, -s**: (Required) The path to the subunit file being parsed
+**--subunit, -s**: (Optional) The path to the subunit file being parsed,
+defaults to stdin
 
 **--non-subunit-name, -n**: (Optional) The file_name that the logs are being
 stored in
 
-**--output-file, -o**: (Required) The path where the JSON output will be
-written to
+**--output-file, -o**: (Optional) The path where the JSON output will be
+written to. This contains more information than is present in stdout.
 
 **--ports, -p**: (Optional) The path to a JSON file describing the ports being
 used by different services
@@ -35,13 +36,14 @@
 Usage
 -----
 
-subunit-describe-calls will take in a file path via the --subunit parameter
-which contains either a subunit v1 or v2 stream. This is then parsed checking
-for details contained in the file_bytes of the --non-subunit-name parameter
-(the default is pythonlogging which is what Tempest uses to store logs). By
-default the OpenStack Kilo release port defaults (http://bit.ly/22jpF5P)
-are used unless a file is provided via the --ports option. The resulting output
-is dumped in JSON output to the path provided in the --output-file option.
+subunit-describe-calls will take in either stdin subunit v1 or v2 stream or a
+file path which contains either a subunit v1 or v2 stream passed via the
+--subunit parameter. This is then parsed checking for details contained in the
+file_bytes of the --non-subunit-name parameter (the default is pythonlogging
+which is what Tempest uses to store logs). By default the OpenStack Kilo
+release port defaults (http://bit.ly/22jpF5P) are used unless a file is
+provided via the --ports option. The resulting output is dumped in JSON output
+to the path provided in the --output-file option.
 
 Ports file JSON structure
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +66,11 @@
               "verb": "HTTP Verb",
               "service": "Name of the service",
               "url": "A shortened version of the URL called",
-              "status_code": "The status code of the response"
+              "status_code": "The status code of the response",
+              "request_headers": "The headers of the request",
+              "request_body": "The body of the request",
+              "response_headers": "The headers of the response",
+              "response_body": "The body of the response"
           }
       ]
   }
@@ -75,6 +81,7 @@
 import json
 import os
 import re
+import sys
 
 import subunit
 import testtools
@@ -91,6 +98,9 @@
                         '(?P<verb>\w*) (?P<url>.*) .*')
     port_re = re.compile(r'.*:(?P<port>\d+).*')
     path_re = re.compile(r'http[s]?://[^/]*/(?P<path>.*)')
+    request_re = re.compile(r'.* Request - Headers: (?P<headers>.*)')
+    response_re = re.compile(r'.* Response - Headers: (?P<headers>.*)')
+    body_re = re.compile(r'.*Body: (?P<body>.*)')
 
     # Based on mitaka defaults:
     # http://docs.openstack.org/mitaka/config-reference/
@@ -151,15 +161,46 @@
 
         calls = []
         for _, detail in details.items():
+            in_request = False
+            in_response = False
+            current_call = {}
             for line in detail.as_text().split("\n"):
-                match = self.url_re.match(line)
-                if match is not None:
-                    calls.append({
-                        "name": match.group("name"),
-                        "verb": match.group("verb"),
-                        "status_code": match.group("code"),
-                        "service": self.get_service(match.group("url")),
-                        "url": self.url_path(match.group("url"))})
+                url_match = self.url_re.match(line)
+                request_match = self.request_re.match(line)
+                response_match = self.response_re.match(line)
+                body_match = self.body_re.match(line)
+
+                if url_match is not None:
+                    if current_call != {}:
+                        calls.append(current_call.copy())
+                        current_call = {}
+                        in_request, in_response = False, False
+                    current_call.update({
+                        "name": url_match.group("name"),
+                        "verb": url_match.group("verb"),
+                        "status_code": url_match.group("code"),
+                        "service": self.get_service(url_match.group("url")),
+                        "url": self.url_path(url_match.group("url"))})
+                elif request_match is not None:
+                    in_request, in_response = True, False
+                    current_call.update(
+                        {"request_headers": request_match.group("headers")})
+                elif in_request and body_match is not None:
+                    in_request = False
+                    current_call.update(
+                        {"request_body": body_match.group(
+                            "body")})
+                elif response_match is not None:
+                    in_request, in_response = False, True
+                    current_call.update(
+                        {"response_headers": response_match.group(
+                            "headers")})
+                elif in_response and body_match is not None:
+                    in_response = False
+                    current_call.update(
+                        {"response_body": body_match.group("body")})
+            if current_call != {}:
+                calls.append(current_call.copy())
 
         return calls
 
@@ -203,11 +244,12 @@
         desc = "Outputs all HTTP calls a given test made that were logged."
         super(ArgumentParser, self).__init__(description=desc)
 
-        self.prog = "Argument Parser"
+        self.prog = "subunit-describe-calls"
 
         self.add_argument(
-            "-s", "--subunit", metavar="<subunit file>", required=True,
-            default=None, help="The path to the subunit output file.")
+            "-s", "--subunit", metavar="<subunit file>",
+            nargs="?", type=argparse.FileType('rb'), default=sys.stdin,
+            help="The path to the subunit output file.")
 
         self.add_argument(
             "-n", "--non-subunit-name", metavar="<non subunit name>",
@@ -216,19 +258,18 @@
 
         self.add_argument(
             "-o", "--output-file", metavar="<output file>", default=None,
-            help="The output file name for the json.", required=True)
+            help="The output file name for the json.")
 
         self.add_argument(
             "-p", "--ports", metavar="<ports file>", default=None,
             help="A JSON file describing the ports for each service.")
 
 
-def parse(subunit_file, non_subunit_name, ports):
+def parse(stream, non_subunit_name, ports):
     if ports is not None and os.path.exists(ports):
         ports = json.loads(open(ports).read())
 
     url_parser = UrlParser(ports)
-    stream = open(subunit_file, 'rb')
     suite = subunit.ByteStreamToStreamResult(
         stream, non_subunit_name=non_subunit_name)
     result = testtools.StreamToExtendedDecorator(url_parser)
@@ -248,8 +289,21 @@
 
 
 def output(url_parser, output_file):
-    with open(output_file, "w") as outfile:
-        outfile.write(json.dumps(url_parser.test_logs))
+    if output_file is not None:
+        with open(output_file, "w") as outfile:
+            outfile.write(json.dumps(url_parser.test_logs))
+        return
+
+    for test_name, items in url_parser.test_logs.iteritems():
+        sys.stdout.write('{0}\n'.format(test_name))
+        if not items:
+            sys.stdout.write('\n')
+            continue
+        for item in items:
+            sys.stdout.write('\t- {0} {1} request for {2} to {3}\n'.format(
+                item.get('status_code'), item.get('verb'),
+                item.get('service'), item.get('url')))
+        sys.stdout.write('\n')
 
 
 def entry_point():
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..194b9e9 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -101,7 +101,7 @@
                 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
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index 2ca9f40..4e3c395 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -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/utils/net_utils.py b/tempest/common/utils/net_utils.py
index d98fb32..f0d3da3 100644
--- a/tempest/common/utils/net_utils.py
+++ b/tempest/common/utils/net_utils.py
@@ -12,7 +12,6 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import itertools
 import netaddr
 
 from tempest.lib import exceptions as lib_exc
@@ -38,11 +37,17 @@
         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
-    ip_list = [str(ip) for ip in itertools.islice(av_set, count)]
-
-    if len(ip_list) != count:
-        msg = "Insufficient IP addresses available"
-        raise lib_exc.BadRequest(message=msg)
-
-    return ip_list
+    addrs = []
+    for cidr in reversed(av_set.iter_cidrs()):
+        for ip in reversed(cidr):
+            addrs.append(str(ip))
+            if len(addrs) == count:
+                return addrs
+    msg = "Insufficient IP addresses available"
+    raise lib_exc.BadRequest(message=msg)
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index df08e30..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
@@ -141,7 +139,7 @@
     while int(time.time()) - start < client.build_timeout:
         image = show_image(image_id)
         # Compute image client returns response wrapped in 'image' element
-        # which is not case with Glance image client.
+        # which is not the case with Glance image client.
         if 'image' in image:
             image = image['image']
 
diff --git a/tempest/config.py b/tempest/config.py
index 0c2b913..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
 
 
@@ -173,6 +174,16 @@
                      "a domain scoped token to use admin APIs")
 ]
 
+service_clients_group = cfg.OptGroup(name='service-clients',
+                                     title="Service Clients Options")
+
+ServiceClientsGroup = [
+    cfg.IntOpt('http_timeout',
+               default=60,
+               help='Timeout in seconds to wait for the http request to '
+                    'return'),
+]
+
 identity_feature_group = cfg.OptGroup(name='identity-feature-enabled',
                                       title='Enabled Identity Features')
 
@@ -369,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'),
@@ -491,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 "
@@ -642,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')]),
 ]
@@ -1119,6 +1131,7 @@
     (compute_group, ComputeGroup),
     (compute_features_group, ComputeFeaturesGroup),
     (identity_group, IdentityGroup),
+    (service_clients_group, ServiceClientsGroup),
     (identity_feature_group, IdentityFeatureGroup),
     (image_group, ImageGroup),
     (image_feature_group, ImageFeaturesGroup),
@@ -1184,6 +1197,7 @@
         self.compute = _CONF.compute
         self.compute_feature_enabled = _CONF['compute-feature-enabled']
         self.identity = _CONF.identity
+        self.service_clients = _CONF['service-clients']
         self.identity_feature_enabled = _CONF['identity-feature-enabled']
         self.image = _CONF.image
         self.image_feature_enabled = _CONF['image-feature-enabled']
@@ -1275,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):
@@ -1372,6 +1395,7 @@
         * `disable_ssl_certificate_validation`
         * `ca_certs`
         * `trace_requests`
+        * `http_timeout`
 
     The dict returned by this does not fit a few service clients:
 
@@ -1393,7 +1417,8 @@
         'disable_ssl_certificate_validation':
             CONF.identity.disable_ssl_certificate_validation,
         'ca_certs': CONF.identity.ca_certificates_file,
-        'trace_requests': CONF.debug.trace_requests
+        'trace_requests': CONF.debug.trace_requests,
+        'http_timeout': CONF.service_clients.http_timeout
     }
 
     if service_client_name is None:
@@ -1432,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/exceptions.py b/tempest/exceptions.py
index f534f30..272f6e3 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -63,14 +63,15 @@
 
 
 class ServerUnreachable(exceptions.TempestException):
-    message = "The server is not reachable via the configured network"
+    message = ("Server %(server_id)s is not reachable via "
+               "the configured network")
 
 
 # NOTE(andreaf) This exception is added here to facilitate the migration
 # of get_network_from_name and preprov_creds to tempest.lib, and it should
 # be migrated along with them
 class InvalidTestResource(exceptions.TempestException):
-    message = "%(name) is not a valid %(type), or the name is ambiguous"
+    message = "%(name)s is not a valid %(type)s, or the name is ambiguous"
 
 
 class RFCViolation(exceptions.RestClientException):
diff --git a/tempest/lib/api_schema/response/compute/v2_16/__init__.py b/tempest/lib/api_schema/response/compute/v2_16/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_16/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_16/servers.py b/tempest/lib/api_schema/response/compute/v2_16/servers.py
new file mode 100644
index 0000000..6868110
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_16/servers.py
@@ -0,0 +1,160 @@
+# Copyright 2014 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.
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+from tempest.lib.api_schema.response.compute.v2_9 import servers
+
+# Compute microversion 2.16:
+# 1. New attributes in 'server' dict.
+#      'host_status'
+
+server_detail = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'name': {'type': 'string'},
+        'status': {'type': 'string'},
+        'image': {'oneOf': [
+            {'type': 'object',
+                'properties': {
+                    'id': {'type': 'string'},
+                    'links': parameter_types.links
+                },
+                'additionalProperties': False,
+                'required': ['id', 'links']},
+            {'type': ['string', 'null']}
+        ]},
+        'flavor': {
+            'type': 'object',
+            'properties': {
+                'id': {'type': 'string'},
+                'links': parameter_types.links
+            },
+            'additionalProperties': False,
+            'required': ['id', 'links']
+        },
+        'fault': {
+            'type': 'object',
+            'properties': {
+                'code': {'type': 'integer'},
+                'created': {'type': 'string'},
+                'message': {'type': 'string'},
+                'details': {'type': 'string'},
+            },
+            'additionalProperties': False,
+            # NOTE(gmann): 'details' is not necessary to be present
+            #  in the 'fault'. So it is not defined as 'required'.
+            'required': ['code', 'created', 'message']
+        },
+        'user_id': {'type': 'string'},
+        'tenant_id': {'type': 'string'},
+        'created': {'type': 'string'},
+        'updated': {'type': 'string'},
+        'progress': {'type': 'integer'},
+        'metadata': {'type': 'object'},
+        'links': parameter_types.links,
+        'addresses': parameter_types.addresses,
+        'hostId': {'type': 'string'},
+        'OS-DCF:diskConfig': {'type': 'string'},
+        'accessIPv4': parameter_types.access_ip_v4,
+        'accessIPv6': parameter_types.access_ip_v6,
+        'key_name': {'type': ['string', 'null']},
+        'security_groups': {'type': 'array'},
+        'OS-SRV-USG:launched_at': {'type': ['string', 'null']},
+        'OS-SRV-USG:terminated_at': {'type': ['string', 'null']},
+        'OS-EXT-AZ:availability_zone': {'type': 'string'},
+        'OS-EXT-STS:task_state': {'type': ['string', 'null']},
+        'OS-EXT-STS:vm_state': {'type': 'string'},
+        'OS-EXT-STS:power_state': {'type': 'integer'},
+        'OS-EXT-SRV-ATTR:host': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:instance_name': {'type': 'string'},
+        'OS-EXT-SRV-ATTR:hypervisor_hostname': {'type': ['string', 'null']},
+        'config_drive': {'type': 'string'},
+        'os-extended-volumes:volumes_attached': {
+            'type': 'array',
+            'items': {
+                'type': 'object',
+                'properties': {
+                    'id': {'type': 'string'},
+                    'delete_on_termination': {'type': 'boolean'}
+                },
+                'additionalProperties': False,
+            },
+        },
+        'OS-EXT-SRV-ATTR:reservation_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:launch_index': {'type': 'integer'},
+        'OS-EXT-SRV-ATTR:kernel_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:ramdisk_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:hostname': {'type': 'string'},
+        'OS-EXT-SRV-ATTR:root_device_name': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:user_data': {'type': ['string', 'null']},
+        'locked': {'type': 'boolean'},
+        # NOTE(gmann): new attributes in version 2.16
+        'host_status': {'type': 'string'}
+    },
+    'additionalProperties': False,
+    # NOTE(gmann): 'progress' attribute is present in the response
+    # only when server's status is one of the progress statuses
+    # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
+    # 'fault' attribute is present in the response
+    # only when server's status is one of the  "ERROR", "DELETED".
+    # OS-DCF:diskConfig and accessIPv4/v6 are API
+    # extensions, and some environments return a response
+    # without these attributes.So these are not defined as 'required'.
+    'required': ['id', 'name', 'status', 'image', 'flavor',
+                 'user_id', 'tenant_id', 'created', 'updated',
+                 'metadata', 'links', 'addresses', 'hostId']
+}
+
+server_detail['properties']['addresses']['patternProperties'][
+    '^[a-zA-Z0-9-_.]+$']['items']['properties'].update({
+        'OS-EXT-IPS:type': {'type': 'string'},
+        'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
+# NOTE(gmann)dd: Update OS-EXT-IPS:type and OS-EXT-IPS-MAC:mac_addr
+# attributes in server address. Those are API extension,
+# and some environments return a response without
+# these attributes. So they are not 'required'.
+
+get_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': server_detail
+        },
+        'additionalProperties': False,
+        'required': ['server']
+    }
+}
+
+list_servers_detail = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'servers': {
+                'type': 'array',
+                'items': server_detail
+            },
+            'servers_links': parameter_types.links
+        },
+        'additionalProperties': False,
+        # NOTE(gmann): servers_links attribute is not necessary to be
+        # present always So it is not 'required'.
+        'required': ['servers']
+    }
+}
+
+list_servers = copy.deepcopy(servers.list_servers)
diff --git a/tempest/lib/api_schema/response/compute/v2_19/servers.py b/tempest/lib/api_schema/response/compute/v2_19/servers.py
index 883839e..05cc32c 100644
--- a/tempest/lib/api_schema/response/compute/v2_19/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_19/servers.py
@@ -15,15 +15,18 @@
 import copy
 
 from tempest.lib.api_schema.response.compute.v2_1 import servers as serversv21
-from tempest.lib.api_schema.response.compute.v2_9 import servers as serversv29
+from tempest.lib.api_schema.response.compute.v2_16 import servers \
+    as serversv216
 
-get_server = copy.deepcopy(serversv29.get_server)
+list_servers = copy.deepcopy(serversv216.list_servers)
+
+get_server = copy.deepcopy(serversv216.get_server)
 get_server['response_body']['properties']['server'][
     'properties'].update({'description': {'type': ['string', 'null']}})
 get_server['response_body']['properties']['server'][
     'required'].append('description')
 
-list_servers_detail = copy.deepcopy(serversv29.list_servers_detail)
+list_servers_detail = copy.deepcopy(serversv216.list_servers_detail)
 list_servers_detail['response_body']['properties']['servers']['items'][
     'properties'].update({'description': {'type': ['string', 'null']}})
 list_servers_detail['response_body']['properties']['servers']['items'][
diff --git a/tempest/lib/api_schema/response/compute/v2_23/__init__.py b/tempest/lib/api_schema/response/compute/v2_23/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_23/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_23/migrations.py b/tempest/lib/api_schema/response/compute/v2_23/migrations.py
new file mode 100644
index 0000000..3cd0f6e
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_23/migrations.py
@@ -0,0 +1,62 @@
+# Copyright 2014 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.api_schema.response.compute.v2_1 import parameter_types
+
+# Compute microversion 2.23:
+# New attributes in 'migrations' list.
+#    'migration_type'
+#    'links'
+
+list_migrations = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'migrations': {
+                'type': 'array',
+                'items': {
+                    'type': 'object',
+                    'properties': {
+                        'id': {'type': 'integer'},
+                        'status': {'type': ['string', 'null']},
+                        'instance_uuid': {'type': ['string', 'null']},
+                        'source_node': {'type': ['string', 'null']},
+                        'source_compute': {'type': ['string', 'null']},
+                        'dest_node': {'type': ['string', 'null']},
+                        'dest_compute': {'type': ['string', 'null']},
+                        'dest_host': {'type': ['string', 'null']},
+                        'old_instance_type_id': {'type': ['integer', 'null']},
+                        'new_instance_type_id': {'type': ['integer', 'null']},
+                        'created_at': {'type': 'string'},
+                        'updated_at': {'type': ['string', 'null']},
+                        # New attributes in version 2.23
+                        'migration_type': {'type': ['string', 'null']},
+                        'links': parameter_types.links
+                    },
+                    'additionalProperties': False,
+                    'required': [
+                        'id', 'status', 'instance_uuid', 'source_node',
+                        'source_compute', 'dest_node', 'dest_compute',
+                        'dest_host', 'old_instance_type_id',
+                        'new_instance_type_id', 'created_at', 'updated_at',
+                        'migration_type'
+                    ]
+                }
+            }
+        },
+        'additionalProperties': False,
+        'required': ['migrations']
+    }
+}
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/api_schema/response/compute/v2_3/__init__.py b/tempest/lib/api_schema/response/compute/v2_3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_3/__init__.py
diff --git a/tempest/lib/api_schema/response/compute/v2_3/servers.py b/tempest/lib/api_schema/response/compute/v2_3/servers.py
new file mode 100644
index 0000000..ee16333
--- /dev/null
+++ b/tempest/lib/api_schema/response/compute/v2_3/servers.py
@@ -0,0 +1,166 @@
+# Copyright 2014 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.
+import copy
+
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+from tempest.lib.api_schema.response.compute.v2_1 import servers
+
+# Compute microversion 2.3:
+# 1. New attributes in 'os-extended-volumes:volumes_attached' dict.
+#      'delete_on_termination'
+# 2. New attributes in 'server' dict.
+#      'OS-EXT-SRV-ATTR:reservation_id'
+#      'OS-EXT-SRV-ATTR:launch_index'
+#      'OS-EXT-SRV-ATTR:kernel_id'
+#      'OS-EXT-SRV-ATTR:ramdisk_id'
+#      'OS-EXT-SRV-ATTR:hostname'
+#      'OS-EXT-SRV-ATTR:root_device_name'
+#      'OS-EXT-SRV-ATTR:user_data'
+
+server_detail = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'name': {'type': 'string'},
+        'status': {'type': 'string'},
+        'image': {'oneOf': [
+            {'type': 'object',
+                'properties': {
+                    'id': {'type': 'string'},
+                    'links': parameter_types.links
+                },
+                'additionalProperties': False,
+                'required': ['id', 'links']},
+            {'type': ['string', 'null']}
+        ]},
+        'flavor': {
+            'type': 'object',
+            'properties': {
+                'id': {'type': 'string'},
+                'links': parameter_types.links
+            },
+            'additionalProperties': False,
+            'required': ['id', 'links']
+        },
+        'fault': {
+            'type': 'object',
+            'properties': {
+                'code': {'type': 'integer'},
+                'created': {'type': 'string'},
+                'message': {'type': 'string'},
+                'details': {'type': 'string'},
+            },
+            'additionalProperties': False,
+            # NOTE(gmann): 'details' is not necessary to be present
+            #  in the 'fault'. So it is not defined as 'required'.
+            'required': ['code', 'created', 'message']
+        },
+        'user_id': {'type': 'string'},
+        'tenant_id': {'type': 'string'},
+        'created': {'type': 'string'},
+        'updated': {'type': 'string'},
+        'progress': {'type': 'integer'},
+        'metadata': {'type': 'object'},
+        'links': parameter_types.links,
+        'addresses': parameter_types.addresses,
+        'hostId': {'type': 'string'},
+        'OS-DCF:diskConfig': {'type': 'string'},
+        'accessIPv4': parameter_types.access_ip_v4,
+        'accessIPv6': parameter_types.access_ip_v6,
+        'key_name': {'type': ['string', 'null']},
+        'security_groups': {'type': 'array'},
+        'OS-SRV-USG:launched_at': {'type': ['string', 'null']},
+        'OS-SRV-USG:terminated_at': {'type': ['string', 'null']},
+        'OS-EXT-AZ:availability_zone': {'type': 'string'},
+        'OS-EXT-STS:task_state': {'type': ['string', 'null']},
+        'OS-EXT-STS:vm_state': {'type': 'string'},
+        'OS-EXT-STS:power_state': {'type': 'integer'},
+        'OS-EXT-SRV-ATTR:host': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:instance_name': {'type': 'string'},
+        'OS-EXT-SRV-ATTR:hypervisor_hostname': {'type': ['string', 'null']},
+        'config_drive': {'type': 'string'},
+        # NOTE(gmann): new attributes in version 2.3
+        'os-extended-volumes:volumes_attached': {
+            'type': 'array',
+            'items': {
+                'type': 'object',
+                'properties': {
+                    'id': {'type': 'string'},
+                    'delete_on_termination': {'type': 'boolean'}
+                },
+                'additionalProperties': False,
+            },
+        },
+        'OS-EXT-SRV-ATTR:reservation_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:launch_index': {'type': 'integer'},
+        'OS-EXT-SRV-ATTR:kernel_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:ramdisk_id': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:hostname': {'type': 'string'},
+        'OS-EXT-SRV-ATTR:root_device_name': {'type': ['string', 'null']},
+        'OS-EXT-SRV-ATTR:user_data': {'type': ['string', 'null']},
+    },
+    'additionalProperties': False,
+    # NOTE(gmann): 'progress' attribute is present in the response
+    # only when server's status is one of the progress statuses
+    # ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
+    # 'fault' attribute is present in the response
+    # only when server's status is one of the  "ERROR", "DELETED".
+    # OS-DCF:diskConfig and accessIPv4/v6 are API
+    # extensions, and some environments return a response
+    # without these attributes.So these are not defined as 'required'.
+    'required': ['id', 'name', 'status', 'image', 'flavor',
+                 'user_id', 'tenant_id', 'created', 'updated',
+                 'metadata', 'links', 'addresses', 'hostId']
+}
+
+server_detail['properties']['addresses']['patternProperties'][
+    '^[a-zA-Z0-9-_.]+$']['items']['properties'].update({
+        'OS-EXT-IPS:type': {'type': 'string'},
+        'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
+# NOTE(gmann)dd: Update OS-EXT-IPS:type and OS-EXT-IPS-MAC:mac_addr
+# attributes in server address. Those are API extension,
+# and some environments return a response without
+# these attributes. So they are not 'required'.
+
+get_server = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': server_detail
+        },
+        'additionalProperties': False,
+        'required': ['server']
+    }
+}
+
+list_servers_detail = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'servers': {
+                'type': 'array',
+                'items': server_detail
+            },
+            'servers_links': parameter_types.links
+        },
+        'additionalProperties': False,
+        # NOTE(gmann): servers_links attribute is not necessary to be
+        # present always So it is not 'required'.
+        'required': ['servers']
+    }
+}
+
+list_servers = copy.deepcopy(servers.list_servers)
diff --git a/tempest/lib/api_schema/response/compute/v2_9/servers.py b/tempest/lib/api_schema/response/compute/v2_9/servers.py
index e9b7249..470190c 100644
--- a/tempest/lib/api_schema/response/compute/v2_9/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_9/servers.py
@@ -14,7 +14,9 @@
 
 import copy
 
-from tempest.lib.api_schema.response.compute.v2_1 import servers
+from tempest.lib.api_schema.response.compute.v2_3 import servers
+
+list_servers = copy.deepcopy(servers.list_servers)
 
 get_server = copy.deepcopy(servers.get_server)
 get_server['response_body']['properties']['server'][
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 54a7002..1857a43 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -260,11 +260,13 @@
 
     def __init__(self, credentials, auth_url,
                  disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None, scope='project'):
+                 ca_certs=None, trace_requests=None, scope='project',
+                 http_timeout=None):
         super(KeystoneAuthProvider, self).__init__(credentials, scope)
         self.dscv = disable_ssl_certificate_validation
         self.ca_certs = ca_certs
         self.trace_requests = trace_requests
+        self.http_timeout = http_timeout
         self.auth_url = auth_url
         self.auth_client = self._auth_client(auth_url)
 
@@ -342,7 +344,8 @@
     def _auth_client(self, auth_url):
         return json_v2id.TokenClient(
             auth_url, disable_ssl_certificate_validation=self.dscv,
-            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
+            ca_certs=self.ca_certs, trace_requests=self.trace_requests,
+            http_timeout=self.http_timeout)
 
     def _auth_params(self):
         """Auth parameters to be passed to the token request
@@ -429,7 +432,8 @@
     def _auth_client(self, auth_url):
         return json_v3id.V3TokenClient(
             auth_url, disable_ssl_certificate_validation=self.dscv,
-            ca_certs=self.ca_certs, trace_requests=self.trace_requests)
+            ca_certs=self.ca_certs, trace_requests=self.trace_requests,
+            http_timeout=self.http_timeout)
 
     def _auth_params(self):
         """Auth parameters to be passed to the token request
@@ -595,7 +599,7 @@
 
 def get_credentials(auth_url, fill_in=True, identity_version='v2',
                     disable_ssl_certificate_validation=None, ca_certs=None,
-                    trace_requests=None, **kwargs):
+                    trace_requests=None, http_timeout=None, **kwargs):
     """Builds a credentials object based on the configured auth_version
 
     :param auth_url (string): Full URI of the OpenStack Identity API(Keystone)
@@ -611,6 +615,8 @@
     :param ca_certs: CA certificate bundle for validation of certificates
            in SSL API requests to the auth system
     :param trace_requests: trace in log API requests to the auth system
+    :param http_timeout: timeout in seconds to wait for the http request to
+           return
     :param kwargs (dict): Dict of credential key/value pairs
 
     Examples:
@@ -634,7 +640,8 @@
         dscv = disable_ssl_certificate_validation
         auth_provider = auth_provider_class(
             creds, auth_url, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests,
+            http_timeout=http_timeout)
         creds = auth_provider.fill_credentials()
     return creds
 
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/http.py b/tempest/lib/common/http.py
index dffc5f9..86ea26e 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -18,7 +18,7 @@
 
 class ClosingHttp(urllib3.poolmanager.PoolManager):
     def __init__(self, disable_ssl_certificate_validation=False,
-                 ca_certs=None):
+                 ca_certs=None, timeout=None):
         kwargs = {}
 
         if disable_ssl_certificate_validation:
@@ -29,6 +29,9 @@
             kwargs['cert_reqs'] = 'CERT_REQUIRED'
             kwargs['ca_certs'] = ca_certs
 
+        if timeout:
+            kwargs['timeout'] = timeout
+
         super(ClosingHttp, self).__init__(**kwargs)
 
     def request(self, url, method, *args, **kwargs):
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 1b0f53a..5c5d3c2 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -64,8 +64,10 @@
                                                     certificate validation
     :param str ca_certs: File containing the CA Bundle to use in verifying a
                          TLS server cert
-    :param str trace_request: Regex to use for specifying logging the entirety
+    :param str trace_requests: Regex to use for specifying logging the entirety
                               of the request and response payload
+    :param str http_timeout: Timeout in seconds to wait for the http request to
+                             return
     """
     TYPE = "json"
 
@@ -78,7 +80,7 @@
                  endpoint_type='publicURL',
                  build_interval=1, build_timeout=60,
                  disable_ssl_certificate_validation=False, ca_certs=None,
-                 trace_requests='', name=None):
+                 trace_requests='', name=None, http_timeout=None):
         self.auth_provider = auth_provider
         self.service = service
         self.region = region
@@ -99,9 +101,13 @@
                                        'vary', 'www-authenticate'))
         dscv = disable_ssl_certificate_validation
         self.http_obj = http.ClosingHttp(
-            disable_ssl_certificate_validation=dscv, ca_certs=ca_certs)
+            disable_ssl_certificate_validation=dscv, ca_certs=ca_certs,
+            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):
@@ -397,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
@@ -455,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:
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index 7fcec8c..6b6548e 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -47,8 +47,8 @@
     :param str name: The name that you want to include
     :param str prefix: The prefix that you want to include
     :return: a random name. The format is
-             '<prefix>-<random number>-<name>-<random number>'.
-             (e.g. 'prefixfoo-1308607012-namebar-154876201')
+             '<prefix>-<name>-<random number>'.
+             (e.g. 'prefixfoo-namebar-154876201')
     :rtype: string
     """
     randbits = str(random.randint(1, 0x7fffffff))
@@ -75,7 +75,7 @@
     ascii_char = string.ascii_letters
     digits = string.digits
     digit = random.choice(string.digits)
-    puncs = '~!@#$%^&*_=+'
+    puncs = '~!@#%^&*_=+'
     punc = random.choice(puncs)
     seed = ascii_char + digits + puncs
     pre = upper + digit + punc
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 5ca78f9..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):
@@ -229,3 +229,13 @@
 
 class UnknownServiceClient(TempestException):
     message = "Service clients named %(services)s are not known"
+
+
+class ServiceClientRegistrationException(TempestException):
+    message = ("Error registering module %(name)s in path %(module_path)s, "
+               "with service %(service_version)s and clients "
+               "%(client_names)s: %(detailed_error)s")
+
+
+class PluginRegistrationException(TempestException):
+    message = "Error registering plugin %(name)s: %(detailed_error)s"
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
new file mode 100644
index 0000000..adf666b
--- /dev/null
+++ b/tempest/lib/services/clients.py
@@ -0,0 +1,447 @@
+# 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.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
+class ClientsRegistry(object):
+    """Registry of all service clients available from plugins"""
+
+    def __init__(self):
+        self._service_clients = {}
+
+    def register_service_client(self, plugin_name, service_client_data):
+        if plugin_name in self._service_clients:
+            detailed_error = 'Clients for plugin %s already registered'
+            raise exceptions.PluginRegistrationException(
+                name=plugin_name,
+                detailed_error=detailed_error % plugin_name)
+        self._service_clients[plugin_name] = service_client_data
+
+    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/agents_client.py b/tempest/lib/services/compute/agents_client.py
old mode 100644
new mode 100755
index 6d3a817..3f05d3b
--- a/tempest/lib/services/compute/agents_client.py
+++ b/tempest/lib/services/compute/agents_client.py
@@ -24,7 +24,11 @@
     """Tests Agents API"""
 
     def list_agents(self, **params):
-        """List all agent builds."""
+        """List all agent builds.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listbuilds
+        """
         url = 'os-agents'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -46,7 +50,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_agent(self, agent_id):
-        """Delete an existing agent build."""
+        """Delete an existing agent build.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteBuild
+        """
         resp, body = self.delete("os-agents/%s" % agent_id)
         self.validate_response(schema.delete_agent, resp, body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/flavors_client.py b/tempest/lib/services/compute/flavors_client.py
old mode 100644
new mode 100755
index 5be8272..ae1700c
--- a/tempest/lib/services/compute/flavors_client.py
+++ b/tempest/lib/services/compute/flavors_client.py
@@ -28,6 +28,11 @@
 class FlavorsClient(base_compute_client.BaseComputeClient):
 
     def list_flavors(self, detail=False, **params):
+        """Lists flavors.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listFlavors
+        """
         url = 'flavors'
         _schema = schema.list_flavors
 
@@ -43,6 +48,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_flavor(self, flavor_id):
+        """Shows details for a flavor.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showFlavor
+        """
         resp, body = self.get("flavors/%s" % flavor_id)
         body = json.loads(body)
         self.validate_response(schema.create_get_flavor_details, resp, body)
@@ -67,7 +77,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_flavor(self, flavor_id):
-        """Delete the given flavor."""
+        """Delete the given flavor.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteFlavor
+        """
         resp, body = self.delete("flavors/{0}".format(flavor_id))
         self.validate_response(schema.delete_flavor, resp, body)
         return rest_client.ResponseBody(resp, body)
@@ -102,7 +116,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def list_flavor_extra_specs(self, flavor_id):
-        """Get extra Specs details of the mentioned flavor."""
+        """Get extra Specs details of the mentioned flavor.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listFlavorExtraSpecs
+        """
         resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
         body = json.loads(body)
         self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
@@ -110,7 +128,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_flavor_extra_spec(self, flavor_id, key):
-        """Get extra Specs key-value of the mentioned flavor and key."""
+        """Get extra Specs key-value of the mentioned flavor and key.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showFlavorExtraSpec
+        """
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (flavor_id,
                               key))
         body = json.loads(body)
@@ -136,14 +158,22 @@
     def unset_flavor_extra_spec(self, flavor_id, key):  # noqa
         # NOTE: This noqa is for passing T111 check and we cannot rename
         #       to keep backwards compatibility.
-        """Unset extra Specs from the mentioned flavor."""
+        """Unset extra Specs from the mentioned flavor.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteFlavorExtraSpec
+        """
         resp, body = self.delete('flavors/%s/os-extra_specs/%s' %
                                  (flavor_id, key))
         self.validate_response(schema.unset_flavor_extra_specs, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def list_flavor_access(self, flavor_id):
-        """Get flavor access information given the flavor id."""
+        """Get flavor access information given the flavor id.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listFlavorAccess
+        """
         resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id)
         body = json.loads(body)
         self.validate_response(schema_access.add_remove_list_flavor_access,
@@ -151,7 +181,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def add_flavor_access(self, flavor_id, tenant_id):
-        """Add flavor access for the specified tenant."""
+        """Add flavor access for the specified tenant.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#addFlavorAccess
+        """
         post_body = {
             'addTenantAccess': {
                 'tenant': tenant_id
@@ -165,7 +199,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def remove_flavor_access(self, flavor_id, tenant_id):
-        """Remove flavor access from the specified tenant."""
+        """Remove flavor access from the specified tenant.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#removeFlavorAccess
+        """
         post_body = {
             'removeTenantAccess': {
                 'tenant': tenant_id
diff --git a/tempest/lib/services/compute/floating_ips_client.py b/tempest/lib/services/compute/floating_ips_client.py
old mode 100644
new mode 100755
index 03e4894..6922c48
--- a/tempest/lib/services/compute/floating_ips_client.py
+++ b/tempest/lib/services/compute/floating_ips_client.py
@@ -25,7 +25,11 @@
 class FloatingIPsClient(base_compute_client.BaseComputeClient):
 
     def list_floating_ips(self, **params):
-        """Returns a list of all floating IPs filtered by any parameters."""
+        """Returns a list of all floating IPs filtered by any parameters.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listfloatingipsObject
+        """
         url = 'os-floating-ips'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -36,7 +40,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_floating_ip(self, floating_ip_id):
-        """Get the details of a floating IP."""
+        """Get the details of a floating IP.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showFloatingIP
+        """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.get(url)
         body = json.loads(body)
@@ -57,7 +65,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_floating_ip(self, floating_ip_id):
-        """Deletes the provided floating IP from the project."""
+        """Deletes the provided floating IP from the project.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteFloatingIP
+        """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.delete(url)
         self.validate_response(schema.add_remove_floating_ip, resp, body)
diff --git a/tempest/lib/services/compute/keypairs_client.py b/tempest/lib/services/compute/keypairs_client.py
old mode 100644
new mode 100755
index 7b8e6b2..2246739
--- a/tempest/lib/services/compute/keypairs_client.py
+++ b/tempest/lib/services/compute/keypairs_client.py
@@ -28,6 +28,11 @@
                             {'min': '2.2', 'max': None, 'schema': schemav22}]
 
     def list_keypairs(self, **params):
+        """Lists keypairs that are associated with the account.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listKeypairs
+        """
         url = 'os-keypairs'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -38,6 +43,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_keypair(self, keypair_name, **params):
+        """Shows details for a keypair that is associated with the account.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showKeypair
+        """
         url = "os-keypairs/%s" % keypair_name
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -61,6 +71,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_keypair(self, keypair_name, **params):
+        """Deletes a keypair.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteKeypair
+        """
         url = "os-keypairs/%s" % keypair_name
         if params:
             url += '?%s' % urllib.urlencode(params)
diff --git a/tempest/lib/services/compute/migrations_client.py b/tempest/lib/services/compute/migrations_client.py
index 62246d3..c3bdba7 100644
--- a/tempest/lib/services/compute/migrations_client.py
+++ b/tempest/lib/services/compute/migrations_client.py
@@ -16,11 +16,16 @@
 from six.moves.urllib import parse as urllib
 
 from tempest.lib.api_schema.response.compute.v2_1 import migrations as schema
+from tempest.lib.api_schema.response.compute.v2_23 import migrations \
+    as schemav223
 from tempest.lib.common import rest_client
 from tempest.lib.services.compute import base_compute_client
 
 
 class MigrationsClient(base_compute_client.BaseComputeClient):
+    schema_versions_info = [
+        {'min': None, 'max': '2.22', 'schema': schema},
+        {'min': '2.23', 'max': None, 'schema': schemav223}]
 
     def list_migrations(self, **params):
         """List all migrations.
@@ -35,5 +40,6 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.list_migrations, resp, body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/security_groups_client.py b/tempest/lib/services/compute/security_groups_client.py
old mode 100644
new mode 100755
index 6b9c7e1..386c214
--- a/tempest/lib/services/compute/security_groups_client.py
+++ b/tempest/lib/services/compute/security_groups_client.py
@@ -26,7 +26,11 @@
 class SecurityGroupsClient(base_compute_client.BaseComputeClient):
 
     def list_security_groups(self, **params):
-        """List all security groups for a user."""
+        """List all security groups for a user.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listSecGroups
+        """
 
         url = 'os-security-groups'
         if params:
@@ -38,7 +42,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_security_group(self, security_group_id):
-        """Get the details of a Security Group."""
+        """Get the details of a Security Group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showSecGroup
+        """
         url = "os-security-groups/%s" % security_group_id
         resp, body = self.get(url)
         body = json.loads(body)
@@ -71,7 +79,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_security_group(self, security_group_id):
-        """Delete the provided Security Group."""
+        """Delete the provided Security Group.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteSecGroup
+        """
         resp, body = self.delete(
             'os-security-groups/%s' % security_group_id)
         self.validate_response(schema.delete_security_group, resp, body)
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
old mode 100644
new mode 100755
index 0d31ac7..8b22be0
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -20,7 +20,10 @@
 from six.moves.urllib import parse as urllib
 
 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
 from tempest.lib.services.compute import base_compute_client
@@ -28,9 +31,12 @@
 
 class ServersClient(base_compute_client.BaseComputeClient):
     schema_versions_info = [
-        {'min': None, 'max': '2.8', 'schema': schema},
-        {'min': '2.9', 'max': '2.18', 'schema': schemav29},
-        {'min': '2.19', 'max': None, 'schema': schemav219}]
+        {'min': None, 'max': '2.2', 'schema': schema},
+        {'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': '2.25', 'schema': schemav219},
+        {'min': '2.26', 'max': None, 'schema': schemav226}]
 
     def __init__(self, auth_provider, service, region,
                  enable_instance_password=True, **kwargs):
@@ -99,7 +105,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_server(self, server_id):
-        """Get server details."""
+        """Get server details.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showServer
+        """
         resp, body = self.get("servers/%s" % server_id)
         body = json.loads(body)
         schema = self.get_schema(self.schema_versions_info)
@@ -107,7 +117,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_server(self, server_id):
-        """Delete server."""
+        """Delete server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteServer
+        """
         resp, body = self.delete("servers/%s" % server_id)
         self.validate_response(schema.delete_server, resp, body)
         return rest_client.ResponseBody(resp, body)
@@ -137,7 +151,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def list_addresses(self, server_id):
-        """Lists all addresses for a server."""
+        """Lists all addresses for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#list-ips
+        """
         resp, body = self.get("servers/%s/ips" % server_id)
         body = json.loads(body)
         self.validate_response(schema.list_addresses, resp, body)
@@ -260,12 +278,22 @@
         return self.action(server_id, 'revertResize', **kwargs)
 
     def list_server_metadata(self, server_id):
+        """Lists all metadata for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listServerMetadata
+        """
         resp, body = self.get("servers/%s/metadata" % server_id)
         body = json.loads(body)
         self.validate_response(schema.list_server_metadata, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def set_server_metadata(self, server_id, meta, no_metadata_field=False):
+        """Sets one or more metadata items for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#createServerMetadata
+        """
         if no_metadata_field:
             post_body = ""
         else:
@@ -277,6 +305,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def update_server_metadata(self, server_id, meta):
+        """Updates one or more metadata items for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#updateServerMetadata
+        """
         post_body = json.dumps({'metadata': meta})
         resp, body = self.post('servers/%s/metadata' % server_id,
                                post_body)
@@ -286,6 +319,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_server_metadata_item(self, server_id, key):
+        """Shows details for a metadata item, by key, for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showServerMetadataItem
+        """
         resp, body = self.get("servers/%s/metadata/%s" % (server_id, key))
         body = json.loads(body)
         self.validate_response(schema.set_show_server_metadata_item,
@@ -293,6 +331,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def set_server_metadata_item(self, server_id, key, meta):
+        """Sets a metadata item, by key, for a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#setServerMetadataItem
+        """
         post_body = json.dumps({'meta': meta})
         resp, body = self.put('servers/%s/metadata/%s' % (server_id, key),
                               post_body)
@@ -302,6 +345,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_server_metadata_item(self, server_id, key):
+        """Deletes a metadata item, by key, from a server.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteServerMetadataItem
+        """
         resp, body = self.delete("servers/%s/metadata/%s" %
                                  (server_id, key))
         self.validate_response(schema.delete_server_metadata_item,
@@ -309,9 +357,19 @@
         return rest_client.ResponseBody(resp, body)
 
     def stop_server(self, server_id, **kwargs):
+        """Stops a running server and changes its status to SHUTOFF.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#stop
+        """
         return self.action(server_id, 'os-stop', **kwargs)
 
     def start_server(self, server_id, **kwargs):
+        """Starts a stopped server and changes its status to ACTIVE.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#start
+        """
         return self.action(server_id, 'os-start', **kwargs)
 
     def attach_volume(self, server_id, **kwargs):
@@ -337,14 +395,23 @@
         return rest_client.ResponseBody(resp, body)
 
     def detach_volume(self, server_id, volume_id):  # noqa
-        """Detaches a volume from a server instance."""
+        """Detaches a volume from a server instance.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteVolumeAttachment
+        """
         resp, body = self.delete('servers/%s/os-volume_attachments/%s' %
                                  (server_id, volume_id))
         self.validate_response(schema.detach_volume, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def show_volume_attachment(self, server_id, volume_id):
-        """Return details about the given volume attachment."""
+        """Return details about the given volume attachment.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#
+                              getVolumeAttachmentDetails
+        """
         resp, body = self.get('servers/%s/os-volume_attachments/%s' % (
             server_id, volume_id))
         body = json.loads(body)
@@ -352,7 +419,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def list_volume_attachments(self, server_id):
-        """Returns the list of volume attachments for a given instance."""
+        """Returns the list of volume attachments for a given instance.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listVolumeAttachments
+        """
         resp, body = self.get('servers/%s/os-volume_attachments' % (
             server_id))
         body = json.loads(body)
@@ -362,7 +433,8 @@
     def add_security_group(self, server_id, **kwargs):
         """Add a security group to the server.
 
-        Available params: TODO
+        Available params: http://developer.openstack.org/
+                          api-ref-compute-v2.1.html#addSecurityGroup
         """
         # TODO(oomichi): The api-site doesn't contain this API description.
         # So the above should be changed to the api-site link after
@@ -373,7 +445,8 @@
     def remove_security_group(self, server_id, **kwargs):
         """Remove a security group from the server.
 
-        Available params: TODO
+        Available params: http://developer.openstack.org/
+                          api-ref-compute-v2.1.html#removeSecurityGroup
         """
         # TODO(oomichi): The api-site doesn't contain this API description.
         # So the above should be changed to the api-site link after
@@ -503,7 +576,11 @@
         return self.action(server_id, 'rescue', schema.rescue_server, **kwargs)
 
     def unrescue_server(self, server_id):
-        """Unrescue the provided server."""
+        """Unrescue the provided server.
+
+        Available params: http://developer.openstack.org/
+                          api-ref-compute-v2.1.html#unrescue
+        """
         return self.action(server_id, 'unrescue')
 
     def show_server_diagnostics(self, server_id):
diff --git a/tempest/lib/services/compute/services_client.py b/tempest/lib/services/compute/services_client.py
old mode 100644
new mode 100755
index a190e5f..b6dbe28
--- a/tempest/lib/services/compute/services_client.py
+++ b/tempest/lib/services/compute/services_client.py
@@ -25,6 +25,11 @@
 class ServicesClient(base_compute_client.BaseComputeClient):
 
     def list_services(self, **params):
+        """Lists all running Compute services for a tenant.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listServices
+        """
         url = 'os-services'
         if params:
             url += '?%s' % urllib.urlencode(params)
diff --git a/tempest/lib/services/compute/volumes_client.py b/tempest/lib/services/compute/volumes_client.py
old mode 100644
new mode 100755
index 41d9af2..2787779
--- a/tempest/lib/services/compute/volumes_client.py
+++ b/tempest/lib/services/compute/volumes_client.py
@@ -25,7 +25,11 @@
 class VolumesClient(base_compute_client.BaseComputeClient):
 
     def list_volumes(self, detail=False, **params):
-        """List all the volumes created."""
+        """List all the volumes created.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#listVolumes
+        """
         url = 'os-volumes'
 
         if detail:
@@ -39,7 +43,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_volume(self, volume_id):
-        """Return the details of a single volume."""
+        """Return the details of a single volume.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#showVolume
+        """
         url = "os-volumes/%s" % volume_id
         resp, body = self.get(url)
         body = json.loads(body)
@@ -59,7 +67,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_volume(self, volume_id):
-        """Delete the Specified Volume."""
+        """Delete the Specified Volume.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-compute-v2.1.html#deleteVolume
+        """
         resp, body = self.delete("os-volumes/%s" % volume_id)
         self.validate_response(schema.delete_volume, resp, body)
         return rest_client.ResponseBody(resp, body)
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/services_client.py b/tempest/lib/services/identity/v2/services_client.py
old mode 100644
new mode 100755
index 4a63d56..c26d419
--- a/tempest/lib/services/identity/v2/services_client.py
+++ b/tempest/lib/services/identity/v2/services_client.py
@@ -22,7 +22,11 @@
     api_version = "v2.0"
 
     def create_service(self, **kwargs):
-        """Create a service."""
+        """Create a service.
+
+        Available params: see http://developer.openstack.org/api-ref/identity/
+                              v2-ext/?expanded=#create-service-admin-extension
+        """
         post_body = json.dumps({'OS-KSADM:service': kwargs})
         resp, body = self.post('/OS-KSADM/services', post_body)
         self.expected_success(200, resp.status)
@@ -38,7 +42,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def list_services(self, **params):
-        """List Service - Returns Services."""
+        """List Service - Returns Services.
+
+        Available params: see http://developer.openstack.org/api-ref/identity/
+                              v2-ext/?expanded=#list-services-admin-extension
+        """
         url = '/OS-KSADM/services'
         if params:
             url += '?%s' % urllib.urlencode(params)
diff --git a/tempest/lib/services/identity/v2/token_client.py b/tempest/lib/services/identity/v2/token_client.py
index 5716027..a5d7c86 100644
--- a/tempest/lib/services/identity/v2/token_client.py
+++ b/tempest/lib/services/identity/v2/token_client.py
@@ -22,11 +22,11 @@
 class TokenClient(rest_client.RestClient):
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None):
+                 ca_certs=None, trace_requests=None, **kwargs):
         dscv = disable_ssl_certificate_validation
         super(TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
 
         if auth_url is None:
             raise exceptions.IdentityError("Couldn't determine auth_url")
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/lib/services/identity/v3/endpoints_client.py
similarity index 100%
rename from tempest/services/identity/v3/json/endpoints_client.py
rename to tempest/lib/services/identity/v3/endpoints_client.py
diff --git a/tempest/services/identity/v3/json/policies_client.py b/tempest/lib/services/identity/v3/policies_client.py
similarity index 100%
rename from tempest/services/identity/v3/json/policies_client.py
rename to tempest/lib/services/identity/v3/policies_client.py
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/identity/v3/token_client.py b/tempest/lib/services/identity/v3/token_client.py
index 964d43f..c1f7e7b 100644
--- a/tempest/lib/services/identity/v3/token_client.py
+++ b/tempest/lib/services/identity/v3/token_client.py
@@ -22,11 +22,11 @@
 class V3TokenClient(rest_client.RestClient):
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
-                 ca_certs=None, trace_requests=None):
+                 ca_certs=None, trace_requests=None, **kwargs):
         dscv = disable_ssl_certificate_validation
         super(V3TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
-            ca_certs=ca_certs, trace_requests=trace_requests)
+            ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
 
         if auth_url is None:
             raise exceptions.IdentityError("Couldn't determine auth_url")
diff --git a/tempest/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index 4276847..996ce94 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -54,24 +54,44 @@
         return rest_client.ResponseBody(resp, body)
 
     def deactivate_image(self, image_id):
+        """Deactivate image.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref-image-v2.html#deactivateImage-v2
+         """
         url = 'images/%s/actions/deactivate' % image_id
         resp, body = self.post(url, None)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
     def reactivate_image(self, image_id):
+        """Reactivate image.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref-image-v2.html#reactivateImage-v2
+         """
         url = 'images/%s/actions/reactivate' % image_id
         resp, body = self.post(url, None)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
     def delete_image(self, image_id):
+        """Delete image.
+
+         Available params: see http://developer.openstack.org/
+                               api-ref-image-v2.html#deleteImage-v2
+         """
         url = 'images/%s' % image_id
         resp, _ = self.delete(url)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp)
 
     def list_images(self, params=None):
+        """List images.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-image-v2.html#listImages-v2
+        """
         url = 'images'
 
         if params:
@@ -83,6 +103,11 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_image(self, image_id):
+        """Show image details.
+
+        Available params: http://developer.openstack.org/
+                          api-ref-image-v2.html#showImage-v2
+        """
         url = 'images/%s' % image_id
         resp, body = self.get(url)
         self.expected_success(200, resp.status)
@@ -102,6 +127,11 @@
         return 'image'
 
     def store_image_file(self, image_id, data):
+        """Upload binary image data.
+
+        Available params: http://developer.openstack.org/
+                          api-ref-image-v2.html#storeImageFile-v2
+        """
         url = 'images/%s/file' % image_id
 
         # We are going to do chunked transfert, so split the input data
@@ -115,7 +145,7 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_image_file(self, image_id):
-        """Show an image file.
+        """Download binary image data.
 
         Available params: http://developer.openstack.org/
                           api-ref-image-v2.html#showImageFile-v2
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/floating_ips_client.py b/tempest/lib/services/network/floating_ips_client.py
old mode 100644
new mode 100755
index 1968e05..f6cc0ff
--- a/tempest/lib/services/network/floating_ips_client.py
+++ b/tempest/lib/services/network/floating_ips_client.py
@@ -16,16 +16,34 @@
 class FloatingIPsClient(base.BaseNetworkClient):
 
     def create_floatingip(self, **kwargs):
+        """Creates a floating IP.
+
+        If you specify port information, associates the floating IP with an
+        internal port.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#createFloatingIp
+        """
         uri = '/floatingips'
         post_data = {'floatingip': kwargs}
         return self.create_resource(uri, post_data)
 
     def update_floatingip(self, floatingip_id, **kwargs):
+        """Updates a floating IP and its association with an internal port.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#updateFloatingIp
+        """
         uri = '/floatingips/%s' % floatingip_id
         post_data = {'floatingip': kwargs}
         return self.update_resource(uri, post_data)
 
     def show_floatingip(self, floatingip_id, **fields):
+        """Shows details for a floating IP.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showFloatingIp
+        """
         uri = '/floatingips/%s' % floatingip_id
         return self.show_resource(uri, **fields)
 
@@ -34,5 +52,10 @@
         return self.delete_resource(uri)
 
     def list_floatingips(self, **filters):
+        """Lists floating IPs.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#listFloatingIps
+        """
         uri = '/floatingips'
         return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/networks_client.py b/tempest/lib/services/network/networks_client.py
index 19fa1db..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,13 +29,18 @@
         """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}
         return self.update_resource(uri, post_data)
 
     def show_network(self, network_id, **fields):
+        """Shows details for a network.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/networking/v2/index.html#show-network-details
+        """
         uri = '/networks/%s' % network_id
         return self.show_resource(uri, **fields)
 
@@ -44,6 +49,11 @@
         return self.delete_resource(uri)
 
     def list_networks(self, **filters):
+        """Lists networks to which the tenant has access.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref/networking/v2/index.html#list-networks
+        """
         uri = '/networks'
         return self.list_resources(uri, **filters)
 
@@ -51,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/network/routers_client.py b/tempest/lib/services/network/routers_client.py
old mode 100644
new mode 100755
index 2ba1938..23e9c4e
--- a/tempest/lib/services/network/routers_client.py
+++ b/tempest/lib/services/network/routers_client.py
@@ -26,11 +26,21 @@
         return self.create_resource(uri, post_body)
 
     def update_router(self, router_id, **kwargs):
+        """Updates a logical router.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#updateRouter
+        """
         uri = '/routers/%s' % router_id
         update_body = {'router': kwargs}
         return self.update_resource(uri, update_body)
 
     def show_router(self, router_id, **fields):
+        """Shows details for a router.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showRouter
+        """
         uri = '/routers/%s' % router_id
         return self.show_resource(uri, **fields)
 
@@ -39,6 +49,11 @@
         return self.delete_resource(uri)
 
     def list_routers(self, **filters):
+        """Lists logical routers.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#listRouters
+        """
         uri = '/routers'
         return self.list_resources(uri, **filters)
 
@@ -46,7 +61,8 @@
         """Add router interface.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2-ext.html#addRouterInterface
+                              api-ref-networking-v2-ext.html#
+                              addRouterInterface
         """
         uri = '/routers/%s/add_router_interface' % router_id
         return self.update_resource(uri, kwargs)
@@ -55,7 +71,8 @@
         """Remove router interface.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-networking-v2-ext.html#deleteRouterInterface
+                              api-ref-networking-v2-ext.html#
+                              deleteRouterInterface
         """
         uri = '/routers/%s/remove_router_interface' % router_id
         return self.update_resource(uri, kwargs)
diff --git a/tempest/lib/services/network/security_group_rules_client.py b/tempest/lib/services/network/security_group_rules_client.py
old mode 100644
new mode 100755
index 944eba6..6cd01e1
--- a/tempest/lib/services/network/security_group_rules_client.py
+++ b/tempest/lib/services/network/security_group_rules_client.py
@@ -16,11 +16,22 @@
 class SecurityGroupRulesClient(base.BaseNetworkClient):
 
     def create_security_group_rule(self, **kwargs):
+        """Creates an OpenStack Networking security group rule.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#
+                              createSecGroupRule
+        """
         uri = '/security-group-rules'
         post_data = {'security_group_rule': kwargs}
         return self.create_resource(uri, post_data)
 
     def show_security_group_rule(self, security_group_rule_id, **fields):
+        """Shows detailed information for a security group rule.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showSecGroupRule
+        """
         uri = '/security-group-rules/%s' % security_group_rule_id
         return self.show_resource(uri, **fields)
 
@@ -29,5 +40,10 @@
         return self.delete_resource(uri)
 
     def list_security_group_rules(self, **filters):
+        """Lists a summary of all OpenStack Networking security group rules.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#listSecGroupRules
+        """
         uri = '/security-group-rules'
         return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/network/subnetpools_client.py b/tempest/lib/services/network/subnetpools_client.py
old mode 100644
new mode 100755
index 12349b1..f0a66a0
--- a/tempest/lib/services/network/subnetpools_client.py
+++ b/tempest/lib/services/network/subnetpools_client.py
@@ -18,19 +18,39 @@
 class SubnetpoolsClient(base.BaseNetworkClient):
 
     def list_subnetpools(self, **filters):
+        """Lists subnet pools to which the tenant has access.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#listSubnetPools
+        """
         uri = '/subnetpools'
         return self.list_resources(uri, **filters)
 
     def create_subnetpool(self, **kwargs):
+        """Creates a subnet pool.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#createSubnetPool
+        """
         uri = '/subnetpools'
         post_data = {'subnetpool': kwargs}
         return self.create_resource(uri, post_data)
 
     def show_subnetpool(self, subnetpool_id, **fields):
+        """Shows information for a subnet pool.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#showSubnetPool
+        """
         uri = '/subnetpools/%s' % subnetpool_id
         return self.show_resource(uri, **fields)
 
     def update_subnetpool(self, subnetpool_id, **kwargs):
+        """Updates a subnet pool.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2-ext.html#updateSubnetPool
+        """
         uri = '/subnetpools/%s' % subnetpool_id
         post_data = {'subnetpool': kwargs}
         return self.update_resource(uri, post_data)
diff --git a/tempest/lib/services/network/subnets_client.py b/tempest/lib/services/network/subnets_client.py
index 9de4a33..0fde3ee 100755
--- a/tempest/lib/services/network/subnets_client.py
+++ b/tempest/lib/services/network/subnets_client.py
@@ -36,6 +36,11 @@
         return self.update_resource(uri, post_data)
 
     def show_subnet(self, subnet_id, **fields):
+        """Shows details for a subnet.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#showSubnet
+        """
         uri = '/subnets/%s' % subnet_id
         return self.show_resource(uri, **fields)
 
@@ -44,6 +49,11 @@
         return self.delete_resource(uri)
 
     def list_subnets(self, **filters):
+        """Lists subnets to which the tenant has access.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-networking-v2.html#listSubnets
+        """
         uri = '/subnets'
         return self.list_resources(uri, **filters)
 
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/base/base_availability_zone_client.py b/tempest/lib/services/volume/v1/availability_zone_client.py
similarity index 90%
rename from tempest/services/volume/base/base_availability_zone_client.py
rename to tempest/lib/services/volume/v1/availability_zone_client.py
index 1c2deba..be4f539 100644
--- a/tempest/services/volume/base/base_availability_zone_client.py
+++ b/tempest/lib/services/volume/v1/availability_zone_client.py
@@ -18,7 +18,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseAvailabilityZoneClient(rest_client.RestClient):
+class AvailabilityZoneClient(rest_client.RestClient):
+    """Volume V1 availability zone client."""
 
     def list_availability_zones(self):
         resp, body = self.get('os-availability-zone')
diff --git a/tempest/services/volume/base/base_extensions_client.py b/tempest/lib/services/volume/v1/extensions_client.py
similarity index 91%
rename from tempest/services/volume/base/base_extensions_client.py
rename to tempest/lib/services/volume/v1/extensions_client.py
index b90fe94..7b849a8 100644
--- a/tempest/services/volume/base/base_extensions_client.py
+++ b/tempest/lib/services/volume/v1/extensions_client.py
@@ -18,7 +18,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseExtensionsClient(rest_client.RestClient):
+class ExtensionsClient(rest_client.RestClient):
+    """Volume V1 extensions client."""
 
     def list_extensions(self):
         url = 'extensions'
diff --git a/tempest/services/volume/base/admin/base_hosts_client.py b/tempest/lib/services/volume/v1/hosts_client.py
similarity index 90%
rename from tempest/services/volume/base/admin/base_hosts_client.py
rename to tempest/lib/services/volume/v1/hosts_client.py
index 382e9a8..56ba12c 100644
--- a/tempest/services/volume/base/admin/base_hosts_client.py
+++ b/tempest/lib/services/volume/v1/hosts_client.py
@@ -19,8 +19,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseHostsClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Hosts API requests"""
+class HostsClient(rest_client.RestClient):
+    """Client class to send CRUD Volume Host API V1 requests"""
 
     def list_hosts(self, **params):
         """Lists all hosts."""
diff --git a/tempest/services/volume/base/admin/base_quotas_client.py b/tempest/lib/services/volume/v1/quotas_client.py
similarity index 84%
copy from tempest/services/volume/base/admin/base_quotas_client.py
copy to tempest/lib/services/volume/v1/quotas_client.py
index 83816f2..8924b42 100644
--- a/tempest/services/volume/base/admin/base_quotas_client.py
+++ b/tempest/lib/services/volume/v1/quotas_client.py
@@ -18,10 +18,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseQuotasClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Quotas API requests"""
-
-    TYPE = "json"
+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."""
@@ -44,17 +42,11 @@
         body = jsonutils.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def show_quota_usage(self, tenant_id):
-        """List the quota set for a tenant."""
-
-        body = self.show_quota_set(tenant_id, params={'usage': True})
-        return body
-
     def update_quota_set(self, tenant_id, **kwargs):
         """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/base/admin/base_services_client.py b/tempest/lib/services/volume/v1/services_client.py
similarity index 91%
rename from tempest/services/volume/base/admin/base_services_client.py
rename to tempest/lib/services/volume/v1/services_client.py
index 861eb92..d438a34 100644
--- a/tempest/services/volume/base/admin/base_services_client.py
+++ b/tempest/lib/services/volume/v1/services_client.py
@@ -19,7 +19,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseServicesClient(rest_client.RestClient):
+class ServicesClient(rest_client.RestClient):
+    """Volume V1 volume services client"""
 
     def list_services(self, **params):
         url = 'os-services'
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/base/base_availability_zone_client.py b/tempest/lib/services/volume/v2/availability_zone_client.py
similarity index 89%
copy from tempest/services/volume/base/base_availability_zone_client.py
copy to tempest/lib/services/volume/v2/availability_zone_client.py
index 1c2deba..bb4a357 100644
--- a/tempest/services/volume/base/base_availability_zone_client.py
+++ b/tempest/lib/services/volume/v2/availability_zone_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 NEC Corporation.
+# Copyright 2014 IBM Corp.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -18,7 +18,8 @@
 from tempest.lib.common import rest_client
 
 
-class BaseAvailabilityZoneClient(rest_client.RestClient):
+class AvailabilityZoneClient(rest_client.RestClient):
+    api_version = "v2"
 
     def list_availability_zones(self):
         resp, body = self.get('os-availability-zone')
diff --git a/tempest/services/volume/base/base_extensions_client.py b/tempest/lib/services/volume/v2/extensions_client.py
similarity index 86%
copy from tempest/services/volume/base/base_extensions_client.py
copy to tempest/lib/services/volume/v2/extensions_client.py
index b90fe94..09279d5 100644
--- a/tempest/services/volume/base/base_extensions_client.py
+++ b/tempest/lib/services/volume/v2/extensions_client.py
@@ -1,4 +1,4 @@
-# Copyright 2012 OpenStack Foundation
+# Copyright 2014 IBM Corp.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -18,7 +18,9 @@
 from tempest.lib.common import rest_client
 
 
-class BaseExtensionsClient(rest_client.RestClient):
+class ExtensionsClient(rest_client.RestClient):
+    """Volume V2 extensions client."""
+    api_version = "v2"
 
     def list_extensions(self):
         url = 'extensions'
diff --git a/tempest/services/volume/base/admin/base_hosts_client.py b/tempest/lib/services/volume/v2/hosts_client.py
similarity index 86%
copy from tempest/services/volume/base/admin/base_hosts_client.py
copy to tempest/lib/services/volume/v2/hosts_client.py
index 382e9a8..dd7c482 100644
--- a/tempest/services/volume/base/admin/base_hosts_client.py
+++ b/tempest/lib/services/volume/v2/hosts_client.py
@@ -1,4 +1,4 @@
-# Copyright 2013 OpenStack Foundation
+# Copyright 2014 OpenStack Foundation
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -19,8 +19,9 @@
 from tempest.lib.common import rest_client
 
 
-class BaseHostsClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Hosts API requests"""
+class HostsClient(rest_client.RestClient):
+    """Client class to send CRUD Volume V2 API requests"""
+    api_version = "v2"
 
     def list_hosts(self, **params):
         """Lists all hosts."""
diff --git a/tempest/services/volume/base/admin/base_quotas_client.py b/tempest/lib/services/volume/v2/quotas_client.py
similarity index 85%
rename from tempest/services/volume/base/admin/base_quotas_client.py
rename to tempest/lib/services/volume/v2/quotas_client.py
index 83816f2..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,10 +19,9 @@
 from tempest.lib.common import rest_client
 
 
-class BaseQuotasClient(rest_client.RestClient):
-    """Client class to send CRUD Volume Quotas API requests"""
-
-    TYPE = "json"
+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."""
@@ -44,12 +44,6 @@
         body = jsonutils.loads(body)
         return rest_client.ResponseBody(resp, body)
 
-    def show_quota_usage(self, tenant_id):
-        """List the quota set for a tenant."""
-
-        body = self.show_quota_set(tenant_id, params={'usage': True})
-        return body
-
     def update_quota_set(self, tenant_id, **kwargs):
         """Updates quota set
 
diff --git a/tempest/services/volume/base/admin/base_services_client.py b/tempest/lib/services/volume/v2/services_client.py
similarity index 85%
copy from tempest/services/volume/base/admin/base_services_client.py
copy to tempest/lib/services/volume/v2/services_client.py
index 861eb92..bc55469 100644
--- a/tempest/services/volume/base/admin/base_services_client.py
+++ b/tempest/lib/services/volume/v2/services_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 NEC Corporation
+# Copyright 2014 OpenStack Foundation
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -19,7 +19,9 @@
 from tempest.lib.common import rest_client
 
 
-class BaseServicesClient(rest_client.RestClient):
+class ServicesClient(rest_client.RestClient):
+    """Client class to send CRUD Volume V2 API requests"""
+    api_version = "v2"
 
     def list_services(self, **params):
         url = 'os-services'
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 f889c44..fdccfc3 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
@@ -183,7 +146,7 @@
         # every network
         if vnic_type:
             ports = []
-            networks = []
+
             create_port_body = {'binding:vnic_type': vnic_type,
                                 'namestart': 'port-smoke'}
             if kwargs:
@@ -204,25 +167,30 @@
                     if security_groups_ids:
                         create_port_body[
                             'security_groups'] = security_groups_ids
-                networks = kwargs.pop('networks')
+                networks = kwargs.pop('networks', [])
+            else:
+                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']
-                port = self._create_port(network_id=net_id,
-                                         client=clients.ports_client,
-                                         **create_port_body)
-                ports.append({'port': port['id']})
+                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,
+                                             **create_port_body)
+                    ports.append({'port': port['id']})
+                else:
+                    ports.append({'port': net['port']})
             if ports:
                 kwargs['networks'] = ports
             self.ports = ports
@@ -236,18 +204,10 @@
             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
 
@@ -461,11 +421,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)
@@ -664,7 +625,7 @@
             for address in addresses:
                 if address['version'] == CONF.validation.ip_version_for_ssh:
                     return address['addr']
-            raise exceptions.ServerUnreachable()
+            raise exceptions.ServerUnreachable(server_id=server['id'])
         else:
             raise exceptions.InvalidConfiguration()
 
@@ -808,21 +769,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.
@@ -832,6 +778,7 @@
         # NOTE(vsaienko) With Ironic, instances live on separate hardware
         # servers. Neutron does not bind ports for Ironic instances, as a
         # result the port remains in the DOWN state.
+        # TODO(vsaienko) remove once bug: #1599836 is resolved.
         if CONF.service_available.ironic:
             p_status.append('DOWN')
         port_map = [(p["id"], fxip["ip_address"])
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index 655d19d..c060c61 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -15,12 +15,9 @@
 
 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__)
 
 
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_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 402a70c..e0e1204 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
 
@@ -410,6 +411,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
@@ -642,6 +644,8 @@
 
         Nova should unbind the port from the instance on delete if the port was
         not created by Nova as part of the boot request.
+
+        We should also be able to boot another server with the same port.
         """
         # Setup the network, create a port and boot the server from that port.
         self._setup_network_and_servers(boot_with_port=True)
@@ -670,6 +674,17 @@
         self.assertEqual('', port['device_id'])
         self.assertEqual('', port['device_owner'])
 
+        # Boot another server with the same port to make sure nothing was
+        # left around that could cause issues.
+        name = data_utils.rand_name('reuse-port')
+        server = self._create_server(name, self.network, port['id'])
+        port_list = self._list_ports(device_id=server['id'],
+                                     network_id=self.network['id'])
+        self.assertEqual(1, len(port_list),
+                         'There should only be one port created for '
+                         'server %s.' % server['id'])
+        self.assertEqual(port['id'], port_list[0]['id'])
+
     @test.requires_ext(service='network', extension='l3_agent_scheduler')
     @test.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
     @test.services('compute', 'network')
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 59ebb7a..364b6f5 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -18,6 +18,7 @@
 
 from tempest import config
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
 
@@ -254,6 +255,7 @@
         self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2,
                                dualnet=True)
 
+    @decorators.skip_because(bug="1540983")
     @test.idempotent_id('9178ad42-10e4-47e9-8987-e02b170cc5cd')
     @test.services('compute', 'network')
     def test_dualnet_multi_prefix_slaac(self):
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 b58479d..60dca3d 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -16,8 +16,6 @@
 import json
 import re
 
-from oslo_log import log as logging
-
 from tempest import config
 from tempest import exceptions
 from tempest.scenario import manager
@@ -25,8 +23,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class TestServerBasicOps(manager.ScenarioTest):
 
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_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index d6528a3..47c6e8d 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
-
 from tempest import config
 from tempest.scenario import manager
 from tempest import test
@@ -33,9 +31,13 @@
 
     """
 
+    @classmethod
+    def skip_checks(cls):
+        super(TestSnapshotPattern, cls).skip_checks()
+        if not CONF.compute_feature_enabled.snapshot:
+            raise cls.skipException("Snapshotting is not available.")
+
     @test.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
-    @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
-                          'Snapshotting is not available.')
     @test.services('compute', 'network', 'image')
     def test_snapshot_pattern(self):
         # prepare for booting an instance
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 386e621..0000000
--- a/tempest/service_clients.py
+++ /dev/null
@@ -1,178 +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.
-
-from tempest.lib import auth
-from tempest.lib import exceptions
-
-
-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"""
-    # TODO(andreaf) For now this returns only tempest_modules
-    return tempest_modules()
-
-
-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.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()))
-
-    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/baremetal/v1/json/baremetal_client.py b/tempest/services/baremetal/v1/json/baremetal_client.py
old mode 100644
new mode 100755
index f24ef68..ede0d90
--- a/tempest/services/baremetal/v1/json/baremetal_client.py
+++ b/tempest/services/baremetal/v1/json/baremetal_client.py
@@ -20,7 +20,11 @@
 
     @base.handle_errors
     def list_nodes(self, **kwargs):
-        """List all existing nodes."""
+        """List all existing nodes.
+
+        Available params: see http://developer.openstack.org/api-ref/
+                              baremetal/index.html#list-nodes
+        """
         return self._list_request('nodes', **kwargs)
 
     @base.handle_errors
@@ -35,7 +39,11 @@
 
     @base.handle_errors
     def list_ports(self, **kwargs):
-        """List all existing ports."""
+        """List all existing ports.
+
+        Available params: see http://developer.openstack.org/api-ref/
+                              baremetal/index.html?expanded=#list-ports
+        """
         return self._list_request('ports', **kwargs)
 
     @base.handle_errors
@@ -50,7 +58,11 @@
 
     @base.handle_errors
     def list_ports_detail(self, **kwargs):
-        """Details list all existing ports."""
+        """Details list all existing ports.
+
+        Available params: see http://developer.openstack.org/api-ref/baremetal/
+                              index.html?expanded=#list-detailed-ports
+        """
         return self._list_request('/ports/detail', **kwargs)
 
     @base.handle_errors
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
index 144c5a9..a4e55d4 100644
--- a/tempest/services/identity/v3/__init__.py
+++ b/tempest/services/identity/v3/__init__.py
@@ -12,22 +12,22 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+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.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.endpoints_client import EndPointsClient
 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.policies_client import PoliciesClient
 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__ = ['V3TokenClient', 'CredentialsClient', 'DomainsClient',
-           'EndPointsClient', 'GroupsClient', 'IdentityClient',
-           'PoliciesClient', 'ProjectsClient', 'RegionsClient', 'RolesClient',
-           'ServicesClient', 'TrustsClient', 'UsersClient', ]
+__all__ = ['EndPointsClient', 'PoliciesClient', 'RegionsClient',
+           'ServicesClient', 'V3TokenClient', 'CredentialsClient',
+           'DomainsClient', 'GroupsClient', 'IdentityClient', 'ProjectsClient',
+           '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/projects_client.py b/tempest/services/identity/v3/json/projects_client.py
index 97e43df..ce2f38d 100644
--- a/tempest/services/identity/v3/json/projects_client.py
+++ b/tempest/services/identity/v3/json/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/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
old mode 100644
new mode 100755
index e4d9014..83870ae
--- a/tempest/services/volume/base/admin/base_types_client.py
+++ b/tempest/services/volume/base/admin/base_types_client.py
@@ -48,7 +48,11 @@
         return 'volume-type/encryption-type'
 
     def list_volume_types(self, **params):
-        """List all the volume_types created."""
+        """List all the volume_types created.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#showVolumeTypes
+        """
         url = 'types'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -58,9 +62,13 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def show_volume_type(self, volume_id):
-        """Returns the details of a single volume_type."""
-        url = "types/%s" % str(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" % volume_type_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -78,22 +86,24 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_volume_type(self, volume_id):
-        """Deletes the Specified Volume_type."""
-        resp, body = self.delete("types/%s" % str(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" % 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)
 
@@ -102,114 +112,93 @@
         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.
+        Available params: see http://developer.openstack.org/
+                              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."""
-        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 3842d66..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)
@@ -89,6 +89,13 @@
         self.expected_success(201, resp.status)
         return rest_client.ResponseBody(resp, body)
 
+    def reset_backup_status(self, backup_id, status):
+        """Reset the specified backup's status."""
+        post_body = json.dumps({'os-reset_status': {"status": status}})
+        resp, body = self.post('backups/%s/action' % backup_id, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
     def wait_for_backup_status(self, backup_id, status):
         """Waits for a Backup to reach a given status."""
         body = self.show_backup(backup_id)['backup']
@@ -99,7 +106,7 @@
             time.sleep(self.build_interval)
             body = self.show_backup(backup_id)['backup']
             backup_status = body['status']
-            if backup_status == 'error':
+            if backup_status == 'error' and backup_status != status:
                 raise exceptions.VolumeBackupException(backup_id=backup_id)
 
             if int(time.time()) - start >= self.build_timeout:
@@ -109,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..e00ac68 100644
--- a/tempest/services/volume/base/base_qos_client.py
+++ b/tempest/services/volume/base/base_qos_client.py
@@ -82,7 +82,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 +96,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 +128,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 +136,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 +144,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 +152,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
old mode 100644
new mode 100755
index 6d3f03b..38a6dc7
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -23,7 +23,11 @@
     create_resp = 200
 
     def list_snapshots(self, detail=False, **params):
-        """List all the snapshot."""
+        """List all the snapshot.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#listSnapshots
+        """
         url = 'snapshots'
         if detail:
             url += '/detail'
@@ -36,8 +40,12 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_snapshot(self, snapshot_id):
-        """Returns the details of a single snapshot."""
-        url = "snapshots/%s" % str(snapshot_id)
+        """Returns the details of a single snapshot.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#showSnapshot
+        """
+        url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -68,8 +76,12 @@
         return rest_client.ResponseBody(resp, body)
 
     def delete_snapshot(self, snapshot_id):
-        """Delete Snapshot."""
-        resp, body = self.delete("snapshots/%s" % str(snapshot_id))
+        """Delete Snapshot.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#deleteSnapshot
+        """
+        resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -100,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)
@@ -108,15 +120,20 @@
     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)
         return rest_client.ResponseBody(resp, body)
 
     def show_snapshot_metadata(self, snapshot_id):
-        """Get metadata of the snapshot."""
-        url = "snapshots/%s/metadata" % str(snapshot_id)
+        """Get metadata of the snapshot.
+
+        Available params: see http://developer.openstack.org/
+                              api-ref-blockstorage-v2.html#
+                              showSnapshotMetadata
+        """
+        url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
@@ -126,10 +143,11 @@
         """Update metadata for the snapshot.
 
         Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#updateSnapshotMetadata
+                              api-ref-blockstorage-v2.html#
+                              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)
@@ -142,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)
@@ -150,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..273dbbb 100755
--- a/tempest/services/volume/base/base_volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -63,7 +63,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 +77,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)
@@ -109,7 +126,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)
 
@@ -231,7 +248,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 +270,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 +305,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 +313,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 +322,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 +331,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 +339,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/hosts_client.py b/tempest/services/volume/v1/json/admin/hosts_client.py
deleted file mode 100644
index 3b52968..0000000
--- a/tempest/services/volume/v1/json/admin/hosts_client.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2013 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_hosts_client
-
-
-class HostsClient(base_hosts_client.BaseHostsClient):
-    """Client class to send CRUD Volume Host API V1 requests"""
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/v1/json/admin/services_client.py b/tempest/services/volume/v1/json/admin/services_client.py
deleted file mode 100644
index 2bffd55..0000000
--- a/tempest/services/volume/v1/json/admin/services_client.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2014 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.services.volume.base.admin import base_services_client
-
-
-class ServicesClient(base_services_client.BaseServicesClient):
-    """Volume V1 volume services client"""
diff --git a/tempest/services/volume/v1/json/availability_zone_client.py b/tempest/services/volume/v1/json/availability_zone_client.py
deleted file mode 100644
index 3a27027..0000000
--- a/tempest/services/volume/v1/json/availability_zone_client.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2014 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.services.volume.base import base_availability_zone_client
-
-
-class AvailabilityZoneClient(
-        base_availability_zone_client.BaseAvailabilityZoneClient):
-    """Volume V1 availability zone client."""
diff --git a/tempest/services/volume/v1/json/extensions_client.py b/tempest/services/volume/v1/json/extensions_client.py
deleted file mode 100644
index f99d0f5..0000000
--- a/tempest/services/volume/v1/json/extensions_client.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2012 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 import base_extensions_client
-
-
-class ExtensionsClient(base_extensions_client.BaseExtensionsClient):
-    """Volume V1 extensions client."""
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/hosts_client.py b/tempest/services/volume/v2/json/admin/hosts_client.py
deleted file mode 100644
index e092c6a..0000000
--- a/tempest/services/volume/v2/json/admin/hosts_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_hosts_client
-
-
-class HostsClient(base_hosts_client.BaseHostsClient):
-    """Client class to send CRUD Volume V2 API requests"""
-    api_version = "v2"
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/services_client.py b/tempest/services/volume/v2/json/admin/services_client.py
deleted file mode 100644
index db19ba9..0000000
--- a/tempest/services/volume/v2/json/admin/services_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_services_client
-
-
-class ServicesClient(base_services_client.BaseServicesClient):
-    """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/services/volume/v2/json/availability_zone_client.py b/tempest/services/volume/v2/json/availability_zone_client.py
deleted file mode 100644
index 905ebdc..0000000
--- a/tempest/services/volume/v2/json/availability_zone_client.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2014 IBM Corp.
-# 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 import base_availability_zone_client
-
-
-class AvailabilityZoneClient(
-        base_availability_zone_client.BaseAvailabilityZoneClient):
-    api_version = "v2"
diff --git a/tempest/services/volume/v2/json/extensions_client.py b/tempest/services/volume/v2/json/extensions_client.py
deleted file mode 100644
index 245906f..0000000
--- a/tempest/services/volume/v2/json/extensions_client.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2014 IBM Corp.
-# 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 import base_extensions_client
-
-
-class ExtensionsClient(base_extensions_client.BaseExtensionsClient):
-    api_version = "v2"
diff --git a/tempest/stress/actions/unit_test.py b/tempest/stress/actions/unit_test.py
index 3b27885..e016c61 100644
--- a/tempest/stress/actions/unit_test.py
+++ b/tempest/stress/actions/unit_test.py
@@ -80,8 +80,6 @@
 
             try:
                 self.run_core()
-            except Exception as e:
-                raise e
             finally:
                 if (CONF.stress.leave_dirty_stack is False
                     and self.class_setup_per == SetUpClassRunTime.action):
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index d604b28..eb50126 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -19,6 +19,7 @@
 import stevedore
 
 from tempest.lib.common.utils import misc
+from tempest.lib.services import clients
 
 LOG = logging.getLogger(__name__)
 
@@ -62,6 +63,54 @@
         """
         return []
 
+    def get_service_clients(self):
+        """Get a list of the service clients for registration
+
+        If the plugin implements service clients for one or more APIs, it
+        may return their details by this method for automatic registration
+        in any ServiceClients object instantiated by tests.
+        The default implementation returns an empty list.
+
+        :return list of dictionaries. Each element of the list represents
+            the service client for an API. Each dict must define all
+            parameters required for the invocation of
+            `service_clients.ServiceClients.register_service_client_module`.
+        :rtype: list
+
+        Example:
+
+            >>>  # Example implementation with one service client
+            >>>  myservice_config = config.service_client_config('myservice')
+            >>>  params = {
+            >>>     'name': 'myservice',
+            >>>     'service_version': 'myservice',
+            >>>     'module_path': 'myservice_tempest_tests.services',
+            >>>     'client_names': ['API1Client', 'API2Client'],
+            >>>  }
+            >>>  params.update(myservice_config)
+            >>>  return [params]
+
+            >>>  # Example implementation with two service clients
+            >>>  foo1_config = config.service_client_config('foo')
+            >>>  params_foo1 = {
+            >>>     'name': 'foo_v1',
+            >>>     'service_version': 'foo.v1',
+            >>>     'module_path': 'bar_tempest_tests.services.foo.v1',
+            >>>     'client_names': ['API1Client', 'API2Client'],
+            >>>  }
+            >>>  params_foo1.update(foo_config)
+            >>>  foo2_config = config.service_client_config('foo')
+            >>>  params_foo2 = {
+            >>>     'name': 'foo_v2',
+            >>>     'service_version': 'foo.v2',
+            >>>     'module_path': 'bar_tempest_tests.services.foo.v2',
+            >>>     'client_names': ['API1Client', 'API2Client'],
+            >>>  }
+            >>>  params_foo2.update(foo2_config)
+            >>>  return [params_foo1, params_foo2]
+        """
+        return []
+
 
 @misc.singleton
 class TempestTestPluginManager(object):
@@ -75,6 +124,7 @@
             'tempest.test_plugins', invoke_on_load=True,
             propagate_map_exceptions=True,
             on_load_failure_callback=self.failure_hook)
+        self._register_service_clients()
 
     @staticmethod
     def failure_hook(_, ep, err):
@@ -102,3 +152,13 @@
             if opt_list:
                 plugin_options.extend(opt_list)
         return plugin_options
+
+    def _register_service_clients(self):
+        registry = clients.ClientsRegistry()
+        for plug in self.ext_plugins:
+            try:
+                registry.register_service_client(
+                    plug.name, plug.obj.get_service_clients())
+            except Exception:
+                LOG.exception('Plugin %s raised an exception trying to run '
+                              'get_service_clients' % plug.name)
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
deleted file mode 100644
index 5ec9720..0000000
--- a/tempest/tests/cmd/test_javelin.py
+++ /dev/null
@@ -1,422 +0,0 @@
-#!/usr/bin/env python
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import mock
-from oslotest import mockpatch
-
-from tempest.cmd import javelin
-from tempest.lib import exceptions as lib_exc
-from tempest.tests import base
-
-
-class JavelinUnitTest(base.TestCase):
-
-    def setUp(self):
-        super(JavelinUnitTest, self).setUp()
-        javelin.LOG = mock.MagicMock()
-        self.fake_client = mock.MagicMock()
-        self.fake_object = mock.MagicMock()
-
-    def test_load_resources(self):
-        with mock.patch('six.moves.builtins.open', mock.mock_open(),
-                        create=True) as open_mock:
-            with mock.patch('yaml.load', mock.MagicMock(),
-                            create=True) as load_mock:
-                javelin.load_resources(self.fake_object)
-                load_mock.assert_called_once_with(open_mock(self.fake_object))
-
-    def test_keystone_admin(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
-        javelin.OPTS = self.fake_object
-        javelin.keystone_admin()
-        javelin.OSClient.assert_called_once_with(
-            self.fake_object.os_username,
-            self.fake_object.os_password,
-            self.fake_object.os_tenant_name)
-
-    def test_client_for_user(self):
-        fake_user = mock.MagicMock()
-        javelin.USERS = {fake_user['name']: fake_user}
-        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
-        javelin.client_for_user(fake_user['name'])
-        javelin.OSClient.assert_called_once_with(
-            fake_user['name'], fake_user['pass'], fake_user['tenant'])
-
-    def test_client_for_non_existing_user(self):
-        fake_non_existing_user = self.fake_object
-        fake_user = mock.MagicMock()
-        javelin.USERS = {fake_user['name']: fake_user}
-        self.useFixture(mockpatch.PatchObject(javelin, "OSClient"))
-        javelin.client_for_user(fake_non_existing_user['name'])
-        self.assertFalse(javelin.OSClient.called)
-
-    def test_attach_volumes(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        self.useFixture(mockpatch.PatchObject(
-            javelin, "_get_volume_by_name",
-            return_value=self.fake_object.volume))
-
-        self.useFixture(mockpatch.PatchObject(
-            javelin, "_get_server_by_name",
-            return_value=self.fake_object.server))
-
-        javelin.attach_volumes([self.fake_object])
-
-        mocked_function = self.fake_client.volumes.attach_volume
-        mocked_function.assert_called_once_with(
-            self.fake_object.volume['id'],
-            instance_uuid=self.fake_object.server['id'],
-            mountpoint=self.fake_object['device'])
-
-
-class TestCreateResources(JavelinUnitTest):
-    def test_create_tenants(self):
-
-        self.fake_client.tenants.list_tenants.return_value = {'tenants': []}
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=self.fake_client))
-
-        javelin.create_tenants([self.fake_object['name']])
-
-        mocked_function = self.fake_client.tenants.create_tenant
-        mocked_function.assert_called_once_with(name=self.fake_object['name'])
-
-    def test_create_duplicate_tenant(self):
-        self.fake_client.tenants.list_tenants.return_value = {'tenants': [
-            {'name': self.fake_object['name']}]}
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=self.fake_client))
-
-        javelin.create_tenants([self.fake_object['name']])
-
-        mocked_function = self.fake_client.tenants.create_tenant
-        self.assertFalse(mocked_function.called)
-
-    def test_create_users(self):
-        self.useFixture(mockpatch.Patch(
-                        'tempest.common.identity.get_tenant_by_name',
-                        return_value=self.fake_object['tenant']))
-        self.useFixture(mockpatch.Patch(
-                        'tempest.common.identity.get_user_by_username',
-                        side_effect=lib_exc.NotFound("user is not found")))
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=self.fake_client))
-
-        javelin.create_users([self.fake_object])
-
-        fake_tenant_id = self.fake_object['tenant']['id']
-        fake_email = "%s@%s" % (self.fake_object['user'], fake_tenant_id)
-        mocked_function = self.fake_client.users.create_user
-        mocked_function.assert_called_once_with(
-            name=self.fake_object['name'],
-            password=self.fake_object['password'],
-            tenantId=fake_tenant_id,
-            email=fake_email,
-            enabled=True)
-
-    def test_create_user_missing_tenant(self):
-        self.useFixture(mockpatch.Patch(
-                        'tempest.common.identity.get_tenant_by_name',
-                        side_effect=lib_exc.NotFound("tenant is not found")))
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=self.fake_client))
-
-        javelin.create_users([self.fake_object])
-
-        mocked_function = self.fake_client.users.create_user
-        self.assertFalse(mocked_function.called)
-
-    def test_create_objects(self):
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_assign_swift_role"))
-        self.useFixture(mockpatch.PatchObject(javelin, "_file_contents",
-                        return_value=self.fake_object.content))
-
-        javelin.create_objects([self.fake_object])
-
-        mocked_function = self.fake_client.containers.create_container
-        mocked_function.assert_called_once_with(self.fake_object['container'])
-        mocked_function = self.fake_client.objects.create_object
-        mocked_function.assert_called_once_with(self.fake_object['container'],
-                                                self.fake_object['name'],
-                                                self.fake_object.content)
-
-    def test_create_images(self):
-        self.fake_client.images.create_image.return_value = \
-            self.fake_object['body']
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_image_by_name",
-                                              return_value=[]))
-        self.useFixture(mockpatch.PatchObject(javelin, "_resolve_image",
-                                              return_value=(None, None)))
-
-        with mock.patch('six.moves.builtins.open', mock.mock_open(),
-                        create=True) as open_mock:
-            javelin.create_images([self.fake_object])
-
-        mocked_function = self.fake_client.images.create_image
-        mocked_function.assert_called_once_with(self.fake_object['name'],
-                                                self.fake_object['format'],
-                                                self.fake_object['format'])
-
-        mocked_function = self.fake_client.images.store_image_file
-        fake_image_id = self.fake_object['body'].get('id')
-        mocked_function.assert_called_once_with(fake_image_id, open_mock())
-
-    def test_create_networks(self):
-        self.fake_client.networks.list_networks.return_value = {
-            'networks': []}
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        javelin.create_networks([self.fake_object])
-
-        mocked_function = self.fake_client.networks.create_network
-        mocked_function.assert_called_once_with(name=self.fake_object['name'])
-
-    def test_create_subnet(self):
-
-        fake_network = self.fake_object['network']
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_resource_by_name",
-                                              return_value=fake_network))
-
-        fake_netaddr = mock.MagicMock()
-        self.useFixture(mockpatch.PatchObject(javelin, "netaddr",
-                                              return_value=fake_netaddr))
-        fake_version = javelin.netaddr.IPNetwork().version
-
-        javelin.create_subnets([self.fake_object])
-
-        mocked_function = self.fake_client.networks.create_subnet
-        mocked_function.assert_called_once_with(network_id=fake_network['id'],
-                                                cidr=self.fake_object['range'],
-                                                name=self.fake_object['name'],
-                                                ip_version=fake_version)
-
-    @mock.patch("tempest.common.waiters.wait_for_volume_status")
-    def test_create_volumes(self, mock_wait_for_volume_status):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_volume_by_name",
-                                              return_value=None))
-        self.fake_client.volumes.create_volume.return_value = \
-            self.fake_object.body
-
-        javelin.create_volumes([self.fake_object])
-
-        mocked_function = self.fake_client.volumes.create_volume
-        mocked_function.assert_called_once_with(
-            size=self.fake_object['gb'],
-            display_name=self.fake_object['name'])
-        mock_wait_for_volume_status.assert_called_once_with(
-            self.fake_client.volumes, self.fake_object.body['volume']['id'],
-            'available')
-
-    @mock.patch("tempest.common.waiters.wait_for_volume_status")
-    def test_create_volume_existing(self, mock_wait_for_volume_status):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_volume_by_name",
-                                              return_value=self.fake_object))
-        self.fake_client.volumes.create_volume.return_value = \
-            self.fake_object.body
-
-        javelin.create_volumes([self.fake_object])
-
-        mocked_function = self.fake_client.volumes.create_volume
-        self.assertFalse(mocked_function.called)
-        self.assertFalse(mock_wait_for_volume_status.called)
-
-    def test_create_router(self):
-
-        self.fake_client.routers.list_routers.return_value = {'routers': []}
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        javelin.create_routers([self.fake_object])
-
-        mocked_function = self.fake_client.networks.create_router
-        mocked_function.assert_called_once_with(name=self.fake_object['name'])
-
-    def test_create_router_existing(self):
-        self.fake_client.routers.list_routers.return_value = {
-            'routers': [self.fake_object]}
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        javelin.create_routers([self.fake_object])
-
-        mocked_function = self.fake_client.networks.create_router
-        self.assertFalse(mocked_function.called)
-
-    def test_create_secgroup(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.fake_client.secgroups.list_security_groups.return_value = (
-            {'security_groups': []})
-        self.fake_client.secgroups.create_security_group.return_value = \
-            {'security_group': {'id': self.fake_object['secgroup_id']}}
-
-        javelin.create_secgroups([self.fake_object])
-
-        mocked_function = self.fake_client.secgroups.create_security_group
-        mocked_function.assert_called_once_with(
-            name=self.fake_object['name'],
-            description=self.fake_object['description'])
-
-
-class TestDestroyResources(JavelinUnitTest):
-
-    def test_destroy_tenants(self):
-
-        fake_tenant = self.fake_object['tenant']
-        fake_auth = self.fake_client
-        self.useFixture(mockpatch.Patch(
-                        'tempest.common.identity.get_tenant_by_name',
-                        return_value=fake_tenant))
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=fake_auth))
-        javelin.destroy_tenants([fake_tenant])
-
-        mocked_function = fake_auth.tenants.delete_tenant
-        mocked_function.assert_called_once_with(fake_tenant['id'])
-
-    def test_destroy_users(self):
-
-        fake_user = self.fake_object['user']
-        fake_tenant = self.fake_object['tenant']
-
-        fake_auth = self.fake_client
-        fake_auth.tenants.list_tenants.return_value = \
-            {'tenants': [fake_tenant]}
-        fake_auth.users.list_users.return_value = {'users': [fake_user]}
-
-        self.useFixture(mockpatch.Patch(
-                        'tempest.common.identity.get_user_by_username',
-                        return_value=fake_user))
-        self.useFixture(mockpatch.PatchObject(javelin, "keystone_admin",
-                                              return_value=fake_auth))
-
-        javelin.destroy_users([fake_user])
-
-        mocked_function = fake_auth.users.delete_user
-        mocked_function.assert_called_once_with(fake_user['id'])
-
-    def test_destroy_objects(self):
-
-        self.fake_client.objects.delete_object.return_value = \
-            {'status': "200"}, ""
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        javelin.destroy_objects([self.fake_object])
-
-        mocked_function = self.fake_client.objects.delete_object
-        mocked_function.asswert_called_once(self.fake_object['container'],
-                                            self.fake_object['name'])
-
-    def test_destroy_images(self):
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_image_by_name",
-                        return_value=self.fake_object['image']))
-
-        javelin.destroy_images([self.fake_object])
-
-        mocked_function = self.fake_client.images.delete_image
-        mocked_function.assert_called_once_with(
-            self.fake_object['image']['id'])
-
-    def test_destroy_networks(self):
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        self.useFixture(mockpatch.PatchObject(
-            javelin, "_get_resource_by_name",
-            return_value=self.fake_object['resource']))
-
-        javelin.destroy_networks([self.fake_object])
-
-        mocked_function = self.fake_client.networks.delete_network
-        mocked_function.assert_called_once_with(
-            self.fake_object['resource']['id'])
-
-    def test_destroy_volumes(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        self.useFixture(mockpatch.PatchObject(
-            javelin, "_get_volume_by_name",
-            return_value=self.fake_object.volume))
-
-        javelin.destroy_volumes([self.fake_object])
-
-        mocked_function = self.fake_client.volumes.detach_volume
-        mocked_function.assert_called_once_with(self.fake_object.volume['id'])
-        mocked_function = self.fake_client.volumes.delete_volume
-        mocked_function.assert_called_once_with(self.fake_object.volume['id'])
-
-    def test_destroy_subnets(self):
-
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        fake_subnet_id = self.fake_object['subnet_id']
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_resource_by_name",
-                                              return_value={
-                                                  'id': fake_subnet_id}))
-
-        javelin.destroy_subnets([self.fake_object])
-
-        mocked_function = self.fake_client.subnets.delete_subnet
-        mocked_function.assert_called_once_with(fake_subnet_id)
-
-    def test_destroy_routers(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-
-        # this function is used on 2 different occasions in the code
-        def _fake_get_resource_by_name(*args):
-            if args[1] == "routers":
-                return {"id": self.fake_object['router_id']}
-            elif args[1] == "subnets":
-                return {"id": self.fake_object['subnet_id']}
-        javelin._get_resource_by_name = _fake_get_resource_by_name
-
-        javelin.destroy_routers([self.fake_object])
-
-        mocked_function = self.fake_client.routers.delete_router
-        mocked_function.assert_called_once_with(
-            self.fake_object['router_id'])
-
-    def test_destroy_secgroup(self):
-        self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
-                                              return_value=self.fake_client))
-        fake_secgroup = {'id': self.fake_object['id']}
-        self.useFixture(mockpatch.PatchObject(javelin, "_get_resource_by_name",
-                                              return_value=fake_secgroup))
-
-        javelin.destroy_secgroups([self.fake_object])
-
-        mocked_function = self.fake_client.secgroups.delete_security_group
-        mocked_function.assert_called_once_with(self.fake_object['id'])
diff --git a/tempest/tests/cmd/test_subunit_describe_calls.py b/tempest/tests/cmd/test_subunit_describe_calls.py
index 43b417a..1c24c37 100644
--- a/tempest/tests/cmd/test_subunit_describe_calls.py
+++ b/tempest/tests/cmd/test_subunit_describe_calls.py
@@ -38,46 +38,159 @@
             os.path.dirname(os.path.abspath(__file__)),
             'sample_streams/calls.subunit')
         parser = subunit_describe_calls.parse(
-            subunit_file, "pythonlogging", None)
+            open(subunit_file), "pythonlogging", None)
         expected_result = {
-            'bar': [{'name': 'AgentsAdminTestJSON:setUp',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents',
-                     'verb': 'POST'},
-                    {'name': 'AgentsAdminTestJSON:test_create_agent',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents',
-                     'verb': 'POST'},
-                    {'name': 'AgentsAdminTestJSON:tearDown',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents/1',
-                     'verb': 'DELETE'},
-                    {'name': 'AgentsAdminTestJSON:_run_cleanups',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents/2',
-                     'verb': 'DELETE'}],
-            'foo': [{'name': 'AgentsAdminTestJSON:setUp',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents',
-                     'verb': 'POST'},
-                    {'name': 'AgentsAdminTestJSON:test_delete_agent',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents/3',
-                     'verb': 'DELETE'},
-                    {'name': 'AgentsAdminTestJSON:test_delete_agent',
-                     'service': 'Nova',
-                     'status_code': '200',
-                     'url': 'v2.1/<id>/os-agents',
-                     'verb': 'GET'},
-                    {'name': 'AgentsAdminTestJSON:tearDown',
-                     'service': 'Nova',
-                     'status_code': '404',
-                     'url': 'v2.1/<id>/os-agents/3',
-                     'verb': 'DELETE'}]}
+            'bar': [{
+                'name': 'AgentsAdminTestJSON:setUp',
+                'request_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "common", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86_64-424013832", "os": "linux"}}',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "common", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86_64-424013832", "os": "linux", '
+                '"agent_id": 1}}',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'203', 'x-compute-request-id': "
+                "'req-25ddaae2-0ef1-40d1-8228-59bd64a7e75b', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:00 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents',
+                'verb': 'POST'}, {
+                'name': 'AgentsAdminTestJSON:test_create_agent',
+                'request_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "kvm", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86-252246646", "os": "win"}}',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "kvm", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86-252246646", "os": "win", '
+                '"agent_id": 2}}',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'195', 'x-compute-request-id': "
+                "'req-b4136f06-c015-4e7e-995f-c43831e3ecce', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:00 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents',
+                'verb': 'POST'}, {
+                'name': 'AgentsAdminTestJSON:tearDown',
+                'request_body': 'None',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'0', 'x-compute-request-id': "
+                "'req-ee905fd6-a5b5-4da4-8c37-5363cb25bd9d', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:00 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents/1',
+                'verb': 'DELETE'}, {
+                'name': 'AgentsAdminTestJSON:_run_cleanups',
+                'request_body': 'None',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_headers': "{'status': '200', 'content-length': "
+                "'0', 'x-compute-request-id': "
+                "'req-e912cac0-63e0-4679-a68a-b6d18ddca074', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:00 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents/2',
+                'verb': 'DELETE'}],
+            'foo': [{
+                'name': 'AgentsAdminTestJSON:setUp',
+                'request_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "common", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86_64-948635295", "os": "linux"}}',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '{"agent": {"url": "xxx://xxxx/xxx/xxx", '
+                '"hypervisor": "common", "md5hash": '
+                '"add6bb58e139be103324d04d82d8f545", "version": "7.0", '
+                '"architecture": "tempest-x86_64-948635295", "os": "linux", '
+                '"agent_id": 3}}',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'203', 'x-compute-request-id': "
+                "'req-ccd2116d-04b1-4ffe-ae32-fb623f68bf1c', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:01 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents',
+                'verb': 'POST'}, {
+                'name': 'AgentsAdminTestJSON:test_delete_agent',
+                'request_body': 'None',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'0', 'x-compute-request-id': "
+                "'req-6e7fa28f-ae61-4388-9a78-947c58bc0588', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:01 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents/3',
+                'verb': 'DELETE'}, {
+                'name': 'AgentsAdminTestJSON:test_delete_agent',
+                'request_body': 'None',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_body': '{"agents": []}',
+                'response_headers': "{'status': '200', 'content-length': "
+                "'14', 'content-location': "
+                "'http://23.253.76.97:8774/v2.1/"
+                "cf6b1933fe5b476fbbabb876f6d1b924/os-agents', "
+                "'x-compute-request-id': "
+                "'req-e41aa9b4-41a6-4138-ae04-220b768eb644', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:01 GMT', 'content-type': "
+                "'application/json'}",
+                'service': 'Nova',
+                'status_code': '200',
+                'url': 'v2.1/<id>/os-agents',
+                'verb': 'GET'}, {
+                'name': 'AgentsAdminTestJSON:tearDown',
+                'request_body': 'None',
+                'request_headers': "{'Content-Type': 'application/json', "
+                "'Accept': 'application/json', 'X-Auth-Token': '<omitted>'}",
+                'response_headers': "{'status': '404', 'content-length': "
+                "'82', 'x-compute-request-id': "
+                "'req-e297aeea-91cf-4f26-b49c-8f46b1b7a926', 'vary': "
+                "'X-OpenStack-Nova-API-Version', 'connection': 'close', "
+                "'x-openstack-nova-api-version': '2.1', 'date': "
+                "'Tue, 02 Feb 2016 03:27:02 GMT', 'content-type': "
+                "'application/json; charset=UTF-8'}",
+                'service': 'Nova',
+                'status_code': '404',
+                'url': 'v2.1/<id>/os-agents/3',
+                'verb': 'DELETE'}]}
+
         self.assertEqual(expected_result, parser.test_logs)
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/fake_tempest_plugin.py b/tempest/tests/fake_tempest_plugin.py
index f718d0b..56aae1e 100644
--- a/tempest/tests/fake_tempest_plugin.py
+++ b/tempest/tests/fake_tempest_plugin.py
@@ -18,6 +18,7 @@
 
 class FakePlugin(plugins.TempestPlugin):
     expected_load_test = ["my/test/path", "/home/dir"]
+    expected_service_clients = [{'foo': 'bar'}]
 
     def load_tests(self):
         return self.expected_load_test
@@ -28,6 +29,9 @@
     def get_opt_lists(self):
         return []
 
+    def get_service_clients(self):
+        return self.expected_service_clients
+
 
 class FakeStevedoreObj(object):
     obj = FakePlugin()
@@ -38,3 +42,26 @@
 
     def __init__(self, name='Test1'):
         self._name = name
+
+
+class FakePluginNoServiceClients(plugins.TempestPlugin):
+
+    def load_tests(self):
+        return []
+
+    def register_opts(self, conf):
+        return
+
+    def get_opt_lists(self):
+        return []
+
+
+class FakeStevedoreObjNoServiceClients(object):
+    obj = FakePluginNoServiceClients()
+
+    @property
+    def name(self):
+        return self._name
+
+    def __init__(self, name='Test2'):
+        self._name = name
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/services/identity/v3/test_endpoints_client.py b/tempest/tests/lib/services/identity/v3/test_endpoints_client.py
new file mode 100644
index 0000000..f8c553f
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_endpoints_client.py
@@ -0,0 +1,100 @@
+# 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 endpoints_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestEndpointsClient(base.BaseServiceTest):
+    FAKE_CREATE_ENDPOINT = {
+        "endpoint": {
+            "id": 1,
+            "tenantId": 1,
+            "region": "North",
+            "type": "compute",
+            "publicURL": "https://compute.north.public.com/v1",
+            "internalURL": "https://compute.north.internal.com/v1",
+            "adminURL": "https://compute.north.internal.com/v1"
+        }
+    }
+
+    FAKE_LIST_ENDPOINTS = {
+        "endpoints": [
+            {
+                "id": 1,
+                "tenantId": "1",
+                "region": "North",
+                "type": "compute",
+                "publicURL": "https://compute.north.public.com/v1",
+                "internalURL": "https://compute.north.internal.com/v1",
+                "adminURL": "https://compute.north.internal.com/v1"
+            },
+            {
+                "id": 2,
+                "tenantId": "1",
+                "region": "South",
+                "type": "compute",
+                "publicURL": "https://compute.north.public.com/v1",
+                "internalURL": "https://compute.north.internal.com/v1",
+                "adminURL": "https://compute.north.internal.com/v1"
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestEndpointsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = endpoints_client.EndPointsClient(fake_auth,
+                                                       'identity', 'regionOne')
+
+    def _test_create_endpoint(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_endpoint,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_ENDPOINT,
+            bytes_body,
+            status=201,
+            service_id="b344506af7644f6794d9cb316600b020",
+            region="region-demo",
+            publicurl="https://compute.north.public.com/v1",
+            adminurl="https://compute.north.internal.com/v1",
+            internalurl="https://compute.north.internal.com/v1")
+
+    def _test_list_endpoints(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_endpoints,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_ENDPOINTS,
+            bytes_body)
+
+    def test_create_endpoint_with_str_body(self):
+        self._test_create_endpoint()
+
+    def test_create_endpoint_with_bytes_body(self):
+        self._test_create_endpoint(bytes_body=True)
+
+    def test_list_endpoints_with_str_body(self):
+        self._test_list_endpoints()
+
+    def test_list_endpoints_with_bytes_body(self):
+        self._test_list_endpoints(bytes_body=True)
+
+    def test_delete_endpoint(self):
+        self.check_service_client_function(
+            self.client.delete_endpoint,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            endpoint_id="b344506af7644f6794d9cb316600b020",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_policies_client.py b/tempest/tests/lib/services/identity/v3/test_policies_client.py
new file mode 100644
index 0000000..66c3d65
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_policies_client.py
@@ -0,0 +1,152 @@
+# 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 policies_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestPoliciesClient(base.BaseServiceTest):
+    FAKE_CREATE_POLICY = {
+        "policy": {
+            "blob": "{'foobar_user': 'role:compute-user'}",
+            "project_id": "0426ac1e48f642ef9544c2251e07e261",
+            "type": "application/json",
+            "user_id": "0ffd248c55b443eaac5253b4e9cbf9b5"
+            }
+        }
+
+    FAKE_POLICY_INFO = {
+        "policy": {
+            "blob": {
+                "foobar_user": [
+                    "role:compute-user"
+                    ]
+                },
+            "id": "717273",
+            "links": {
+                "self": "http://example.com/identity/v3/policies/717273"
+                },
+            "project_id": "456789",
+            "type": "application/json",
+            "user_id": "616263"
+            }
+        }
+
+    FAKE_LIST_POLICIES = {
+        "links": {
+            "next": None,
+            "previous": None,
+            "self": "http://example.com/identity/v3/policies"
+            },
+        "policies": [
+            {
+                "blob": {
+                    "foobar_user": [
+                        "role:compute-user"
+                        ]
+                    },
+                "id": "717273",
+                "links": {
+                    "self": "http://example.com/identity/v3/policies/717273"
+                    },
+                "project_id": "456789",
+                "type": "application/json",
+                "user_id": "616263"
+                },
+            {
+                "blob": {
+                    "foobar_user": [
+                        "role:compute-user"
+                        ]
+                    },
+                "id": "717274",
+                "links": {
+                    "self": "http://example.com/identity/v3/policies/717274"
+                    },
+                "project_id": "456789",
+                "type": "application/json",
+                "user_id": "616263"
+                }
+            ]
+    }
+
+    def setUp(self):
+        super(TestPoliciesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = policies_client.PoliciesClient(fake_auth,
+                                                     'identity', 'regionOne')
+
+    def _test_create_policy(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_policy,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_POLICY,
+            bytes_body,
+            status=201)
+
+    def _test_show_policy(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_policy,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_POLICY_INFO,
+            bytes_body,
+            policy_id="717273")
+
+    def _test_list_policies(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_policies,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_POLICIES,
+            bytes_body)
+
+    def _test_update_policy(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_policy,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_POLICY_INFO,
+            bytes_body,
+            policy_id="717273")
+
+    def test_create_policy_with_str_body(self):
+        self._test_create_policy()
+
+    def test_create_policy_with_bytes_body(self):
+        self._test_create_policy(bytes_body=True)
+
+    def test_show_policy_with_str_body(self):
+        self._test_show_policy()
+
+    def test_show_policy_with_bytes_body(self):
+        self._test_show_policy(bytes_body=True)
+
+    def test_list_policies_with_str_body(self):
+        self._test_list_policies()
+
+    def test_list_policies_with_bytes_body(self):
+        self._test_list_policies(bytes_body=True)
+
+    def test_update_policy_with_str_body(self):
+        self._test_update_policy()
+
+    def test_update_policy_with_bytes_body(self):
+        self._test_update_policy(bytes_body=True)
+
+    def test_delete_policy(self):
+        self.check_service_client_function(
+            self.client.delete_policy,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            policy_id="717273",
+            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/lib/services/test_clients.py b/tempest/tests/lib/services/test_clients.py
new file mode 100644
index 0000000..5db932c
--- /dev/null
+++ b/tempest/tests/lib/services/test_clients.py
@@ -0,0 +1,370 @@
+# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import fixtures
+import mock
+import testtools
+import types
+
+from tempest.lib import auth
+from tempest.lib import exceptions
+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
+
+
+has_attribute = testtools.matchers.MatchesPredicateWithParams(
+    lambda x, y: hasattr(x, y), '{0} does not have an attribute {1}')
+
+
+class TestClientsFactory(base.TestCase):
+
+    def setUp(self):
+        super(TestClientsFactory, self).setUp()
+        self.classes = []
+
+    def _setup_fake_module(self, class_names=None, extra_dict=None):
+        class_names = class_names or []
+        fake_module = types.ModuleType('fake_service_client')
+        _dict = {}
+        # Add fake classes to the fake module
+        for name in class_names:
+            _dict[name] = type(name, (object,), {})
+            # Store it for assertions
+            self.classes.append(_dict[name])
+        if extra_dict:
+            _dict[extra_dict] = extra_dict
+        fake_module.__dict__.update(_dict)
+        fixture_importlib = self.useFixture(fixtures.MockPatch(
+            'importlib.import_module', return_value=fake_module))
+        return fixture_importlib.mock
+
+    def test___init___one_class(self):
+        fake_partial = 'fake_partial'
+        partial_mock = self.useFixture(fixtures.MockPatch(
+            '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 = 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
+        for client in class_names:
+            self.assertThat(factory, has_attribute(client))
+        # Partial have been invoked correctly
+        partial_mock.assert_called_once_with(
+            self.classes[0], auth_provider, params)
+        # Get the clients
+        for name in class_names:
+            self.assertEqual(fake_partial, getattr(factory, name))
+
+    def test___init___two_classes(self):
+        fake_partial = 'fake_partial'
+        partial_mock = self.useFixture(fixtures.MockPatch(
+            '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 = 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
+        for client in class_names:
+            self.assertThat(factory, has_attribute(client))
+        # Partial have been invoked the right number of times
+        partial_mock.call_count = len(class_names)
+        # Get the clients
+        for name in class_names:
+            self.assertEqual(fake_partial, getattr(factory, name))
+
+    def test___init___no_module(self):
+        auth_provider = fake_auth_provider.FakeAuthProvider()
+        class_names = ['FakeServiceClient1', 'FakeServiceClient2']
+        with testtools.ExpectedException(ImportError, '.*fake_module.*'):
+            clients.ClientsFactory('fake_module', class_names,
+                                   auth_provider)
+
+    def test___init___not_a_class(self):
+        class_names = ['FakeServiceClient1', 'FakeServiceClient2']
+        extended_class_names = class_names + ['not_really_a_class']
+        self._setup_fake_module(
+            class_names=class_names, extra_dict='not_really_a_class')
+        auth_provider = fake_auth_provider.FakeAuthProvider()
+        expected_msg = '.*not_really_a_class.*str.*'
+        with testtools.ExpectedException(TypeError, expected_msg):
+            clients.ClientsFactory('fake_module', extended_class_names,
+                                   auth_provider)
+
+    def test___init___class_not_found(self):
+        class_names = ['FakeServiceClient1', 'FakeServiceClient2']
+        extended_class_names = class_names + ['not_really_a_class']
+        self._setup_fake_module(class_names=class_names)
+        auth_provider = fake_auth_provider.FakeAuthProvider()
+        expected_msg = '.*not_really_a_class.*fake_service_client.*'
+        with testtools.ExpectedException(AttributeError, expected_msg):
+            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 = 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)
+        # Class has not be initialised yet
+        klass_mock.assert_not_called()
+        # Use partial and assert on parameters
+        client = partial()
+        self.assertEqual(expected_fake_client, client)
+        klass_mock.assert_called_once_with(auth_provider=auth_provider,
+                                           **params)
+
+    def test__get_partial_class_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'}
+        later_params = {'k2': 'v4', 'k3': 'v3'}
+        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)
+        # Class has not be initialised yet
+        klass_mock.assert_not_called()
+        # Use partial and assert on parameters
+        client = partial(**later_params)
+        params.update(later_params)
+        self.assertEqual(expected_fake_client, client)
+        klass_mock.assert_called_once_with(auth_provider=auth_provider,
+                                           **params)
+
+    def test__get_partial_class_with_alias(self):
+        expected_fake_client = 'not_really_a_client'
+        client_alias = 'fake_client'
+        self._setup_fake_module(class_names=[])
+        auth_provider = fake_auth_provider.FakeAuthProvider()
+        params = {'k1': 'v1', 'k2': 'v2'}
+        later_params = {'k2': 'v4', 'k3': 'v3'}
+        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)
+        # Class has not be initialised yet
+        klass_mock.assert_not_called()
+        # Use partial and assert on parameters
+        client = partial(alias=client_alias, **later_params)
+        params.update(later_params)
+        self.assertEqual(expected_fake_client, client)
+        klass_mock.assert_called_once_with(auth_provider=auth_provider,
+                                           **params)
+        self.assertThat(factory, has_attribute(client_alias))
+        self.assertEqual(expected_fake_client, getattr(factory, client_alias))
+
+
+class TestServiceClients(base.TestCase):
+
+    def setUp(self):
+        super(TestServiceClients, self).setUp()
+        self.useFixture(fixtures.MockPatch(
+            '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 = clients.ServiceClients(creds, identity_uri=uri)
+        self.assertIsInstance(_manager.auth_provider,
+                              auth.KeystoneV2AuthProvider)
+
+    def test___init___creds_v3_uri(self):
+        # Verify that no API request is made, since no mock
+        # is required to run the test successfully
+        creds = fake_credentials.FakeKeystoneV3Credentials()
+        uri = 'fake_uri'
+        _manager = clients.ServiceClients(creds, identity_uri=uri)
+        self.assertIsInstance(_manager.auth_provider,
+                              auth.KeystoneV3AuthProvider)
+
+    def test___init___base_creds_uri(self):
+        creds = fake_credentials.FakeCredentials()
+        uri = 'fake_uri'
+        with testtools.ExpectedException(exceptions.InvalidCredentials):
+            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):
+            clients.ServiceClients(creds, identity_uri=uri)
+
+    def test___init___creds_uri_none(self):
+        creds = fake_credentials.FakeKeystoneV2Credentials()
+        msg = ("Invalid Credentials\nDetails: ServiceClients requires a "
+               "non-empty")
+        with testtools.ExpectedException(exceptions.InvalidCredentials,
+                                         value_re=msg):
+            clients.ServiceClients(creds, None)
+
+    def test___init___creds_uri_params(self):
+        creds = fake_credentials.FakeKeystoneV2Credentials()
+        expeted_params = {'fake_param1': 'fake_value1',
+                          'fake_param2': 'fake_value2'}
+        params = {'fake_service1': expeted_params}
+        uri = 'fake_uri'
+        _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())
+            self.assertEqual(expeted_params[_key],
+                             _manager.parameters['fake_service1'].get(_key))
+
+    def test___init___creds_uri_params_unknown_services(self):
+        creds = fake_credentials.FakeKeystoneV2Credentials()
+        fake_params = {'fake_param1': 'fake_value1'}
+        params = {'unknown_service1': fake_params,
+                  'unknown_service2': fake_params}
+        uri = 'fake_uri'
+        msg = "(?=.*{0})(?=.*{1})".format(*list(params.keys()))
+        with testtools.ExpectedException(
+                exceptions.UnknownServiceClient, value_re=msg):
+            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 clients.ServiceClients(creds, identity_uri='fake_uri',
+                                      region=init_region)
+
+    def test__setup_parameters_none_no_region(self):
+        kwargs = {}
+        _manager = self._get_manager(init_region=None)
+        _params = _manager._setup_parameters(kwargs)
+        self.assertNotIn('region', _params)
+
+    def test__setup_parameters_none(self):
+        kwargs = {}
+        _manager = self._get_manager()
+        _params = _manager._setup_parameters(kwargs)
+        self.assertIn('region', _params)
+        self.assertEqual('fake_region', _params['region'])
+
+    def test__setup_parameters_all(self):
+        expected_params = {'region': 'fake_region1',
+                           'catalog_type': 'fake_service2_mod',
+                           'fake_param1': 'fake_value1',
+                           'fake_param2': 'fake_value2'}
+        _manager = self._get_manager()
+        _params = _manager._setup_parameters(expected_params)
+        for _key in _params.keys():
+            self.assertEqual(expected_params[_key],
+                             _params[_key])
+
+    def test_register_service_client_module(self):
+        expected_params = {'fake_param1': 'fake_value1',
+                           'fake_param2': 'fake_value2'}
+        _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.lib.services.clients.ClientsFactory')).mock
+        _manager.register_service_client_module(
+            name='fake_module',
+            service_version='fake_service',
+            module_path='fake.path.to.module',
+            client_names=[],
+            **expected_params)
+        self.assertThat(_manager, has_attribute('fake_module'))
+        # Assert called once, without check for exact parameters
+        self.assertTrue(factory_mock.called)
+        self.assertEqual(1, factory_mock.call_count)
+        # Assert expected params are in with their values
+        actual_kwargs = factory_mock.call_args[1]
+        self.assertIn('region', actual_kwargs)
+        self.assertEqual('fake_region_default', actual_kwargs['region'])
+        for param in expected_params:
+            self.assertIn(param, actual_kwargs)
+            self.assertEqual(expected_params[param], actual_kwargs[param])
+        # Assert the new service is registered
+        self.assertIn('fake_service', _manager._registered_services)
+
+    def test_register_service_client_module_override_default(self):
+        new_region = 'new_region'
+        expected_params = {'fake_param1': 'fake_value1',
+                           'fake_param2': 'fake_value2',
+                           'region': new_region}
+        _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.lib.services.clients.ClientsFactory')).mock
+        _manager.register_service_client_module(
+            name='fake_module',
+            service_version='fake_service',
+            module_path='fake.path.to.module',
+            client_names=[],
+            **expected_params)
+        self.assertThat(_manager, has_attribute('fake_module'))
+        # Assert called once, without check for exact parameters
+        self.assertTrue(factory_mock.called)
+        self.assertEqual(1, factory_mock.call_count)
+        # Assert expected params are in with their values
+        actual_kwargs = factory_mock.call_args[1]
+        self.assertIn('region', actual_kwargs)
+        self.assertEqual(new_region, actual_kwargs['region'])
+        for param in expected_params:
+            self.assertIn(param, actual_kwargs)
+            self.assertEqual(expected_params[param], actual_kwargs[param])
+        # Assert the new service is registered
+        self.assertIn('fake_service', _manager._registered_services)
+
+    def test_register_service_client_module_duplicate_name(self):
+        self.useFixture(fixtures.MockPatch(
+            'tempest.lib.services.clients.ClientsFactory')).mock
+        _manager = self._get_manager()
+        name_owner = 'this_is_a_string'
+        setattr(_manager, 'fake_module', name_owner)
+        expected_error = '.*' + name_owner
+        with testtools.ExpectedException(
+                exceptions.ServiceClientRegistrationException, expected_error):
+            _manager.register_service_client_module(
+                name='fake_module', module_path='fake.path.to.module',
+                service_version='fake_service', client_names=[])
+
+    def test_register_service_client_module_duplicate_service(self):
+        self.useFixture(fixtures.MockPatch(
+            'tempest.lib.services.clients.ClientsFactory')).mock
+        _manager = self._get_manager()
+        duplicate_service = 'fake_service1'
+        expected_error = '.*' + duplicate_service
+        with testtools.ExpectedException(
+                exceptions.ServiceClientRegistrationException, expected_error):
+            _manager.register_service_client_module(
+                name='fake_module', module_path='fake.path.to.module',
+                service_version=duplicate_service, client_names=[])
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index 12590a3..6da7e41 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -244,7 +244,7 @@
         # The original headers where empty
         self.assertNotEqual(url, self.target_url)
         self.assertIsNone(headers)
-        self.assertEqual(body, None)
+        self.assertIsNone(body)
 
     def _test_request_with_alt_part_without_alt_data_no_change(self, body):
         """Test empty alternate auth data with no effect
diff --git a/tempest/tests/negative/test_negative_generators.py b/tempest/tests/negative/test_negative_generators.py
index 78fd80d..2e45ef7 100644
--- a/tempest/tests/negative/test_negative_generators.py
+++ b/tempest/tests/negative/test_negative_generators.py
@@ -146,5 +146,5 @@
             schema_under_test = copy.copy(valid_schema)
             expected_result = \
                 self.generator.generate_payload(test, schema_under_test)
-            self.assertEqual(expected_result, None)
+            self.assertIsNone(expected_result)
             self._validate_result(valid_schema, schema_under_test)
diff --git a/tempest/tests/test_service_clients.py b/tempest/tests/test_service_clients.py
deleted file mode 100644
index a559086..0000000
--- a/tempest/tests/test_service_clients.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-
-import fixtures
-import testtools
-
-from tempest.lib import auth
-from tempest.lib import exceptions
-from tempest import service_clients
-from tempest.tests import base
-from tempest.tests.lib import fake_credentials
-
-
-class TestServiceClients(base.TestCase):
-
-    def setUp(self):
-        super(TestServiceClients, self).setUp()
-        self.useFixture(fixtures.MockPatch(
-            'tempest.service_clients.tempest_modules',
-            return_value=set(['fake_service1', 'fake_service2'])))
-
-    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)
-        self.assertIsInstance(_manager.auth_provider,
-                              auth.KeystoneV2AuthProvider)
-
-    def test___init___creds_v3_uri(self):
-        # Verify that no API request is made, since no mock
-        # is required to run the test successfully
-        creds = fake_credentials.FakeKeystoneV3Credentials()
-        uri = 'fake_uri'
-        _manager = service_clients.ServiceClients(creds, identity_uri=uri)
-        self.assertIsInstance(_manager.auth_provider,
-                              auth.KeystoneV3AuthProvider)
-
-    def test___init___base_creds_uri(self):
-        creds = fake_credentials.FakeCredentials()
-        uri = 'fake_uri'
-        with testtools.ExpectedException(exceptions.InvalidCredentials):
-            service_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)
-
-    def test___init___creds_uri_none(self):
-        creds = fake_credentials.FakeKeystoneV2Credentials()
-        msg = ("Invalid Credentials\nDetails: ServiceClients requires a "
-               "non-empty")
-        with testtools.ExpectedException(exceptions.InvalidCredentials,
-                                         value_re=msg):
-            service_clients.ServiceClients(creds, None)
-
-    def test___init___creds_uri_params(self):
-        creds = fake_credentials.FakeKeystoneV2Credentials()
-        expeted_params = {'fake_param1': 'fake_value1',
-                          'fake_param2': 'fake_value2'}
-        params = {'fake_service1': expeted_params}
-        uri = 'fake_uri'
-        _manager = service_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())
-            self.assertEqual(expeted_params[_key],
-                             _manager.parameters['fake_service1'].get(_key))
-
-    def test___init___creds_uri_params_unknown_services(self):
-        creds = fake_credentials.FakeKeystoneV2Credentials()
-        fake_params = {'fake_param1': 'fake_value1'}
-        params = {'unknown_service1': fake_params,
-                  'unknown_service2': fake_params}
-        uri = 'fake_uri'
-        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)
-
-    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)
-
-    def test__setup_parameters_none_no_region(self):
-        kwargs = {}
-        _manager = self._get_manager(init_region=None)
-        _params = _manager._setup_parameters(kwargs)
-        self.assertNotIn('region', _params)
-
-    def test__setup_parameters_none(self):
-        kwargs = {}
-        _manager = self._get_manager()
-        _params = _manager._setup_parameters(kwargs)
-        self.assertIn('region', _params)
-        self.assertEqual('fake_region', _params['region'])
-
-    def test__setup_parameters_all(self):
-        expected_params = {'region': 'fake_region1',
-                           'catalog_type': 'fake_service2_mod',
-                           'fake_param1': 'fake_value1',
-                           'fake_param2': 'fake_value2'}
-        _manager = self._get_manager()
-        _params = _manager._setup_parameters(expected_params)
-        for _key in _params.keys():
-            self.assertEqual(expected_params[_key],
-                             _params[_key])
diff --git a/tempest/tests/test_tempest_plugin.py b/tempest/tests/test_tempest_plugin.py
index c07e98c..dd50125 100644
--- a/tempest/tests/test_tempest_plugin.py
+++ b/tempest/tests/test_tempest_plugin.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.services import clients
 from tempest.test_discover import plugins
 from tempest.tests import base
 from tempest.tests import fake_tempest_plugin as fake_plugin
@@ -42,3 +43,39 @@
                          result['fake01'])
         self.assertEqual(fake_plugin.FakePlugin.expected_load_test,
                          result['fake02'])
+
+    def test__register_service_clients_with_one_plugin(self):
+        registry = clients.ClientsRegistry()
+        manager = plugins.TempestTestPluginManager()
+        fake_obj = fake_plugin.FakeStevedoreObj()
+        manager.ext_plugins = [fake_obj]
+        manager._register_service_clients()
+        expected_result = fake_plugin.FakePlugin.expected_service_clients
+        registered_clients = registry.get_service_clients()
+        self.assertIn(fake_obj.name, registered_clients)
+        self.assertEqual(expected_result, registered_clients[fake_obj.name])
+
+    def test__get_service_clients_with_two_plugins(self):
+        registry = clients.ClientsRegistry()
+        manager = plugins.TempestTestPluginManager()
+        obj1 = fake_plugin.FakeStevedoreObj('fake01')
+        obj2 = fake_plugin.FakeStevedoreObj('fake02')
+        manager.ext_plugins = [obj1, obj2]
+        manager._register_service_clients()
+        expected_result = fake_plugin.FakePlugin.expected_service_clients
+        registered_clients = registry.get_service_clients()
+        self.assertIn('fake01', registered_clients)
+        self.assertIn('fake02', registered_clients)
+        self.assertEqual(expected_result, registered_clients['fake01'])
+        self.assertEqual(expected_result, registered_clients['fake02'])
+
+    def test__register_service_clients_one_plugin_no_service_clients(self):
+        registry = clients.ClientsRegistry()
+        manager = plugins.TempestTestPluginManager()
+        fake_obj = fake_plugin.FakeStevedoreObjNoServiceClients()
+        manager.ext_plugins = [fake_obj]
+        manager._register_service_clients()
+        expected_result = []
+        registered_clients = registry.get_service_clients()
+        self.assertIn(fake_obj.name, registered_clients)
+        self.assertEqual(expected_result, registered_clients[fake_obj.name])
diff --git a/tox.ini b/tox.ini
index a33101b..a621492 100644
--- a/tox.ini
+++ b/tox.ini
@@ -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