Merge "PCI-DSS tests"
diff --git a/README.rst b/README.rst
index fc4de5e..281516b 100644
--- a/README.rst
+++ b/README.rst
@@ -1,3 +1,13 @@
+========================
+Team and repository tags
+========================
+
+.. image:: http://governance.openstack.org/badges/tempest.svg
+    :target: http://governance.openstack.org/reference/tags/index.html
+    :remote:
+
+.. Change things from this point on
+
 Tempest - The OpenStack Integration Test Suite
 ==============================================
 
diff --git a/REVIEWING.rst b/REVIEWING.rst
index cfe7f4c..9b272bb 100644
--- a/REVIEWING.rst
+++ b/REVIEWING.rst
@@ -93,6 +93,12 @@
 
 .. _reno: http://docs.openstack.org/developer/reno/
 
+Deprecated Code
+---------------
+Sometimes we have some bugs in deprecated code. Basically, we leave it. Because
+we don't need to maintain it. However, if the bug is critical, we might need to
+fix it. When it will happen, we will deal with it on a case-by-case basis.
+
 When to approve
 ---------------
  * Every patch needs two +2s before being approved.
diff --git a/bindep.txt b/bindep.txt
new file mode 100644
index 0000000..6a28348
--- /dev/null
+++ b/bindep.txt
@@ -0,0 +1,11 @@
+# This file contains runtime (non-python) dependencies
+# More info at: http://docs.openstack.org/infra/bindep/readme.html
+
+libffi-dev [platform:dpkg]
+libffi-devel [platform:rpm]
+gcc [platform:rpm]
+gcc [platform:dpkg]
+python-dev [platform:dpkg]
+python-devel [platform:rpm]
+openssl-devel [platform:rpm]
+libssl-dev [platform:dpkg]
diff --git a/doc/source/library/api_microversion_testing.rst b/doc/source/library/api_microversion_testing.rst
index b7a4ba8..8be924d 100644
--- a/doc/source/library/api_microversion_testing.rst
+++ b/doc/source/library/api_microversion_testing.rst
@@ -1,6 +1,6 @@
 .. _api_microversion_testing:
 
-API Microversion Testing Support in Temepst
+API Microversion Testing Support in Tempest
 ===========================================
 
 ---------------------------------------------
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index dc73ef2..6b87b4d 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -236,6 +236,10 @@
 
  .. _2.25: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-mitaka
 
+ * `2.32`_
+
+ .. _2.32: http://docs.openstack.org/developer/nova/api_microversion_history.html#id29
+
  * `2.37`_
 
  .. _2.37: http://docs.openstack.org/developer/nova/api_microversion_history.html#id34
diff --git a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml b/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
index 53741da..484d543 100644
--- a/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
+++ b/releasenotes/notes/12.2.0-clients_module-16f3025f515bf9ec.yaml
@@ -8,7 +8,7 @@
     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
+    which are in tempest.lib, i.e. compute, network and image. The remaining
     service clients (identity, volume and object-storage) will be added in
     future updates.
 deprecations:
diff --git a/releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml b/releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml
index 056e199..6babd93 100644
--- a/releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml
+++ b/releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml
@@ -8,3 +8,5 @@
 
     * volumes_client(v1)
     * volumes_client(v2)
+    * capabilities_client(v2)
+    * scheduler_stats_client(v2)
diff --git a/releasenotes/notes/add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml b/releasenotes/notes/add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
new file mode 100644
index 0000000..432a6b1
--- /dev/null
+++ b/releasenotes/notes/add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - The cred_client module was added to tempest.lib. This module provides a
+    wrapper to the keystone services client which provides a uniform
+    interface that abstracts out the differences between keystone api versions.
diff --git a/releasenotes/notes/add-image-clients-af94564fb34ddca6.yaml b/releasenotes/notes/add-image-clients-af94564fb34ddca6.yaml
new file mode 100644
index 0000000..7e40fd4
--- /dev/null
+++ b/releasenotes/notes/add-image-clients-af94564fb34ddca6.yaml
@@ -0,0 +1,9 @@
+---
+features:
+  - |
+    As in the [doc]:
+    http://developer.openstack.org/api-ref/image/v2/metadefs-index.html,
+    there are some apis are not included, add them.
+
+      * namespace_properties_client(v2)
+
diff --git a/releasenotes/notes/add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml b/releasenotes/notes/add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
new file mode 100644
index 0000000..a1edcc5
--- /dev/null
+++ b/releasenotes/notes/add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
@@ -0,0 +1,6 @@
+---
+features:
+    - Define the identity service role_assignments_client as a library.
+      Add role_assignments_client to the library interface so the other
+      projects can use this module as a stable library without any
+      maintenance changes.
diff --git a/releasenotes/notes/add-service-provider-client-cbba77d424a30dd3.yaml b/releasenotes/notes/add-service-provider-client-cbba77d424a30dd3.yaml
new file mode 100644
index 0000000..b504c78
--- /dev/null
+++ b/releasenotes/notes/add-service-provider-client-cbba77d424a30dd3.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - A Neutron Service Providers client is added to deal with resources
+    of the '/service-providers' route.
diff --git a/releasenotes/notes/move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml b/releasenotes/notes/move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
new file mode 100644
index 0000000..9223ba5
--- /dev/null
+++ b/releasenotes/notes/move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
@@ -0,0 +1,7 @@
+features:
+  - |
+    Define the Volume v3 service clients as library interfaces,
+    allowing other projects to use these modules as stable
+    libraries without maintenance changes.
+
+    * messages_client(v3)
diff --git a/releasenotes/notes/new-volume-limit-client-517c17d9090f4df4.yaml b/releasenotes/notes/new-volume-limit-client-517c17d9090f4df4.yaml
new file mode 100644
index 0000000..033e147
--- /dev/null
+++ b/releasenotes/notes/new-volume-limit-client-517c17d9090f4df4.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - The volume_limits client was added to tempest.lib.
diff --git a/releasenotes/notes/remove-bootable-option-024f8944c056a3e0.yaml b/releasenotes/notes/remove-bootable-option-024f8944c056a3e0.yaml
new file mode 100644
index 0000000..e6e53af
--- /dev/null
+++ b/releasenotes/notes/remove-bootable-option-024f8944c056a3e0.yaml
@@ -0,0 +1,6 @@
+---
+deprecations:
+  - The *bootable* config option in the *volume_feature_enabled* group is
+    removed because the corresponding feature os-set_bootable has been
+    implemented 2.5 years ago and all OpenStack versions which are supported
+    by Tempest should support the feature.
diff --git a/releasenotes/notes/remove-negative-test-generator-1653f4c0f86ccf75.yaml b/releasenotes/notes/remove-negative-test-generator-1653f4c0f86ccf75.yaml
new file mode 100644
index 0000000..a734d15
--- /dev/null
+++ b/releasenotes/notes/remove-negative-test-generator-1653f4c0f86ccf75.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - The Negative Tests Generator has been removed (it was not used by any
+    Tempest tests).
diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst
index 5860a46..875030f 100644
--- a/releasenotes/source/unreleased.rst
+++ b/releasenotes/source/unreleased.rst
@@ -1,5 +1,5 @@
-==========================
- Unreleased Release Notes
-==========================
+============================
+Current Series Release Notes
+============================
 
 .. release-notes::
diff --git a/requirements.txt b/requirements.txt
index 9079a8d..d9a9ebb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,18 +1,18 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-pbr>=1.6 # Apache-2.0
-cliff>=2.2.0 # Apache-2.0
+pbr>=1.8 # Apache-2.0
+cliff>=2.3.0 # Apache-2.0
 jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
 testtools>=1.4.0 # MIT
 paramiko>=2.0 # LGPLv2.1+
 netaddr!=0.7.16,>=0.7.13 # BSD
 testrepository>=0.0.18 # Apache-2.0/BSD
 oslo.concurrency>=3.8.0 # Apache-2.0
-oslo.config>=3.14.0 # Apache-2.0
+oslo.config!=3.18.0,>=3.14.0 # Apache-2.0
 oslo.log>=3.11.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils>=3.17.0 # Apache-2.0
+oslo.utils>=3.18.0 # Apache-2.0
 six>=1.9.0 # MIT
 fixtures>=3.0.0 # Apache-2.0/BSD
 PyYAML>=3.10.0 # MIT
diff --git a/tempest/api/baremetal/README.rst b/tempest/api/baremetal/README.rst
deleted file mode 100644
index 759c937..0000000
--- a/tempest/api/baremetal/README.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-Tempest Field Guide to Baremetal API tests
-==========================================
-
-
-What are these tests?
----------------------
-
-These tests stress the OpenStack baremetal provisioning API provided by
-Ironic.
-
-
-Why are these tests in tempest?
-------------------------------
-
-The purpose of these tests is to exercise the various APIs provided by Ironic
-for managing baremetal nodes.
-
-
-Scope of these tests
---------------------
-
-The baremetal API test perform basic CRUD operations on the Ironic node
-inventory.  They do not actually perform hardware provisioning. It is important
-to note that all Ironic API actions are admin operations meant to be used
-either by cloud operators or other OpenStack services (i.e., Nova).
diff --git a/tempest/api/baremetal/admin/__init__.py b/tempest/api/baremetal/admin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/baremetal/admin/__init__.py
+++ /dev/null
diff --git a/tempest/api/baremetal/admin/base.py b/tempest/api/baremetal/admin/base.py
deleted file mode 100644
index ac5986c..0000000
--- a/tempest/api/baremetal/admin/base.py
+++ /dev/null
@@ -1,206 +0,0 @@
-#    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 functools
-
-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
-
-
-# NOTE(adam_g): The baremetal API tests exercise operations such as enroll
-# node, power on, power off, etc.  Testing against real drivers (ie, IPMI)
-# will require passing driver-specific data to Tempest (addresses,
-# credentials, etc).  Until then, only support testing against the fake driver,
-# which has no external dependencies.
-SUPPORTED_DRIVERS = ['fake']
-
-# NOTE(jroll): resources must be deleted in a specific order, this list
-# defines the resource types to clean up, and the correct order.
-RESOURCE_TYPES = ['port', 'node', 'chassis']
-
-
-def creates(resource):
-    """Decorator that adds resources to the appropriate cleanup list."""
-
-    def decorator(f):
-        @functools.wraps(f)
-        def wrapper(cls, *args, **kwargs):
-            resp, body = f(cls, *args, **kwargs)
-
-            if 'uuid' in body:
-                cls.created_objects[resource].add(body['uuid'])
-
-            return resp, body
-        return wrapper
-    return decorator
-
-
-class BaseBaremetalTest(test.BaseTestCase):
-    """Base class for Baremetal API tests."""
-
-    credentials = ['admin']
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaseBaremetalTest, cls).skip_checks()
-        if not CONF.service_available.ironic:
-            skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
-            raise cls.skipException(skip_msg)
-
-        if CONF.baremetal.driver not in SUPPORTED_DRIVERS:
-            skip_msg = ('%s skipped as Ironic driver %s is not supported for '
-                        'testing.' %
-                        (cls.__name__, CONF.baremetal.driver))
-            raise cls.skipException(skip_msg)
-
-    @classmethod
-    def setup_clients(cls):
-        super(BaseBaremetalTest, cls).setup_clients()
-        cls.client = cls.os_admin.baremetal_client
-
-    @classmethod
-    def resource_setup(cls):
-        super(BaseBaremetalTest, cls).resource_setup()
-
-        cls.driver = CONF.baremetal.driver
-        cls.power_timeout = CONF.baremetal.power_timeout
-        cls.created_objects = {}
-        for resource in RESOURCE_TYPES:
-            cls.created_objects[resource] = set()
-
-    @classmethod
-    def resource_cleanup(cls):
-        """Ensure that all created objects get destroyed."""
-
-        try:
-            for resource in RESOURCE_TYPES:
-                uuids = cls.created_objects[resource]
-                delete_method = getattr(cls.client, 'delete_%s' % resource)
-                for u in uuids:
-                    delete_method(u, ignore_errors=lib_exc.NotFound)
-        finally:
-            super(BaseBaremetalTest, cls).resource_cleanup()
-
-    @classmethod
-    @creates('chassis')
-    def create_chassis(cls, description=None):
-        """Wrapper utility for creating test chassis.
-
-        :param description: A description of the chassis. If not supplied,
-            a random value will be generated.
-        :return: Created chassis.
-
-        """
-        description = description or data_utils.rand_name('test-chassis')
-        resp, body = cls.client.create_chassis(description=description)
-        return resp, body
-
-    @classmethod
-    @creates('node')
-    def create_node(cls, chassis_id, cpu_arch='x86', cpus=8, local_gb=10,
-                    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.
-        :param memory_mb: Available RAM. Default: 4096.
-        :return: Created node.
-
-        """
-        resp, body = cls.client.create_node(chassis_id, cpu_arch=cpu_arch,
-                                            cpus=cpus, local_gb=local_gb,
-                                            memory_mb=memory_mb,
-                                            driver=cls.driver)
-
-        return resp, body
-
-    @classmethod
-    @creates('port')
-    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.
-        :param uuid: UUID of the port.
-        :return: Created port.
-
-        """
-        extra = extra or {}
-        resp, body = cls.client.create_port(address=address, node_id=node_id,
-                                            extra=extra, uuid=uuid)
-
-        return resp, body
-
-    @classmethod
-    def delete_chassis(cls, chassis_id):
-        """Deletes a chassis having the specified UUID.
-
-        :param chassis_id: The unique identifier of the chassis.
-        :return: Server response.
-
-        """
-
-        resp, body = cls.client.delete_chassis(chassis_id)
-
-        if chassis_id in cls.created_objects['chassis']:
-            cls.created_objects['chassis'].remove(chassis_id)
-
-        return resp
-
-    @classmethod
-    def delete_node(cls, node_id):
-        """Deletes a node having the specified UUID.
-
-        :param node_id: The unique identifier of the node.
-        :return: Server response.
-
-        """
-
-        resp, body = cls.client.delete_node(node_id)
-
-        if node_id in cls.created_objects['node']:
-            cls.created_objects['node'].remove(node_id)
-
-        return resp
-
-    @classmethod
-    def delete_port(cls, port_id):
-        """Deletes a port having the specified UUID.
-
-        :param port_id: The unique identifier of the port.
-        :return: Server response.
-
-        """
-
-        resp, body = cls.client.delete_port(port_id)
-
-        if port_id in cls.created_objects['port']:
-            cls.created_objects['port'].remove(port_id)
-
-        return resp
-
-    def validate_self_link(self, resource, uuid, link):
-        """Check whether the given self link formatted correctly."""
-        expected_link = "{base}/{pref}/{res}/{uuid}".format(
-                        base=self.client.base_url,
-                        pref=self.client.uri_prefix,
-                        res=resource,
-                        uuid=uuid)
-        self.assertEqual(expected_link, link)
diff --git a/tempest/api/baremetal/admin/test_api_discovery.py b/tempest/api/baremetal/admin/test_api_discovery.py
deleted file mode 100644
index 41388ad..0000000
--- a/tempest/api/baremetal/admin/test_api_discovery.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#    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.baremetal.admin import base
-from tempest import test
-
-
-class TestApiDiscovery(base.BaseBaremetalTest):
-    """Tests for API discovery features."""
-
-    @test.idempotent_id('a3c27e94-f56c-42c4-8600-d6790650b9c5')
-    def test_api_versions(self):
-        _, descr = self.client.get_api_description()
-        expected_versions = ('v1',)
-        versions = [version['id'] for version in descr['versions']]
-
-        for v in expected_versions:
-            self.assertIn(v, versions)
-
-    @test.idempotent_id('896283a6-488e-4f31-af78-6614286cbe0d')
-    def test_default_version(self):
-        _, descr = self.client.get_api_description()
-        default_version = descr['default_version']
-        self.assertEqual(default_version['id'], 'v1')
-
-    @test.idempotent_id('abc0b34d-e684-4546-9728-ab7a9ad9f174')
-    def test_version_1_resources(self):
-        _, descr = self.client.get_version_description(version='v1')
-        expected_resources = ('nodes', 'chassis',
-                              'ports', 'links', 'media_types')
-
-        for res in expected_resources:
-            self.assertIn(res, descr)
diff --git a/tempest/api/baremetal/admin/test_chassis.py b/tempest/api/baremetal/admin/test_chassis.py
deleted file mode 100644
index 339aaea..0000000
--- a/tempest/api/baremetal/admin/test_chassis.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-#    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 six
-
-from tempest.api.baremetal.admin import base
-from tempest.common.utils import data_utils
-from tempest.lib import exceptions as lib_exc
-from tempest import test
-
-
-class TestChassis(base.BaseBaremetalTest):
-    """Tests for chassis."""
-
-    @classmethod
-    def resource_setup(cls):
-        super(TestChassis, cls).resource_setup()
-        _, cls.chassis = cls.create_chassis()
-
-    def _assertExpected(self, expected, actual):
-        # Check if not expected keys/values exists in actual response body
-        for key, value in six.iteritems(expected):
-            if key not in ('created_at', 'updated_at'):
-                self.assertIn(key, actual)
-                self.assertEqual(value, actual[key])
-
-    @test.idempotent_id('7c5a2e09-699c-44be-89ed-2bc189992d42')
-    def test_create_chassis(self):
-        descr = data_utils.rand_name('test-chassis')
-        _, chassis = self.create_chassis(description=descr)
-        self.assertEqual(chassis['description'], descr)
-
-    @test.idempotent_id('cabe9c6f-dc16-41a7-b6b9-0a90c212edd5')
-    def test_create_chassis_unicode_description(self):
-        # Use a unicode string for testing:
-        # 'We ♡ OpenStack in Ukraine'
-        descr = u'В Україні ♡ OpenStack!'
-        _, chassis = self.create_chassis(description=descr)
-        self.assertEqual(chassis['description'], descr)
-
-    @test.idempotent_id('c84644df-31c4-49db-a307-8942881f41c0')
-    def test_show_chassis(self):
-        _, chassis = self.client.show_chassis(self.chassis['uuid'])
-        self._assertExpected(self.chassis, chassis)
-
-    @test.idempotent_id('29c9cd3f-19b5-417b-9864-99512c3b33b3')
-    def test_list_chassis(self):
-        _, body = self.client.list_chassis()
-        self.assertIn(self.chassis['uuid'],
-                      [i['uuid'] for i in body['chassis']])
-
-    @test.idempotent_id('5ae649ad-22d1-4fe1-bbc6-97227d199fb3')
-    def test_delete_chassis(self):
-        _, body = self.create_chassis()
-        uuid = body['uuid']
-
-        self.delete_chassis(uuid)
-        self.assertRaises(lib_exc.NotFound, self.client.show_chassis, uuid)
-
-    @test.idempotent_id('cda8a41f-6be2-4cbf-840c-994b00a89b44')
-    def test_update_chassis(self):
-        _, body = self.create_chassis()
-        uuid = body['uuid']
-
-        new_description = data_utils.rand_name('new-description')
-        _, body = (self.client.update_chassis(uuid,
-                   description=new_description))
-        _, chassis = self.client.show_chassis(uuid)
-        self.assertEqual(chassis['description'], new_description)
-
-    @test.idempotent_id('76305e22-a4e2-4ab3-855c-f4e2368b9335')
-    def test_chassis_node_list(self):
-        _, node = self.create_node(self.chassis['uuid'])
-        _, body = self.client.list_chassis_nodes(self.chassis['uuid'])
-        self.assertIn(node['uuid'], [n['uuid'] for n in body['nodes']])
diff --git a/tempest/api/baremetal/admin/test_drivers.py b/tempest/api/baremetal/admin/test_drivers.py
deleted file mode 100644
index f08d7ab..0000000
--- a/tempest/api/baremetal/admin/test_drivers.py
+++ /dev/null
@@ -1,38 +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.api.baremetal.admin import base
-from tempest import config
-from tempest import test
-
-CONF = config.CONF
-
-
-class TestDrivers(base.BaseBaremetalTest):
-    """Tests for drivers."""
-    @classmethod
-    def resource_setup(cls):
-        super(TestDrivers, cls).resource_setup()
-        cls.driver_name = CONF.baremetal.driver
-
-    @test.idempotent_id('5aed2790-7592-4655-9b16-99abcc2e6ec5')
-    def test_list_drivers(self):
-        _, drivers = self.client.list_drivers()
-        self.assertIn(self.driver_name,
-                      [d['name'] for d in drivers['drivers']])
-
-    @test.idempotent_id('fb3287a3-c4d7-44bf-ae9d-1eef906d78ce')
-    def test_show_driver(self):
-        _, driver = self.client.show_driver(self.driver_name)
-        self.assertEqual(self.driver_name, driver['name'])
diff --git a/tempest/api/baremetal/admin/test_nodes.py b/tempest/api/baremetal/admin/test_nodes.py
deleted file mode 100644
index 2c44665..0000000
--- a/tempest/api/baremetal/admin/test_nodes.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#    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 six
-
-from tempest.api.baremetal.admin import base
-from tempest.common.utils import data_utils
-from tempest.common import waiters
-from tempest.lib import exceptions as lib_exc
-from tempest import test
-
-
-class TestNodes(base.BaseBaremetalTest):
-    """Tests for baremetal nodes."""
-
-    def setUp(self):
-        super(TestNodes, self).setUp()
-
-        _, self.chassis = self.create_chassis()
-        _, self.node = self.create_node(self.chassis['uuid'])
-
-    def _assertExpected(self, expected, actual):
-        # Check if not expected keys/values exists in actual response body
-        for key, value in six.iteritems(expected):
-            if key not in ('created_at', 'updated_at'):
-                self.assertIn(key, actual)
-                self.assertEqual(value, actual[key])
-
-    def _associate_node_with_instance(self):
-        self.client.set_node_power_state(self.node['uuid'], 'power off')
-        waiters.wait_for_bm_node_status(self.client, self.node['uuid'],
-                                        'power_state', 'power off')
-        instance_uuid = data_utils.rand_uuid()
-        self.client.update_node(self.node['uuid'],
-                                instance_uuid=instance_uuid)
-        self.addCleanup(self.client.update_node,
-                        uuid=self.node['uuid'], instance_uuid=None)
-        return instance_uuid
-
-    @test.idempotent_id('4e939eb2-8a69-4e84-8652-6fffcbc9db8f')
-    def test_create_node(self):
-        params = {'cpu_arch': 'x86_64',
-                  'cpus': '12',
-                  'local_gb': '10',
-                  'memory_mb': '1024'}
-
-        _, body = self.create_node(self.chassis['uuid'], **params)
-        self._assertExpected(params, body['properties'])
-
-    @test.idempotent_id('9ade60a4-505e-4259-9ec4-71352cbbaf47')
-    def test_delete_node(self):
-        _, node = self.create_node(self.chassis['uuid'])
-
-        self.delete_node(node['uuid'])
-
-        self.assertRaises(lib_exc.NotFound, self.client.show_node,
-                          node['uuid'])
-
-    @test.idempotent_id('55451300-057c-4ecf-8255-ba42a83d3a03')
-    def test_show_node(self):
-        _, loaded_node = self.client.show_node(self.node['uuid'])
-        self._assertExpected(self.node, loaded_node)
-
-    @test.idempotent_id('4ca123c4-160d-4d8d-a3f7-15feda812263')
-    def test_list_nodes(self):
-        _, body = self.client.list_nodes()
-        self.assertIn(self.node['uuid'],
-                      [i['uuid'] for i in body['nodes']])
-
-    @test.idempotent_id('85b1f6e0-57fd-424c-aeff-c3422920556f')
-    def test_list_nodes_association(self):
-        _, body = self.client.list_nodes(associated=True)
-        self.assertNotIn(self.node['uuid'],
-                         [n['uuid'] for n in body['nodes']])
-
-        self._associate_node_with_instance()
-
-        _, body = self.client.list_nodes(associated=True)
-        self.assertIn(self.node['uuid'], [n['uuid'] for n in body['nodes']])
-
-        _, body = self.client.list_nodes(associated=False)
-        self.assertNotIn(self.node['uuid'], [n['uuid'] for n in body['nodes']])
-
-    @test.idempotent_id('18c4ebd8-f83a-4df7-9653-9fb33a329730')
-    def test_node_port_list(self):
-        _, port = self.create_port(self.node['uuid'],
-                                   data_utils.rand_mac_address())
-        _, body = self.client.list_node_ports(self.node['uuid'])
-        self.assertIn(port['uuid'],
-                      [p['uuid'] for p in body['ports']])
-
-    @test.idempotent_id('72591acb-f215-49db-8395-710d14eb86ab')
-    def test_node_port_list_no_ports(self):
-        _, node = self.create_node(self.chassis['uuid'])
-        _, body = self.client.list_node_ports(node['uuid'])
-        self.assertEmpty(body['ports'])
-
-    @test.idempotent_id('4fed270a-677a-4d19-be87-fd38ae490320')
-    def test_update_node(self):
-        props = {'cpu_arch': 'x86_64',
-                 'cpus': '12',
-                 'local_gb': '10',
-                 'memory_mb': '128'}
-
-        _, node = self.create_node(self.chassis['uuid'], **props)
-
-        new_p = {'cpu_arch': 'x86',
-                 'cpus': '1',
-                 'local_gb': '10000',
-                 'memory_mb': '12300'}
-
-        _, body = self.client.update_node(node['uuid'], properties=new_p)
-        _, node = self.client.show_node(node['uuid'])
-        self._assertExpected(new_p, node['properties'])
-
-    @test.idempotent_id('cbf1f515-5f4b-4e49-945c-86bcaccfeb1d')
-    def test_validate_driver_interface(self):
-        _, body = self.client.validate_driver_interface(self.node['uuid'])
-        core_interfaces = ['power', 'deploy']
-        for interface in core_interfaces:
-            self.assertIn(interface, body)
-
-    @test.idempotent_id('5519371c-26a2-46e9-aa1a-f74226e9d71f')
-    def test_set_node_boot_device(self):
-        self.client.set_node_boot_device(self.node['uuid'], 'pxe')
-
-    @test.idempotent_id('9ea73775-f578-40b9-bc34-efc639c4f21f')
-    def test_get_node_boot_device(self):
-        body = self.client.get_node_boot_device(self.node['uuid'])
-        self.assertIn('boot_device', body)
-        self.assertIn('persistent', body)
-        self.assertIsInstance(body['boot_device'], six.string_types)
-        self.assertIsInstance(body['persistent'], bool)
-
-    @test.idempotent_id('3622bc6f-3589-4bc2-89f3-50419c66b133')
-    def test_get_node_supported_boot_devices(self):
-        body = self.client.get_node_supported_boot_devices(self.node['uuid'])
-        self.assertIn('supported_boot_devices', body)
-        self.assertIsInstance(body['supported_boot_devices'], list)
-
-    @test.idempotent_id('f63b6288-1137-4426-8cfe-0d5b7eb87c06')
-    def test_get_console(self):
-        _, body = self.client.get_console(self.node['uuid'])
-        con_info = ['console_enabled', 'console_info']
-        for key in con_info:
-            self.assertIn(key, body)
-
-    @test.idempotent_id('80504575-9b21-4670-92d1-143b948f9437')
-    def test_set_console_mode(self):
-        self.client.set_console_mode(self.node['uuid'], True)
-
-        _, body = self.client.get_console(self.node['uuid'])
-        self.assertEqual(True, body['console_enabled'])
-
-    @test.idempotent_id('b02a4f38-5e8b-44b2-aed2-a69a36ecfd69')
-    def test_get_node_by_instance_uuid(self):
-        instance_uuid = self._associate_node_with_instance()
-        _, body = self.client.show_node_by_instance_uuid(instance_uuid)
-        self.assertEqual(len(body['nodes']), 1)
-        self.assertIn(self.node['uuid'], [n['uuid'] for n in body['nodes']])
diff --git a/tempest/api/baremetal/admin/test_nodestates.py b/tempest/api/baremetal/admin/test_nodestates.py
deleted file mode 100644
index 1ffea25..0000000
--- a/tempest/api/baremetal/admin/test_nodestates.py
+++ /dev/null
@@ -1,59 +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 oslo_utils import timeutils
-
-from tempest.api.baremetal.admin import base
-from tempest import exceptions
-from tempest import test
-
-
-class TestNodeStates(base.BaseBaremetalTest):
-    """Tests for baremetal NodeStates."""
-
-    @classmethod
-    def resource_setup(cls):
-        super(TestNodeStates, cls).resource_setup()
-        _, cls.chassis = cls.create_chassis()
-        _, cls.node = cls.create_node(cls.chassis['uuid'])
-
-    def _validate_power_state(self, node_uuid, power_state):
-        # Validate that power state is set within timeout
-        if power_state == 'rebooting':
-            power_state = 'power on'
-        start = timeutils.utcnow()
-        while timeutils.delta_seconds(
-                start, timeutils.utcnow()) < self.power_timeout:
-            _, node = self.client.show_node(node_uuid)
-            if node['power_state'] == power_state:
-                return
-        message = ('Failed to set power state within '
-                   'the required time: %s sec.' % self.power_timeout)
-        raise exceptions.TimeoutException(message)
-
-    @test.idempotent_id('cd8afa5e-3f57-4e43-8185-beb83d3c9015')
-    def test_list_nodestates(self):
-        _, nodestates = self.client.list_nodestates(self.node['uuid'])
-        for key in nodestates:
-            self.assertEqual(nodestates[key], self.node[key])
-
-    @test.idempotent_id('fc5b9320-0c98-4e5a-8848-877fe5a0322c')
-    def test_set_node_power_state(self):
-        _, node = self.create_node(self.chassis['uuid'])
-        states = ["power on", "rebooting", "power off"]
-        for state in states:
-            # Set power state
-            self.client.set_node_power_state(node['uuid'], state)
-            # Check power state after state is set
-            self._validate_power_state(node['uuid'], state)
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
deleted file mode 100644
index ce519c1..0000000
--- a/tempest/api/baremetal/admin/test_ports.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#    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 six
-
-from tempest.api.baremetal.admin import base
-from tempest.common.utils import data_utils
-from tempest.lib import exceptions as lib_exc
-from tempest import test
-
-
-class TestPorts(base.BaseBaremetalTest):
-    """Tests for ports."""
-
-    def setUp(self):
-        super(TestPorts, self).setUp()
-
-        _, self.chassis = self.create_chassis()
-        _, self.node = self.create_node(self.chassis['uuid'])
-        _, self.port = self.create_port(self.node['uuid'],
-                                        data_utils.rand_mac_address())
-
-    def _assertExpected(self, expected, actual):
-        # Check if not expected keys/values exists in actual response body
-        for key, value in six.iteritems(expected):
-            if key not in ('created_at', 'updated_at'):
-                self.assertIn(key, actual)
-                self.assertEqual(value, actual[key])
-
-    @test.idempotent_id('83975898-2e50-42ed-b5f0-e510e36a0b56')
-    def test_create_port(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-
-        _, body = self.client.show_port(port['uuid'])
-
-        self._assertExpected(port, body)
-
-    @test.idempotent_id('d1f6b249-4cf6-4fe6-9ed6-a6e84b1bf67b')
-    def test_create_port_specifying_uuid(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        uuid = data_utils.rand_uuid()
-
-        _, port = self.create_port(node_id=node_id,
-                                   address=address, uuid=uuid)
-
-        _, body = self.client.show_port(uuid)
-        self._assertExpected(port, body)
-
-    @test.idempotent_id('4a02c4b0-6573-42a4-a513-2e36ad485b62')
-    def test_create_port_with_extra(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'str': 'value', 'int': 123, 'float': 0.123,
-                 'bool': True, 'list': [1, 2, 3], 'dict': {'foo': 'bar'}}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-
-        _, body = self.client.show_port(port['uuid'])
-        self._assertExpected(port, body)
-
-    @test.idempotent_id('1bf257a9-aea3-494e-89c0-63f657ab4fdd')
-    def test_delete_port(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        _, port = self.create_port(node_id=node_id, address=address)
-
-        self.delete_port(port['uuid'])
-
-        self.assertRaises(lib_exc.NotFound, self.client.show_port,
-                          port['uuid'])
-
-    @test.idempotent_id('9fa77ab5-ce59-4f05-baac-148904ba1597')
-    def test_show_port(self):
-        _, port = self.client.show_port(self.port['uuid'])
-        self._assertExpected(self.port, port)
-
-    @test.idempotent_id('7c1114ff-fc3f-47bb-bc2f-68f61620ba8b')
-    def test_show_port_by_address(self):
-        _, port = self.client.show_port_by_address(self.port['address'])
-        self._assertExpected(self.port, port['ports'][0])
-
-    @test.idempotent_id('bd773405-aea5-465d-b576-0ab1780069e5')
-    def test_show_port_with_links(self):
-        _, port = self.client.show_port(self.port['uuid'])
-        self.assertIn('links', port.keys())
-        self.assertEqual(2, len(port['links']))
-        self.assertIn(port['uuid'], port['links'][0]['href'])
-
-    @test.idempotent_id('b5e91854-5cd7-4a8e-bb35-3e0a1314606d')
-    def test_list_ports(self):
-        _, body = self.client.list_ports()
-        self.assertIn(self.port['uuid'],
-                      [i['uuid'] for i in body['ports']])
-        # Verify self links.
-        for port in body['ports']:
-            self.validate_self_link('ports', port['uuid'],
-                                    port['links'][0]['href'])
-
-    @test.idempotent_id('324a910e-2f80-4258-9087-062b5ae06240')
-    def test_list_with_limit(self):
-        _, body = self.client.list_ports(limit=3)
-
-        next_marker = body['ports'][-1]['uuid']
-        self.assertIn(next_marker, body['next'])
-
-    @test.idempotent_id('8a94b50f-9895-4a63-a574-7ecff86e5875')
-    def test_list_ports_details(self):
-        node_id = self.node['uuid']
-
-        uuids = [
-            self.create_port(node_id=node_id,
-                             address=data_utils.rand_mac_address())
-            [1]['uuid'] for i in range(0, 5)]
-
-        _, body = self.client.list_ports_detail()
-
-        ports_dict = dict((port['uuid'], port) for port in body['ports']
-                          if port['uuid'] in uuids)
-
-        for uuid in uuids:
-            self.assertIn(uuid, ports_dict)
-            port = ports_dict[uuid]
-            self.assertIn('extra', port)
-            self.assertIn('node_uuid', port)
-            # never expose the node_id
-            self.assertNotIn('node_id', port)
-            # Verify self link.
-            self.validate_self_link('ports', port['uuid'],
-                                    port['links'][0]['href'])
-
-    @test.idempotent_id('8a03f688-7d75-4ecd-8cbc-e06b8f346738')
-    def test_list_ports_details_with_address(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        self.create_port(node_id=node_id, address=address)
-        for i in range(0, 5):
-            self.create_port(node_id=node_id,
-                             address=data_utils.rand_mac_address())
-
-        _, body = self.client.list_ports_detail(address=address)
-        self.assertEqual(1, len(body['ports']))
-        self.assertEqual(address, body['ports'][0]['address'])
-
-    @test.idempotent_id('9c26298b-1bcb-47b7-9b9e-8bdd6e3c4aba')
-    def test_update_port_replace(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-
-        new_address = data_utils.rand_mac_address()
-        new_extra = {'key1': 'new-value1', 'key2': 'new-value2',
-                     'key3': 'new-value3'}
-
-        patch = [{'path': '/address',
-                  'op': 'replace',
-                  'value': new_address},
-                 {'path': '/extra/key1',
-                  'op': 'replace',
-                  'value': new_extra['key1']},
-                 {'path': '/extra/key2',
-                  'op': 'replace',
-                  'value': new_extra['key2']},
-                 {'path': '/extra/key3',
-                  'op': 'replace',
-                  'value': new_extra['key3']}]
-
-        self.client.update_port(port['uuid'], patch)
-
-        _, body = self.client.show_port(port['uuid'])
-        self.assertEqual(new_address, body['address'])
-        self.assertEqual(new_extra, body['extra'])
-
-    @test.idempotent_id('d7e7fece-6ed9-460a-9ebe-9267217e8580')
-    def test_update_port_remove(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-
-        # Removing one item from the collection
-        self.client.update_port(port['uuid'],
-                                [{'path': '/extra/key2',
-                                 'op': 'remove'}])
-        extra.pop('key2')
-        _, body = self.client.show_port(port['uuid'])
-        self.assertEqual(extra, body['extra'])
-
-        # Removing the collection
-        self.client.update_port(port['uuid'], [{'path': '/extra',
-                                               'op': 'remove'}])
-        _, body = self.client.show_port(port['uuid'])
-        self.assertEqual({}, body['extra'])
-
-        # Assert nothing else was changed
-        self.assertEqual(node_id, body['node_uuid'])
-        self.assertEqual(address, body['address'])
-
-    @test.idempotent_id('241288b3-e98a-400f-a4d7-d1f716146361')
-    def test_update_port_add(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-
-        extra = {'key1': 'value1', 'key2': 'value2'}
-
-        patch = [{'path': '/extra/key1',
-                  'op': 'add',
-                  'value': extra['key1']},
-                 {'path': '/extra/key2',
-                  'op': 'add',
-                  'value': extra['key2']}]
-
-        self.client.update_port(port['uuid'], patch)
-
-        _, body = self.client.show_port(port['uuid'])
-        self.assertEqual(extra, body['extra'])
-
-    @test.idempotent_id('5309e897-0799-4649-a982-0179b04c3876')
-    def test_update_port_mixed_ops(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key1': 'value1', 'key2': 'value2'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-
-        new_address = data_utils.rand_mac_address()
-        new_extra = {'key1': 0.123, 'key3': {'cat': 'meow'}}
-
-        patch = [{'path': '/address',
-                  'op': 'replace',
-                  'value': new_address},
-                 {'path': '/extra/key1',
-                  'op': 'replace',
-                  'value': new_extra['key1']},
-                 {'path': '/extra/key2',
-                  'op': 'remove'},
-                 {'path': '/extra/key3',
-                  'op': 'add',
-                  'value': new_extra['key3']}]
-
-        self.client.update_port(port['uuid'], patch)
-
-        _, body = self.client.show_port(port['uuid'])
-        self.assertEqual(new_address, body['address'])
-        self.assertEqual(new_extra, body['extra'])
diff --git a/tempest/api/baremetal/admin/test_ports_negative.py b/tempest/api/baremetal/admin/test_ports_negative.py
deleted file mode 100644
index 5e3a33f..0000000
--- a/tempest/api/baremetal/admin/test_ports_negative.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#    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.baremetal.admin import base
-from tempest.common.utils import data_utils
-from tempest.lib import exceptions as lib_exc
-from tempest import test
-
-
-class TestPortsNegative(base.BaseBaremetalTest):
-    """Negative tests for ports."""
-
-    def setUp(self):
-        super(TestPortsNegative, self).setUp()
-
-        _, self.chassis = self.create_chassis()
-        _, self.node = self.create_node(self.chassis['uuid'])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('0a6ee1f7-d0d9-4069-8778-37f3aa07303a')
-    def test_create_port_malformed_mac(self):
-        node_id = self.node['uuid']
-        address = 'malformed:mac'
-
-        self.assertRaises(lib_exc.BadRequest,
-                          self.create_port, node_id=node_id, address=address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('30277ee8-0c60-4f1d-b125-0e51c2f43369')
-    def test_create_port_nonexsistent_node_id(self):
-        node_id = data_utils.rand_uuid()
-        address = data_utils.rand_mac_address()
-        self.assertRaises(lib_exc.BadRequest, self.create_port,
-                          node_id=node_id, address=address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('029190f6-43e1-40a3-b64a-65173ba653a3')
-    def test_show_port_malformed_uuid(self):
-        self.assertRaises(lib_exc.BadRequest, self.client.show_port,
-                          'malformed:uuid')
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('0d00e13d-e2e0-45b1-bcbc-55a6d90ca793')
-    def test_show_port_nonexistent_uuid(self):
-        self.assertRaises(lib_exc.NotFound, self.client.show_port,
-                          data_utils.rand_uuid())
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('4ad85266-31e9-4942-99ac-751897dc9e23')
-    def test_show_port_by_mac_not_allowed(self):
-        self.assertRaises(lib_exc.BadRequest, self.client.show_port,
-                          data_utils.rand_mac_address())
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('89a34380-3c61-4c32-955c-2cd9ce94da21')
-    def test_create_port_duplicated_port_uuid(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        uuid = data_utils.rand_uuid()
-
-        self.create_port(node_id=node_id, address=address, uuid=uuid)
-        self.assertRaises(lib_exc.Conflict, self.create_port, node_id=node_id,
-                          address=address, uuid=uuid)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('65e84917-733c-40ae-ae4b-96a4adff931c')
-    def test_create_port_no_mandatory_field_node_id(self):
-        address = data_utils.rand_mac_address()
-
-        self.assertRaises(lib_exc.BadRequest, self.create_port, node_id=None,
-                          address=address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('bcea3476-7033-4183-acfe-e56a30809b46')
-    def test_create_port_no_mandatory_field_mac(self):
-        node_id = self.node['uuid']
-
-        self.assertRaises(lib_exc.BadRequest, self.create_port,
-                          node_id=node_id, address=None)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('2b51cd18-fb95-458b-9780-e6257787b649')
-    def test_create_port_malformed_port_uuid(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        uuid = 'malformed:uuid'
-
-        self.assertRaises(lib_exc.BadRequest, self.create_port,
-                          node_id=node_id, address=address, uuid=uuid)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('583a6856-6a30-4ac4-889f-14e2adff8105')
-    def test_create_port_malformed_node_id(self):
-        address = data_utils.rand_mac_address()
-        self.assertRaises(lib_exc.BadRequest, self.create_port,
-                          node_id='malformed:nodeid', address=address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('e27f8b2e-42c6-4a43-a3cd-accff716bc5c')
-    def test_create_port_duplicated_mac(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        self.create_port(node_id=node_id, address=address)
-        self.assertRaises(lib_exc.Conflict,
-                          self.create_port, node_id=node_id,
-                          address=address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('8907082d-ac5e-4be3-b05f-d072ede82020')
-    def test_update_port_by_mac_not_allowed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
-
-        self.create_port(node_id=node_id, address=address, extra=extra)
-
-        patch = [{'path': '/extra/key',
-                  'op': 'replace',
-                  'value': 'new-value'}]
-
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.update_port, address,
-                          patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('df1ac70c-db9f-41d9-90f1-78cd6b905718')
-    def test_update_port_nonexistent(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-        port_id = port['uuid']
-
-        _, body = self.client.delete_port(port_id)
-
-        patch = [{'path': '/extra/key',
-                  'op': 'replace',
-                  'value': 'new-value'}]
-        self.assertRaises(lib_exc.NotFound,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('c701e315-aa52-41ea-817c-65c5ca8ca2a8')
-    def test_update_port_malformed_port_uuid(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        self.create_port(node_id=node_id, address=address)
-
-        new_address = data_utils.rand_mac_address()
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port,
-                          uuid='malformed:uuid',
-                          patch=[{'path': '/address', 'op': 'replace',
-                                  'value': new_address}])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('f8f15803-34d6-45dc-b06f-e5e04bf1b38b')
-    def test_update_port_add_nonexistent_property(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/nonexistent', ' op': 'add',
-                            'value': 'value'}])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('898ec904-38b1-4fcb-9584-1187d4263a2a')
-    def test_update_port_replace_node_id_with_malformed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        patch = [{'path': '/node_uuid',
-                  'op': 'replace',
-                  'value': 'malformed:node_uuid'}]
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('2949f30f-5f59-43fa-a6d9-4eac578afab4')
-    def test_update_port_replace_mac_with_duplicated(self):
-        node_id = self.node['uuid']
-        address1 = data_utils.rand_mac_address()
-        address2 = data_utils.rand_mac_address()
-
-        _, port1 = self.create_port(node_id=node_id, address=address1)
-
-        _, port2 = self.create_port(node_id=node_id, address=address2)
-        port_id = port2['uuid']
-
-        patch = [{'path': '/address',
-                  'op': 'replace',
-                  'value': address1}]
-        self.assertRaises(lib_exc.Conflict,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('97f6e048-6e4f-4eba-a09d-fbbc78b77a77')
-    def test_update_port_replace_node_id_with_nonexistent(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        patch = [{'path': '/node_uuid',
-                  'op': 'replace',
-                  'value': data_utils.rand_uuid()}]
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('375022c5-9e9e-4b11-9ca4-656729c0c9b2')
-    def test_update_port_replace_mac_with_malformed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        patch = [{'path': '/address',
-                  'op': 'replace',
-                  'value': 'malformed:mac'}]
-
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('5722b853-03fc-4854-8308-2036a1b67d85')
-    def test_update_port_replace_nonexistent_property(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        patch = [{'path': '/nonexistent', ' op': 'replace', 'value': 'value'}]
-
-        self.assertRaises(lib_exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('ae2696ca-930a-4a7f-918f-30ae97c60f56')
-    def test_update_port_remove_mandatory_field_mac(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/address', 'op': 'remove'}])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('5392c1f0-2071-4697-9064-ec2d63019018')
-    def test_update_port_remove_mandatory_field_port_uuid(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/uuid', 'op': 'remove'}])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('06b50d82-802a-47ef-b079-0a3311cf85a2')
-    def test_update_port_remove_nonexistent_property(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/nonexistent', 'op': 'remove'}])
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('03d42391-2145-4a6c-95bf-63fe55eb64fd')
-    def test_delete_port_by_mac_not_allowed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        self.create_port(node_id=node_id, address=address)
-        self.assertRaises(lib_exc.BadRequest, self.client.delete_port, address)
-
-    @test.attr(type=['negative'])
-    @test.idempotent_id('0629e002-818e-4763-b25b-ae5e07b1cb23')
-    def test_update_port_mixed_ops_integrity(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key1': 'value1', 'key2': 'value2'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-        port_id = port['uuid']
-
-        new_address = data_utils.rand_mac_address()
-        new_extra = {'key1': 'new-value1', 'key3': 'new-value3'}
-
-        patch = [{'path': '/address',
-                  'op': 'replace',
-                  'value': new_address},
-                 {'path': '/extra/key1',
-                  'op': 'replace',
-                  'value': new_extra['key1']},
-                 {'path': '/extra/key2',
-                  'op': 'remove'},
-                 {'path': '/extra/key3',
-                  'op': 'add',
-                  'value': new_extra['key3']},
-                 {'path': '/nonexistent',
-                  'op': 'replace',
-                  'value': 'value'}]
-
-        self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
-                          patch)
-
-        # patch should not be applied
-        _, body = self.client.show_port(port_id)
-        self.assertEqual(address, body['address'])
-        self.assertEqual(extra, body['extra'])
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 61359f1..1c37cad 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -12,14 +12,10 @@
 #    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.utils import data_utils
 from tempest import test
 
-LOG = log.getLogger(__name__)
-
 
 class AgentsAdminTestJSON(base.BaseV2ComputeAdminTest):
     """Tests Agents API"""
@@ -90,7 +86,8 @@
         body = self.client.create_agent(**self.params_agent)['agent']
         self.addCleanup(self.client.delete_agent, body['agent_id'])
         agents = self.client.list_agents()['agents']
-        self.assertTrue(len(agents) > 0, 'Cannot get any agents.(%s)' % agents)
+        self.assertGreater(len(agents), 0,
+                           'Cannot get any agents.(%s)' % agents)
         self.assertIn(body['agent_id'], map(lambda x: x['agent_id'], agents))
 
     @test.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
@@ -108,7 +105,8 @@
         agent_id_xen = agent_xen['agent_id']
         agents = (self.client.list_agents(hypervisor=agent_xen['hypervisor'])
                   ['agents'])
-        self.assertTrue(len(agents) > 0, 'Cannot get any agents.(%s)' % agents)
+        self.assertGreater(len(agents), 0,
+                           'Cannot get any agents.(%s)' % agents)
         self.assertIn(agent_id_xen, map(lambda x: x['agent_id'], agents))
         self.assertNotIn(body['agent_id'], map(lambda x: x['agent_id'],
                                                agents))
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 667d30b..1233a2b 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -18,9 +18,12 @@
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest import test
 
+CONF = config.CONF
+
 
 class AggregatesAdminTestJSON(base.BaseV2ComputeAdminTest):
     """Tests Aggregates API that require admin privileges"""
@@ -39,14 +42,22 @@
         cls.host = None
         hypers = cls.os_adm.hypervisor_client.list_hypervisors(
             detail=True)['hypervisors']
+
+        if CONF.compute.hypervisor_type:
+            hypers = [hyper for hyper in hypers
+                      if (hyper['hypervisor_type'] ==
+                          CONF.compute.hypervisor_type)]
+
         hosts_available = [hyper['service']['host'] for hyper in hypers
                            if (hyper['state'] == 'up' and
                                hyper['status'] == 'enabled')]
         if hosts_available:
             cls.host = hosts_available[0]
         else:
-            raise testtools.TestCase.failureException(
-                "no available compute node found")
+            msg = "no available compute node found"
+            if CONF.compute.hypervisor_type:
+                msg += " for hypervisor_type %s" % CONF.compute.hypervisor_type
+            raise testtools.TestCase.failureException(msg)
 
     @test.idempotent_id('0d148aa3-d54c-4317-aa8d-42040a475e20')
     def test_aggregate_create_delete(self):
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 3c4e313..85aa301 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -40,6 +40,13 @@
                  for host in hosts_all if host['service'] == 'compute'])
         cls.host = hosts[0]
 
+    def _create_test_aggregate(self):
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+        aggregate = (self.client.create_aggregate(name=aggregate_name)
+                     ['aggregate'])
+        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        return aggregate
+
     @test.attr(type=['negative'])
     @test.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
     def test_aggregate_create_as_user(self):
@@ -70,24 +77,16 @@
     @test.idempotent_id('9c23a291-b0b1-487b-b464-132e061151b3')
     def test_aggregate_create_with_existent_aggregate_name(self):
         # creating an aggregate with existent aggregate name is forbidden
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = self.client.create_aggregate(name=aggregate_name)
-        self.addCleanup(self.client.delete_aggregate,
-                        aggregate['aggregate']['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Conflict,
                           self.client.create_aggregate,
-                          name=aggregate_name)
+                          name=aggregate['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.delete_aggregate,
                           aggregate['id'])
@@ -103,11 +102,7 @@
     @test.idempotent_id('557cad12-34c9-4ff4-95f0-22f0dfbaf7dc')
     def test_aggregate_get_details_as_user(self):
         # Regular user is not allowed to get aggregate details.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.show_aggregate,
                           aggregate['id'])
@@ -136,12 +131,7 @@
             non_exist_host = data_utils.rand_name('nonexist_host')
             if non_exist_host not in hosts:
                 break
-
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.NotFound, self.client.add_host,
                           aggregate['id'], host=non_exist_host)
 
@@ -149,11 +139,7 @@
     @test.idempotent_id('7324c334-bd13-4c93-8521-5877322c3d51')
     def test_aggregate_add_host_as_user(self):
         # Regular user is not allowed to add a host to an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.add_host,
                           aggregate['id'], host=self.host)
@@ -162,10 +148,7 @@
     @test.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
     def test_aggregate_add_existent_host(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
 
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
@@ -179,10 +162,8 @@
     def test_aggregate_remove_host_as_user(self):
         # Regular user is not allowed to remove a host from an aggregate.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
+
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
                         host=self.host)
@@ -194,11 +175,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
     def test_aggregate_remove_nonexistent_host(self):
-        non_exist_host = data_utils.rand_name('nonexist_host')
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
 
         self.assertRaises(lib_exc.NotFound, self.client.remove_host,
-                          aggregate['id'], host=non_exist_host)
+                          aggregate['id'], host='nonexist_host')
diff --git a/tempest/api/compute/admin/test_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
index ee8ed14..8e481fd 100644
--- a/tempest/api/compute/admin/test_auto_allocate_network.py
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -19,8 +19,8 @@
 from tempest.common import credentials_factory as credentials
 from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions as lib_excs
 from tempest import test
 
 CONF = config.CONF
@@ -66,7 +66,6 @@
     @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
@@ -83,14 +82,14 @@
         nets = cls.networks_client.list_networks(
             **search_opts).get('networks', [])
         if nets:
-            raise exceptions.TempestException(
+            raise lib_excs.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(
+            raise lib_excs.TempestException(
                 'Found shared networks: %s' % nets)
 
     @classmethod
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index 5befa53..3470602 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -29,10 +29,10 @@
     def test_get_availability_zone_list(self):
         # List of availability zone
         availability_zone = self.client.list_availability_zones()
-        self.assertTrue(len(availability_zone['availabilityZoneInfo']) > 0)
+        self.assertGreater(len(availability_zone['availabilityZoneInfo']), 0)
 
     @test.idempotent_id('ef726c58-530f-44c2-968c-c7bed22d5b8c')
     def test_get_availability_zone_list_detail(self):
         # List of availability zones and available services
         availability_zone = self.client.list_availability_zones(detail=True)
-        self.assertTrue(len(availability_zone['availabilityZoneInfo']) > 0)
+        self.assertGreater(len(availability_zone['availabilityZoneInfo']), 0)
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
index b764483..722d9a6 100644
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -25,7 +25,7 @@
     @classmethod
     def resource_setup(cls):
         super(BaremetalNodesAdminTestJSON, cls).resource_setup()
-        if not CONF.service_available.ironic:
+        if not getattr(CONF.service_available, 'ironic', False):
             skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
             raise cls.skipException(skip_msg)
         cls.client = cls.os_adm.baremetal_nodes_client
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index b0ab9be..7eb4bbf 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -102,11 +102,10 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
     def test_flavor_unset_nonexistent_key(self):
-        nonexistent_key = data_utils.rand_name('flavor_key')
         self.assertRaises(lib_exc.NotFound,
                           self.client.unset_flavor_extra_spec,
                           self.flavor['id'],
-                          nonexistent_key)
+                          'nonexistent_key')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index e207aed..a4695b0 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -17,6 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 from tempest import test
 
@@ -54,12 +55,6 @@
                 raise exceptions.InvalidConfiguration(msg)
         return
 
-    def _delete_floating_ips_bulk(self, ip_range):
-        try:
-            self.client.delete_floating_ips_bulk(ip_range)
-        except Exception:
-            pass
-
     @test.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
     @test.services('network')
     def test_create_list_delete_floating_ips_bulk(self):
@@ -73,7 +68,8 @@
                                                      pool,
                                                      interface)
                 ['floating_ips_bulk_create'])
-        self.addCleanup(self._delete_floating_ips_bulk, self.ip_range)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_floating_ips_bulk, self.ip_range)
         self.assertEqual(self.ip_range, body['ip_range'])
         ips_list = self.client.list_floating_ips_bulk()['floating_ip_info']
         self.assertNotEqual(0, len(ips_list))
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index a9e9644..3797b29 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -28,7 +28,7 @@
     @test.idempotent_id('9bfaf98d-e2cb-44b0-a07e-2558b2821e4f')
     def test_list_hosts(self):
         hosts = self.client.list_hosts()['hosts']
-        self.assertTrue(len(hosts) >= 2, str(hosts))
+        self.assertGreaterEqual(len(hosts), 2, str(hosts))
 
     @test.idempotent_id('5dc06f5b-d887-47a2-bb2a-67762ef3c6de')
     def test_list_hosts_with_zone(self):
@@ -36,7 +36,7 @@
         hosts = self.client.list_hosts()['hosts']
         host = hosts[0]
         hosts = self.client.list_hosts(zone=host['zone'])['hosts']
-        self.assertTrue(len(hosts) >= 1)
+        self.assertGreaterEqual(len(hosts), 1)
         self.assertIn(host, hosts)
 
     @test.idempotent_id('9af3c171-fbf4-4150-a624-22109733c2a6')
@@ -58,12 +58,12 @@
         hosts = self.client.list_hosts()['hosts']
 
         hosts = [host for host in hosts if host['service'] == 'compute']
-        self.assertTrue(len(hosts) >= 1)
+        self.assertGreaterEqual(len(hosts), 1)
 
         for host in hosts:
             hostname = host['host_name']
             resources = self.client.show_host(hostname)['host']
-            self.assertTrue(len(resources) >= 1)
+            self.assertGreaterEqual(len(resources), 1)
             host_resource = resources[0]['resource']
             self.assertIsNotNone(host_resource)
             self.assertIsNotNone(host_resource['cpu'])
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 8366945..3821b22 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -13,7 +13,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -27,11 +26,13 @@
         cls.client = cls.os_adm.hosts_client
         cls.non_admin_client = cls.os.hosts_client
 
-    def _get_host_name(self):
-        hosts = self.client.list_hosts()['hosts']
-        self.assertTrue(len(hosts) >= 1)
-        hostname = hosts[0]['host_name']
-        return hostname
+    @classmethod
+    def resource_setup(cls):
+        super(HostsAdminNegativeTestJSON, cls).resource_setup()
+        hosts = cls.client.list_hosts()['hosts']
+        if not hosts:
+            raise lib_exc.NotFound("no host found")
+        cls.hostname = hosts[0]['host_name']
 
     @test.attr(type=['negative'])
     @test.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
@@ -42,27 +43,22 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
     def test_show_host_detail_with_nonexistent_hostname(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
         self.assertRaises(lib_exc.NotFound,
-                          self.client.show_host, nonexitent_hostname)
+                          self.client.show_host, 'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
     def test_show_host_detail_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
     def test_update_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.update_host,
-                          hostname,
+                          self.hostname,
                           status='enable',
                           maintenance_mode='enable')
 
@@ -70,11 +66,9 @@
     @test.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname,
+                          self.hostname,
                           status='invalid',
                           maintenance_mode='enable')
 
@@ -82,11 +76,9 @@
     @test.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
     def test_update_host_with_invalid_maintenance_mode(self):
         # 'maintenance_mode' can only be 'enable' or 'disable'
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname,
+                          self.hostname,
                           status='enable',
                           maintenance_mode='invalid')
 
@@ -94,73 +86,57 @@
     @test.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
     def test_update_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.update_host,
-                          nonexitent_hostname,
+                          'nonexistent_hostname',
                           status='enable',
                           maintenance_mode='enable')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
     def test_startup_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.startup_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
     def test_startup_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.startup_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
     def test_shutdown_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.shutdown_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
     def test_shutdown_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.shutdown_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
     def test_reboot_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.reboot_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
     def test_reboot_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.reboot_host,
-                          hostname)
+                          self.hostname)
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 113ec40..1f043dc 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -31,7 +31,7 @@
         return hypers
 
     def assertHypervisors(self, hypers):
-        self.assertTrue(len(hypers) > 0, "No hypervisors found: %s" % hypers)
+        self.assertGreater(len(hypers), 0, "No hypervisors found: %s" % hypers)
 
     @test.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
     def test_get_hypervisor_list(self):
@@ -52,7 +52,7 @@
         self.assertHypervisors(hypers)
 
         details = self.client.show_hypervisor(hypers[0]['id'])['hypervisor']
-        self.assertTrue(len(details) > 0)
+        self.assertGreater(len(details), 0)
         self.assertEqual(details['hypervisor_hostname'],
                          hypers[0]['hypervisor_hostname'])
 
@@ -65,14 +65,14 @@
         hostname = hypers[0]['hypervisor_hostname']
         hypervisors = (self.client.list_servers_on_hypervisor(hostname)
                        ['hypervisors'])
-        self.assertTrue(len(hypervisors) > 0)
+        self.assertGreater(len(hypervisors), 0)
 
     @test.idempotent_id('797e4f28-b6e0-454d-a548-80cc77c00816')
     def test_get_hypervisor_stats(self):
         # Verify the stats of the all hypervisor
         stats = (self.client.show_hypervisor_statistics()
                  ['hypervisor_statistics'])
-        self.assertTrue(len(stats) > 0)
+        self.assertGreater(len(stats), 0)
 
     @test.idempotent_id('91a50d7d-1c2b-4f24-b55a-a1fe20efca70')
     def test_get_hypervisor_uptime(self):
@@ -87,7 +87,7 @@
         ironic_only = True
         hypers_without_ironic = []
         for hyper in hypers:
-            details = (self.client.show_hypervisor(hypers[0]['id'])
+            details = (self.client.show_hypervisor(hyper['id'])
                        ['hypervisor'])
             if details['hypervisor_type'] != 'ironic':
                 hypers_without_ironic.append(hyper)
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index 9c6df7f..0f35e14 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -47,7 +47,7 @@
     @test.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
     def test_show_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
-        self.assertTrue(len(hypers) > 0)
+        self.assertGreater(len(hypers), 0)
 
         self.assertRaises(
             lib_exc.Forbidden,
@@ -58,7 +58,7 @@
     @test.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
     def test_show_servers_with_non_admin_user(self):
         hypers = self._list_hypervisors()
-        self.assertTrue(len(hypers) > 0)
+        self.assertGreater(len(hypers), 0)
 
         self.assertRaises(
             lib_exc.Forbidden,
@@ -96,7 +96,7 @@
     @test.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
     def test_get_hypervisor_uptime_with_non_admin_user(self):
         hypers = self._list_hypervisors()
-        self.assertTrue(len(hypers) > 0)
+        self.assertGreater(len(hypers), 0)
 
         self.assertRaises(
             lib_exc.Forbidden,
@@ -122,18 +122,16 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
     def test_search_nonexistent_hypervisor(self):
-        nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
-
         self.assertRaises(
             lib_exc.NotFound,
             self.client.search_hypervisor,
-            nonexistent_hypervisor_name)
+            'nonexistent_hypervisor_name')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
     def test_search_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
-        self.assertTrue(len(hypers) > 0)
+        self.assertGreater(len(hypers), 0)
 
         self.assertRaises(
             lib_exc.Forbidden,
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 4f075eb..2dd2e89 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -31,7 +31,6 @@
         super(MigrationsAdminTest, cls).setup_clients()
         cls.client = cls.os_adm.migrations_client
         cls.flavors_admin_client = cls.os_adm.flavors_client
-        cls.admin_hosts_client = cls.os_adm.hosts_client
         cls.admin_servers_client = cls.os_adm.servers_client
 
     @test.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
@@ -47,12 +46,7 @@
         server = self.create_test_server(wait_until="ACTIVE")
         server_id = server['id']
 
-        self.servers_client.resize_server(server_id, self.flavor_ref_alt)
-        waiters.wait_for_server_status(self.servers_client,
-                                       server_id, 'VERIFY_RESIZE')
-        self.servers_client.confirm_resize_server(server_id)
-        waiters.wait_for_server_status(self.servers_client,
-                                       server_id, 'ACTIVE')
+        self.resize_server(server_id, self.flavor_ref_alt)
 
         body = self.client.list_migrations()['migrations']
 
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index e5c8790..8504840 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -42,8 +42,12 @@
                              "{0} networks with label {1}".format(
                                  len(configured_network),
                                  CONF.compute.fixed_network_name))
+        elif CONF.network.public_network_id:
+            configured_network = [x for x in networks if x['id'] ==
+                                  CONF.network.public_network_id]
         else:
-            configured_network = networks
+            raise self.skipException(
+                "Environment has no known-for-sure existing network.")
         configured_network = configured_network[0]
         network = (self.client.show_network(configured_network['id'])
                    ['network'])
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 7d97ce2..ce0adb4 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -74,7 +74,8 @@
                          'ram': 10240, 'floating_ips': 20, 'fixed_ips': 10,
                          'key_pairs': 200, 'injected_file_path_bytes': 512,
                          'instances': 20, 'security_group_rules': 20,
-                         'cores': 2, 'security_groups': 20}
+                         'cores': 2, 'security_groups': 20,
+                         'server_groups': 20, 'server_group_members': 20}
         # Update limits for all quota resources
         quota_set = self.adm_client.update_quota_set(
             self.demo_tenant_id,
@@ -82,13 +83,6 @@
             **new_quota_set)['quota_set']
 
         default_quota_set.pop('id')
-        # NOTE(PhilDay) The following is safe as we're not updating these
-        # two quota values yet.  Once the Nova change to add these is merged
-        # and the client updated to support them this can be removed
-        if 'server_groups' in default_quota_set:
-            default_quota_set.pop('server_groups')
-        if 'server_group_members' in default_quota_set:
-            default_quota_set.pop('server_group_members')
         self.addCleanup(self.adm_client.update_quota_set,
                         self.demo_tenant_id, **default_quota_set)
         for quota in new_quota_set:
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index d6aba5b..015e14d 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -40,6 +40,17 @@
         # tenant most of them should be skipped if we can't do that
         cls.demo_tenant_id = cls.client.tenant_id
 
+    def _update_quota(self, quota_item, quota_value):
+        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
+                     ['quota_set'])
+        default_quota_value = quota_set[quota_item]
+
+        self.adm_client.update_quota_set(self.demo_tenant_id,
+                                         force=True,
+                                         **{quota_item: quota_value})
+        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
+                        **{quota_item: default_quota_value})
+
     @test.attr(type=['negative'])
     @test.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
     def test_update_quota_normal_user(self):
@@ -54,17 +65,7 @@
     @test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
     def test_create_server_when_cpu_quota_is_full(self):
         # Disallow server creation when tenant's vcpu quota is full
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_vcpu_quota = quota_set['cores']
-        vcpu_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         cores=vcpu_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        cores=default_vcpu_quota)
+        self._update_quota('cores', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -72,17 +73,7 @@
     @test.idempotent_id('6fdd7012-584d-4327-a61c-49122e0d5864')
     def test_create_server_when_memory_quota_is_full(self):
         # Disallow server creation when tenant's memory quota is full
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_mem_quota = quota_set['ram']
-        mem_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         ram=mem_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        ram=default_mem_quota)
+        self._update_quota('ram', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -90,16 +81,7 @@
     @test.idempotent_id('7c6be468-0274-449a-81c3-ac1c32ee0161')
     def test_create_server_when_instances_quota_is_full(self):
         # Once instances quota limit is reached, disallow server creation
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_instances_quota = quota_set['instances']
-        instances_quota = 0  # Set quota to zero to disallow server creation
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         instances=instances_quota)
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        instances=default_instances_quota)
+        self._update_quota('instances', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -109,22 +91,10 @@
     @test.services('network')
     def test_security_groups_exceed_limit(self):
         # Negative test: Creation Security Groups over limit should FAIL
-
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_sg_quota = quota_set['security_groups']
-
         # Set the quota to number of used security groups
         sg_quota = self.limits_client.show_limits()['limits']['absolute'][
             'totalSecurityGroupsUsed']
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         security_groups=sg_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set,
-                        self.demo_tenant_id,
-                        security_groups=default_sg_quota)
+        self._update_quota('security_groups', sg_quota)
 
         # Check we cannot create anymore
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
@@ -141,19 +111,7 @@
     def test_security_groups_rules_exceed_limit(self):
         # Negative test: Creation of Security Group Rules should FAIL
         # when we reach limit maxSecurityGroupRules
-
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_sg_rules_quota = quota_set['security_group_rules']
-        sg_rules_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         security_group_rules=sg_rules_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set,
-                        self.demo_tenant_id,
-                        security_group_rules=default_sg_rules_quota)
+        self._update_quota('security_group_rules', 0)
 
         s_name = data_utils.rand_name('securitygroup')
         s_description = data_utils.rand_name('description')
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index efa55d5..a8a8b83 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -29,7 +29,6 @@
         super(ServersAdminTestJSON, cls).setup_clients()
         cls.client = cls.os_adm.servers_client
         cls.non_admin_client = cls.servers_client
-        cls.flavors_client = cls.os_adm.flavors_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
new file mode 100644
index 0000000..b9dac6f
--- /dev/null
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -0,0 +1,61 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute 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 VolumesAdminNegativeTest(base.BaseV2ComputeAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesAdminNegativeTest, cls).skip_checks()
+        if not CONF.service_available.cinder:
+            skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(VolumesAdminNegativeTest, cls).setup_clients()
+        cls.servers_admin_client = cls.os_adm.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(VolumesAdminNegativeTest, cls).resource_setup()
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+    @test.idempotent_id('309b5ecd-0585-4a7e-a36f-d2b2bf55259d')
+    def test_update_attached_volume_with_nonexistent_volume_in_uri(self):
+        volume = self.create_volume()
+        nonexistent_volume = data_utils.rand_uuid()
+        self.assertRaises(lib_exc.NotFound,
+                          self.servers_admin_client.update_attached_volume,
+                          self.server['id'], nonexistent_volume,
+                          volumeId=volume['id'])
+
+    @test.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
+    def test_update_attached_volume_with_nonexistent_volume_in_body(self):
+        volume = self.create_volume()
+        self.attach_volume(self.server, volume)
+
+        nonexistent_volume = data_utils.rand_uuid()
+        self.assertRaises(lib_exc.BadRequest,
+                          self.servers_admin_client.update_attached_volume,
+                          self.server['id'], volume['id'],
+                          volumeId=nonexistent_volume)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index b738e82..d7e01f0 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -75,7 +75,6 @@
             cls.os.compute_security_group_rules_client)
         cls.security_groups_client = cls.os.compute_security_groups_client
         cls.quotas_client = cls.os.quotas_client
-        cls.quota_classes_client = cls.os.quota_classes_client
         cls.compute_networks_client = cls.os.compute_networks_client
         cls.limits_client = cls.os.limits_client
         cls.volumes_extensions_client = cls.os.volumes_extensions_client
@@ -319,12 +318,7 @@
     def rebuild_server(cls, server_id, validatable=False, **kwargs):
         # Destroy an existing server and creates a new one
         if server_id:
-            try:
-                cls.servers_client.delete_server(server_id)
-                waiters.wait_for_server_termination(cls.servers_client,
-                                                    server_id)
-            except Exception:
-                LOG.exception('Failed to delete server %s' % server_id)
+            cls.delete_server(server_id)
 
         cls.password = data_utils.rand_password()
         server = cls.create_test_server(
@@ -345,6 +339,15 @@
             LOG.exception('Failed to delete server %s' % server_id)
 
     @classmethod
+    def resize_server(cls, server_id, new_flavor_id, **kwargs):
+        """resize and confirm_resize an server, waits for it to be ACTIVE."""
+        cls.servers_client.resize_server(server_id, new_flavor_id, **kwargs)
+        waiters.wait_for_server_status(cls.servers_client, server_id,
+                                       'VERIFY_RESIZE')
+        cls.servers_client.confirm_resize_server(server_id)
+        waiters.wait_for_server_status(cls.servers_client, server_id, 'ACTIVE')
+
+    @classmethod
     def delete_volume(cls, volume_id):
         """Deletes the given volume and waits for it to be gone."""
         cls._delete_volume(cls.volumes_extensions_client, volume_id)
@@ -365,7 +368,7 @@
                     return address['addr']
             raise exceptions.ServerUnreachable(server_id=server['id'])
         else:
-            raise exceptions.InvalidConfiguration()
+            raise lib_exc.InvalidConfiguration()
 
     def setUp(self):
         super(BaseV2ComputeTest, self).setUp()
@@ -373,14 +376,21 @@
             self.request_microversion))
 
     @classmethod
-    def create_volume(cls):
+    def create_volume(cls, image_ref=None, **kwargs):
         """Create a volume and wait for it to become 'available'.
 
+        :param image_ref: Specify an image id to create a bootable volume.
+        :**kwargs: other parameters to create volume.
         :returns: The available volume.
         """
-        vol_name = data_utils.rand_name(cls.__name__ + '-volume')
-        volume = cls.volumes_client.create_volume(
-            size=CONF.volume.volume_size, display_name=vol_name)['volume']
+        if 'size' not in kwargs:
+            kwargs['size'] = CONF.volume.volume_size
+        if 'display_name' not in kwargs:
+            vol_name = data_utils.rand_name(cls.__name__ + '-volume')
+            kwargs['display_name'] = vol_name
+        if image_ref is not None:
+            kwargs['imageRef'] = image_ref
+        volume = cls.volumes_client.create_volume(**kwargs)['volume']
         cls.volumes.append(volume)
         waiters.wait_for_volume_status(cls.volumes_client,
                                        volume['id'], 'available')
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index fdf1e93..dcb2d2c 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.api.compute.floating_ips import base
-from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
@@ -111,9 +110,7 @@
         # positive test:Association of an already associated floating IP
         # to specific server should change the association of the Floating IP
         # Create server so as to use for Multiple association
-        body = self.create_test_server()
-        waiters.wait_for_server_status(self.servers_client,
-                                       body['id'], 'ACTIVE')
+        body = self.create_test_server(wait_until='ACTIVE')
         self.new_server_id = body['id']
         self.addCleanup(self.servers_client.delete_server, self.new_server_id)
 
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index f71f046..31cf39c 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -23,7 +23,6 @@
 
 
 class FloatingIPsNegativeTestJSON(base.BaseFloatingIPsTest):
-    server_id = None
 
     @classmethod
     def setup_clients(cls):
@@ -38,15 +37,14 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
         # Generating a nonexistent floatingIP id
-        cls.floating_ip_ids = []
         body = cls.client.list_floating_ips()['floating_ips']
-        for i in range(len(body)):
-            cls.floating_ip_ids.append(body[i]['id'])
+        floating_ip_ids = [floating_ip['id'] for floating_ip in body]
         while True:
-            cls.non_exist_id = data_utils.rand_int_id(start=999)
             if CONF.service_available.neutron:
                 cls.non_exist_id = data_utils.rand_uuid()
-            if cls.non_exist_id not in cls.floating_ip_ids:
+            else:
+                cls.non_exist_id = data_utils.rand_int_id(start=999)
+            if cls.non_exist_id not in floating_ip_ids:
                 break
 
     @test.attr(type=['negative'])
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 999233d..26d4efe 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -20,7 +20,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
+from tempest.lib import exceptions
 from tempest import test
 
 CONF = config.CONF
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 9cb9e03..489bfbc 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -19,11 +19,11 @@
 from tempest import test
 
 
-class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
+class ImagesMetadataNegativeTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
     def setup_clients(cls):
-        super(ImagesMetadataTestJSON, cls).setup_clients()
+        super(ImagesMetadataNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
     @test.attr(type=['negative'])
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 3754637..a06f4a7 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -38,15 +38,12 @@
     def setup_clients(cls):
         super(ImagesTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
-        cls.servers_client = cls.servers_client
 
     @test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
     def test_delete_saving_image(self):
-        snapshot_name = data_utils.rand_name('test-snap')
         server = self.create_test_server(wait_until='ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
         image = self.create_image_from_server(server['id'],
-                                              name=snapshot_name,
                                               wait_until='SAVING')
         self.client.delete_image(image['id'])
         msg = ('The image with ID {image_id} failed to be deleted'
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index e91944f..549262e 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -39,7 +39,6 @@
     def setup_clients(cls):
         super(ImagesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
-        cls.servers_client = cls.servers_client
 
     @test.attr(type=['negative'])
     @test.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
@@ -47,7 +46,7 @@
         # An image should not be created if the server instance is removed
         server = self.create_test_server(wait_until='ACTIVE')
 
-        # Delete server before trying to create server
+        # Delete server before trying to create image
         self.servers_client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.servers_client, server['id'])
         # Create a new image after server is deleted
@@ -64,8 +63,6 @@
         # Create a new image with invalid server id
         name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
-        resp = {}
-        resp['status'] = None
         self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
                           '!@$^&*()', name=name, meta=meta)
 
@@ -99,7 +96,7 @@
     def test_delete_non_existent_image(self):
         # Return an error while trying to delete a non-existent image
 
-        non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
+        non_existent_image_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
@@ -113,9 +110,9 @@
     @test.idempotent_id('924540c3-f1f1-444c-8f58-718958b6724e')
     def test_delete_image_non_hex_string_id(self):
         # Return an error while trying to delete an image with non hex id
-        image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
+        invalid_image_id = data_utils.rand_uuid()[:-1] + "j"
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
-                          image_id)
+                          invalid_image_id)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('68e2c175-bd26-4407-ac0f-4ea9ce2139ea')
@@ -125,7 +122,8 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('b340030d-82cd-4066-a314-c72fb7c59277')
-    def test_delete_image_id_is_over_35_character_limit(self):
+    def test_delete_image_with_id_over_character_limit(self):
         # Return an error while trying to delete image with id over limit
+        invalid_image_id = data_utils.rand_uuid() + "1"
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
-                          '11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
+                          invalid_image_id)
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 6c417f1..0b4a2a8 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
@@ -23,7 +21,6 @@
 from tempest import test
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class ImagesOneServerTestJSON(base.BaseV2ComputeTest):
@@ -45,35 +42,18 @@
         super(ImagesOneServerTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @classmethod
-    def resource_setup(cls):
-        super(ImagesOneServerTestJSON, cls).resource_setup()
-        server = cls.create_test_server(wait_until='ACTIVE')
-        cls.server_id = server['id']
-
     def _get_default_flavor_disk_size(self, flavor_id):
         flavor = self.flavors_client.show_flavor(flavor_id)['flavor']
         return flavor['disk']
 
-    @classmethod
-    def _rebuild_server_when_fails(cls, server_id):
-        try:
-            waiters.wait_for_server_status(cls.servers_client,
-                                           server_id, 'ACTIVE')
-        except Exception:
-            LOG.exception('server %s timed out to become ACTIVE. rebuilding'
-                          % server_id)
-            # Rebuild server if cannot reach the ACTIVE state
-            # Usually it means the server had a serious accident
-            cls.server_id = cls.rebuild_server(server_id)
-
     @test.idempotent_id('3731d080-d4c5-4872-b41a-64d0d0021314')
     def test_create_delete_image(self):
+        server_id = self.create_test_server(wait_until='ACTIVE')['id']
 
         # Create a new image
         name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
-        body = self.client.create_image(self.server_id, name=name,
+        body = self.client.create_image(server_id, name=name,
                                         metadata=meta)
         image_id = data_utils.parse_image_id(body.response['location'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
@@ -98,10 +78,11 @@
         # Verify the image was deleted correctly
         self.client.delete_image(image_id)
         self.client.wait_for_resource_deletion(image_id)
-        self.addCleanup(self._rebuild_server_when_fails, self.server_id)
 
     @test.idempotent_id('3b7c6fe4-dfe7-477c-9243-b06359db51e6')
     def test_create_image_specify_multibyte_character_image_name(self):
+        server_id = self.create_test_server(wait_until='ACTIVE')['id']
+
         # prefix character is:
         # http://www.fileformat.info/info/unicode/char/1F4A9/index.htm
 
@@ -109,7 +90,6 @@
         # #1370954 in glance which will 500 if mysql is used as the
         # backend and it attempts to store a 4 byte utf-8 character
         utf8_name = data_utils.rand_name('\xe2\x82\xa1')
-        body = self.client.create_image(self.server_id, name=utf8_name)
+        body = self.client.create_image(server_id, name=utf8_name)
         image_id = data_utils.parse_image_id(body.response['location'])
         self.addCleanup(self.client.delete_image, image_id)
-        self.addCleanup(self._rebuild_server_when_fails, self.server_id)
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index d9b80e1..1c9b3f1 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -69,11 +69,6 @@
             raise cls.skipException(skip_msg)
 
     @classmethod
-    def setup_credentials(cls):
-        cls.prepare_instance_network()
-        super(ImagesOneServerNegativeTestJSON, cls).setup_credentials()
-
-    @classmethod
     def setup_clients(cls):
         super(ImagesOneServerNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
@@ -98,9 +93,9 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('3d24d11f-5366-4536-bd28-cff32b748eca')
     def test_create_image_specify_metadata_over_limits(self):
-        # Return an error when creating image with meta data over 256 chars
+        # Return an error when creating image with meta data over 255 chars
         snapshot_name = data_utils.rand_name('test-snap')
-        meta = {'a' * 260: 'b' * 260}
+        meta = {'a' * 256: 'b' * 256}
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           self.server_id, name=snapshot_name, metadata=meta)
 
@@ -123,10 +118,10 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
-    def test_create_image_specify_name_over_256_chars(self):
-        # Return an error if snapshot name over 256 characters is passed
+    def test_create_image_specify_name_over_character_limit(self):
+        # Return an error if snapshot name over 255 characters is passed
 
-        snapshot_name = data_utils.rand_name('a' * 260)
+        snapshot_name = ('a' * 256)
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           self.server_id, name=snapshot_name)
 
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index be6f615..562a508 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -57,8 +57,8 @@
         self.assertEqual(key_name, k_name,
                          "The created keypair name is not equal "
                          "to the requested name")
-        self.assertTrue(private_key is not None,
-                        "Field private_key is empty or not found.")
+        self.assertIsNotNone(private_key,
+                             "Field private_key is empty or not found.")
 
     @test.idempotent_id('a4233d5d-52d8-47cc-9a25-e1864527e3df')
     def test_get_keypair_detail(self):
@@ -72,8 +72,8 @@
                          "The created keypair name is not equal "
                          "to requested name")
         public_key = keypair_detail['public_key']
-        self.assertTrue(public_key is not None,
-                        "Field public_key is empty or not found.")
+        self.assertIsNotNone(public_key,
+                             "Field public_key is empty or not found.")
 
     @test.idempotent_id('39c90c6a-304a-49dd-95ec-2366129def05')
     def test_keypair_create_with_pub_key(self):
@@ -89,7 +89,7 @@
                    "XcPojYN56tI0OlrGqojbediJYD0rUsJu4weZpbn8vilb3JuDY+jws"
                    "snSA8wzBx3A/8y9Pp1B nova@ubuntu")
         keypair = self._create_keypair(k_name, pub_key)
-        self.assertFalse('private_key' in keypair,
+        self.assertNotIn('private_key', keypair,
                          "Field private_key is not empty!")
         key_name = keypair['name']
         self.assertEqual(key_name, k_name,
diff --git a/tempest/api/compute/limits/test_absolute_limits.py b/tempest/api/compute/limits/test_absolute_limits.py
index 69811f4..6cc722c 100644
--- a/tempest/api/compute/limits/test_absolute_limits.py
+++ b/tempest/api/compute/limits/test_absolute_limits.py
@@ -35,9 +35,10 @@
                              'maxTotalFloatingIps', 'maxSecurityGroups',
                              'maxSecurityGroupRules', 'maxTotalInstances',
                              'maxTotalKeypairs', 'maxTotalRAMSize',
+                             'maxServerGroups', 'maxServerGroupMembers',
                              'totalCoresUsed', 'totalFloatingIpsUsed',
                              'totalSecurityGroupsUsed', 'totalInstancesUsed',
-                             'totalRAMUsed']
+                             'totalRAMUsed', 'totalServerGroupsUsed']
         # check whether all expected elements exist
         missing_elements =\
             [ele for ele in expected_elements if ele not in absolute_limits]
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 4f53663..32b3ea3 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -35,7 +35,6 @@
     @classmethod
     def setup_clients(cls):
         super(SecurityGroupRulesNegativeTestJSON, cls).setup_clients()
-        cls.client = cls.security_groups_client
         cls.rules_client = cls.security_group_rules_client
 
     @test.attr(type=['negative'])
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 755336f..4184afa 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -94,10 +94,8 @@
 
         # Create server and add the security group created
         # above to the server we just created
-        server = self.create_test_server()
+        server = self.create_test_server(wait_until='ACTIVE')
         server_id = server['id']
-        waiters.wait_for_server_status(self.servers_client, server_id,
-                                       'ACTIVE')
         self.servers_client.add_security_group(server_id, name=sg['name'])
 
         # Check that we are not able to delete the security
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index b936b23..a21ce94 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -20,7 +20,6 @@
 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
@@ -47,34 +46,9 @@
     @classmethod
     def setup_clients(cls):
         super(AttachInterfacesTestJSON, cls).setup_clients()
-        cls.networks_client = cls.os.networks_client
         cls.subnets_client = cls.os.subnets_client
         cls.ports_client = cls.os.ports_client
 
-    def wait_for_interface_status(self, server, port_id, status):
-        """Waits for an interface to reach a given status."""
-        body = (self.interfaces_client.show_interface(server, port_id)
-                ['interfaceAttachment'])
-        interface_status = body['port_state']
-        start = int(time.time())
-
-        while(interface_status != status):
-            time.sleep(self.build_interval)
-            body = (self.interfaces_client.show_interface(server, port_id)
-                    ['interfaceAttachment'])
-            interface_status = body['port_state']
-
-            timed_out = int(time.time()) - start >= self.build_timeout
-
-            if interface_status != status and timed_out:
-                message = ('Interface %s failed to reach %s status '
-                           '(current %s) within the required time (%s s).' %
-                           (port_id, status, interface_status,
-                            self.build_timeout))
-                raise exceptions.TimeoutException(message)
-
-        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.
@@ -99,7 +73,7 @@
                 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)
+                raise lib_exc.TimeoutException(message)
 
         return port
 
@@ -119,16 +93,16 @@
         server = self.create_test_server(wait_until='ACTIVE')
         ifs = (self.interfaces_client.list_interfaces(server['id'])
                ['interfaceAttachments'])
-        body = self.wait_for_interface_status(
-            server['id'], ifs[0]['port_id'], 'ACTIVE')
+        body = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
         ifs[0]['port_state'] = body['port_state']
         return server, ifs
 
     def _test_create_interface(self, server):
         iface = (self.interfaces_client.create_interface(server['id'])
                  ['interfaceAttachment'])
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface)
         return iface
 
@@ -136,8 +110,8 @@
         network_id = ifs[0]['net_id']
         iface = self.interfaces_client.create_interface(
             server['id'], net_id=network_id)['interfaceAttachment']
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, network_id=network_id)
         return iface
 
@@ -148,8 +122,8 @@
         self.addCleanup(self.ports_client.delete_port, port_id)
         iface = self.interfaces_client.create_interface(
             server['id'], port_id=port_id)['interfaceAttachment']
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, port_id=port_id)
         return iface
 
@@ -167,8 +141,8 @@
             server['id'], net_id=network_id,
             fixed_ips=fixed_ips)['interfaceAttachment']
         self.addCleanup(self.ports_client.delete_port, iface['port_id'])
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, fixed_ip=ip_list[0])
         return iface
 
@@ -197,7 +171,7 @@
             if len(ifs) == len(_ifs) and timed_out:
                 message = ('Failed to delete interface within '
                            'the required time: %s sec.' % self.build_timeout)
-                raise exceptions.TimeoutException(message)
+                raise lib_exc.TimeoutException(message)
 
         self.assertNotIn(iface['port_id'], [i['port_id'] for i in _ifs])
         return _ifs
@@ -215,7 +189,7 @@
     def test_create_list_show_delete_interfaces(self):
         server, ifs = self._create_server_get_interfaces()
         interface_count = len(ifs)
-        self.assertTrue(interface_count > 0)
+        self.assertGreater(interface_count, 0)
         self._check_interface(ifs[0])
 
         try:
@@ -253,7 +227,7 @@
         # Add and Remove the fixed IP to server.
         server, ifs = self._create_server_get_interfaces()
         interface_count = len(ifs)
-        self.assertTrue(interface_count > 0)
+        self.assertGreater(interface_count, 0)
         self._check_interface(ifs[0])
         network_id = ifs[0]['net_id']
         self.servers_client.add_fixed_ip(server['id'], networkId=network_id)
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 78f0db4..d2e31ad 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -19,7 +19,6 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
-from tempest.common import waiters
 from tempest import config
 from tempest import test
 
@@ -142,16 +141,12 @@
         self.assertEqual(self.name.lower(), hostname, msg)
 
     @test.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
+    @testtools.skipUnless(
+        test.is_scheduler_filter_enabled("ServerGroupAffinityFilter"),
+        'ServerGroupAffinityFilter is not available.')
     def test_create_server_with_scheduler_hint_group(self):
         # Create a server with the scheduler hint "group".
-        name = data_utils.rand_name('server_group')
-        policies = ['affinity']
-        body = self.server_groups_client.create_server_group(
-            name=name, policies=policies)['server_group']
-        group_id = body['id']
-        self.addCleanup(self.server_groups_client.delete_server_group,
-                        group_id)
-
+        group_id = self.create_test_server_group()['id']
         hints = {'group': group_id}
         server = self.create_test_server(scheduler_hints=hints,
                                          wait_until='ACTIVE')
@@ -182,12 +177,7 @@
         # when trying to delete the subnet. The tear down in the base class
         # will try to delete the server and get a 404 but it's ignored so
         # we're OK.
-        def cleanup_server():
-            self.client.delete_server(server_multi_nics['id'])
-            waiters.wait_for_server_termination(self.client,
-                                                server_multi_nics['id'])
-
-        self.addCleanup(cleanup_server)
+        self.addCleanup(self.delete_server, server_multi_nics['id'])
 
         addresses = (self.client.list_addresses(server_multi_nics['id'])
                      ['addresses'])
@@ -219,13 +209,7 @@
 
         server_multi_nics = self.create_test_server(
             networks=networks, wait_until='ACTIVE')
-
-        def cleanup_server():
-            self.client.delete_server(server_multi_nics['id'])
-            waiters.wait_for_server_termination(self.client,
-                                                server_multi_nics['id'])
-
-        self.addCleanup(cleanup_server)
+        self.addCleanup(self.delete_server, server_multi_nics['id'])
 
         addresses = (self.client.list_addresses(server_multi_nics['id'])
                      ['addresses'])
@@ -268,37 +252,25 @@
         flavor_base = self.flavors_client.show_flavor(
             self.flavor_ref)['flavor']
 
-        def create_flavor_with_extra_specs():
-            flavor_with_eph_disk_name = data_utils.rand_name('eph_flavor')
+        def create_flavor_with_ephemeral(ephem_disk):
             flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000)
 
             ram = flavor_base['ram']
             vcpus = flavor_base['vcpus']
             disk = flavor_base['disk']
 
-            # Create a flavor with extra specs
-            flavor = (self.flavor_client.
-                      create_flavor(name=flavor_with_eph_disk_name,
-                                    ram=ram, vcpus=vcpus, disk=disk,
-                                    id=flavor_with_eph_disk_id,
-                                    ephemeral=1))['flavor']
-            self.addCleanup(flavor_clean_up, flavor['id'])
-
-            return flavor['id']
-
-        def create_flavor_without_extra_specs():
-            flavor_no_eph_disk_name = data_utils.rand_name('no_eph_flavor')
-            flavor_no_eph_disk_id = data_utils.rand_int_id(start=1000)
-
-            ram = flavor_base['ram']
-            vcpus = flavor_base['vcpus']
-            disk = flavor_base['disk']
-
-            # Create a flavor without extra specs
-            flavor = (self.flavor_client.
-                      create_flavor(name=flavor_no_eph_disk_name,
-                                    ram=ram, vcpus=vcpus, disk=disk,
-                                    id=flavor_no_eph_disk_id))['flavor']
+            if ephem_disk > 0:
+                # Create a flavor with ephemeral disk
+                flavor_name = data_utils.rand_name('eph_flavor')
+                flavor = self.flavor_client.create_flavor(
+                    name=flavor_name, ram=ram, vcpus=vcpus, disk=disk,
+                    id=flavor_with_eph_disk_id, ephemeral=ephem_disk)['flavor']
+            else:
+                # Create a flavor without ephemeral disk
+                flavor_name = data_utils.rand_name('no_eph_flavor')
+                flavor = self.flavor_client.create_flavor(
+                    name=flavor_name, ram=ram, vcpus=vcpus, disk=disk,
+                    id=flavor_with_eph_disk_id)['flavor']
             self.addCleanup(flavor_clean_up, flavor['id'])
 
             return flavor['id']
@@ -307,8 +279,8 @@
             self.flavor_client.delete_flavor(flavor_id)
             self.flavor_client.wait_for_resource_deletion(flavor_id)
 
-        flavor_with_eph_disk_id = create_flavor_with_extra_specs()
-        flavor_no_eph_disk_id = create_flavor_without_extra_specs()
+        flavor_with_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=1)
+        flavor_no_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=0)
 
         admin_pass = self.image_ssh_password
 
@@ -318,7 +290,7 @@
             adminPass=admin_pass,
             flavor=flavor_no_eph_disk_id)
 
-        # Get partition number of server without extra specs.
+        # Get partition number of server without ephemeral disk.
         server_no_eph_disk = self.client.show_server(
             server_no_eph_disk['id'])['server']
         linux_client = remote_client.RemoteClient(
@@ -328,7 +300,7 @@
             self.validation_resources['keypair']['private_key'],
             server=server_no_eph_disk,
             servers_client=self.client)
-        partition_num = len(linux_client.get_partitions().split('\n'))
+        disks_num = len(linux_client.get_disks().split('\n'))
 
         # Explicit server deletion necessary for Juno compatibility
         self.client.delete_server(server_no_eph_disk['id'])
@@ -348,8 +320,8 @@
             self.validation_resources['keypair']['private_key'],
             server=server_with_eph_disk,
             servers_client=self.client)
-        partition_num_emph = len(linux_client.get_partitions().split('\n'))
-        self.assertEqual(partition_num + 1, partition_num_emph)
+        disks_num_eph = len(linux_client.get_disks().split('\n'))
+        self.assertEqual(disks_num + 1, disks_num_eph)
 
 
 class ServersTestManualDisk(ServersTestJSON):
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
new file mode 100644
index 0000000..b2d5ae7
--- /dev/null
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -0,0 +1,266 @@
+# Copyright (C) 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.
+
+import json
+
+from oslo_log import log as logging
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest.common.utils.linux import remote_client
+from tempest.common import waiters
+from tempest import config
+from tempest.lib import exceptions
+from tempest import test
+
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+class DeviceTaggingTest(base.BaseV2ComputeTest):
+
+    min_microversion = '2.32'
+    max_microversion = 'latest'
+
+    @classmethod
+    def skip_checks(cls):
+        super(DeviceTaggingTest, cls).skip_checks()
+        if not CONF.service_available.neutron:
+            raise cls.skipException('Neutron is required')
+        if not CONF.validation.run_validation:
+            raise cls.skipException('Validation must be enabled')
+        if (not CONF.compute_feature_enabled.config_drive
+            and not CONF.compute_feature_enabled.metadata_service):
+            raise cls.skipException('One of metadata or config drive must be '
+                                    'enabled')
+
+    @classmethod
+    def setup_clients(cls):
+        super(DeviceTaggingTest, cls).setup_clients()
+        cls.networks_client = cls.os.networks_client
+        cls.ports_client = cls.os.ports_client
+        cls.subnets_client = cls.os.subnets_client
+        cls.interfaces_client = cls.os.interfaces_client
+
+    @classmethod
+    def setup_credentials(cls):
+        cls.set_network_resources(network=True, subnet=True, router=True,
+                                  dhcp=True)
+        super(DeviceTaggingTest, cls).setup_credentials()
+
+    @classmethod
+    def resource_setup(cls):
+        cls.set_validation_resources()
+        super(DeviceTaggingTest, cls).resource_setup()
+
+    def verify_device_metadata(self, md_json):
+        md_dict = json.loads(md_json)
+        for d in md_dict['devices']:
+            if d['type'] == 'nic':
+                if d['mac'] == self.port1['mac_address']:
+                    self.assertEqual(d['tags'], ['port-1'])
+                if d['mac'] == self.port2['mac_address']:
+                    self.assertEqual(d['tags'], ['port-2'])
+                if d['mac'] == self.net_2_100_mac:
+                    self.assertEqual(d['tags'], ['net-2-100'])
+                if d['mac'] == self.net_2_200_mac:
+                    self.assertEqual(d['tags'], ['net-2-200'])
+
+        found_devices = [d['tags'][0] for d in md_dict['devices']]
+        self.assertItemsEqual(found_devices, ['port-1', 'port-2', 'net-1',
+                                              'net-2-100', 'net-2-200',
+                                              'boot', 'other'])
+
+    @test.idempotent_id('a2e65a6c-66f1-4442-aaa8-498c31778d96')
+    @test.services('network', 'volume', 'image')
+    def test_device_tagging(self):
+        # Create volumes
+        # The create_volume methods waits for the volumes to be available and
+        # the base class will clean them up on tearDown.
+        boot_volume = self.create_volume(CONF.compute.image_ref)
+        other_volume = self.create_volume()
+        untagged_volume = self.create_volume()
+
+        # Create networks
+        net1 = self.networks_client.create_network(
+            name=data_utils.rand_name('device-tagging-net1'))['network']
+        self.addCleanup(self.networks_client.delete_network, net1['id'])
+
+        net2 = self.networks_client.create_network(
+            name=data_utils.rand_name('device-tagging-net2'))['network']
+        self.addCleanup(self.networks_client.delete_network, net2['id'])
+
+        # Create subnets
+        subnet1 = self.subnets_client.create_subnet(
+            network_id=net1['id'],
+            cidr='10.1.1.0/24',
+            ip_version=4)['subnet']
+        self.addCleanup(self.subnets_client.delete_subnet, subnet1['id'])
+
+        subnet2 = self.subnets_client.create_subnet(
+            network_id=net2['id'],
+            cidr='10.2.2.0/24',
+            ip_version=4)['subnet']
+        self.addCleanup(self.subnets_client.delete_subnet, subnet2['id'])
+
+        # Create ports
+        self.port1 = self.ports_client.create_port(
+            network_id=net1['id'],
+            fixed_ips=[{'subnet_id': subnet1['id']}])['port']
+        self.addCleanup(self.ports_client.delete_port, self.port1['id'])
+
+        self.port2 = self.ports_client.create_port(
+            network_id=net1['id'],
+            fixed_ips=[{'subnet_id': subnet1['id']}])['port']
+        self.addCleanup(self.ports_client.delete_port, self.port2['id'])
+
+        # Create server
+        admin_pass = data_utils.rand_password()
+        config_drive_enabled = CONF.compute_feature_enabled.config_drive
+
+        server = self.create_test_server(
+            validatable=True,
+            config_drive=config_drive_enabled,
+            adminPass=admin_pass,
+            name=data_utils.rand_name('device-tagging-server'),
+            networks=[
+                # Validation network for ssh
+                {
+                    'uuid': self.get_tenant_network()['id']
+                },
+                # Different tags for different ports
+                {
+                    'port': self.port1['id'],
+                    'tag': 'port-1'
+                },
+                {
+                    'port': self.port2['id'],
+                    'tag': 'port-2'
+                },
+                # Two nics on same net, one tagged one not
+                {
+                    'uuid': net1['id'],
+                    'tag': 'net-1'
+                },
+                {
+                    'uuid': net1['id']
+                },
+                # Two nics on same net, different IP
+                {
+                    'uuid': net2['id'],
+                    'fixed_ip': '10.2.2.100',
+                    'tag': 'net-2-100'
+                },
+                {
+                    'uuid': net2['id'],
+                    'fixed_ip': '10.2.2.200',
+                    'tag': 'net-2-200'
+                }
+            ],
+            block_device_mapping_v2=[
+                # Boot volume
+                {
+                    'uuid': boot_volume['id'],
+                    'source_type': 'volume',
+                    'destination_type': 'volume',
+                    'boot_index': 0,
+                    'tag': 'boot'
+                },
+                # Other volume
+                {
+                    'uuid': other_volume['id'],
+                    'source_type': 'volume',
+                    'destination_type': 'volume',
+                    'boot_index': 1,
+                    'tag': 'other'
+                },
+                # Untagged volume
+                {
+                    'uuid': untagged_volume['id'],
+                    'source_type': 'volume',
+                    'destination_type': 'volume',
+                    'boot_index': 2
+                }
+            ])
+
+        self.addCleanup(waiters.wait_for_server_termination,
+                        self.servers_client, server['id'])
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+
+        self.ssh_client = remote_client.RemoteClient(
+            self.get_server_ip(server),
+            CONF.validation.image_ssh_user,
+            admin_pass,
+            self.validation_resources['keypair']['private_key'],
+            server=server,
+            servers_client=self.servers_client)
+
+        # Find the MAC addresses of our fixed IPs
+        self.net_2_100_mac = None
+        self.net_2_200_mac = None
+        ifaces = self.interfaces_client.list_interfaces(server['id'])
+        for iface in ifaces['interfaceAttachments']:
+            if 'fixed_ips' in iface:
+                for ip in iface['fixed_ips']:
+                    if ip['ip_address'] == '10.2.2.100':
+                        self.net_2_100_mac = iface['mac_addr']
+                    if ip['ip_address'] == '10.2.2.200':
+                        self.net_2_200_mac = iface['mac_addr']
+        # Make sure we have the MACs we need, there's no reason for some to be
+        # missing
+        self.assertTrue(self.net_2_100_mac)
+        self.assertTrue(self.net_2_200_mac)
+
+        # Verify metadata from metadata service
+        if CONF.compute_feature_enabled.metadata_service:
+            md_url = 'http://169.254.169.254/openstack/latest/meta_data.json'
+            LOG.info('Attempting to verify tagged devices in server %s via '
+                     'the metadata service: %s', server['id'], md_url)
+
+            def get_and_verify_metadata():
+                try:
+                    self.ssh_client.exec_command('curl -V')
+                except exceptions.SSHExecCommandFailed:
+                    if not CONF.compute_feature_enabled.config_drive:
+                        raise self.skipException('curl not found in guest '
+                                                 'and config drive is '
+                                                 'disabled')
+                    LOG.warning('curl was not found in the guest, device '
+                                'tagging metadata was not checked in the '
+                                'metadata API')
+                    return True
+                cmd = 'curl %s' % md_url
+                md_json = self.ssh_client.exec_command(cmd)
+                self.verify_device_metadata(md_json)
+                return True
+
+            if not test.call_until_true(get_and_verify_metadata,
+                                        CONF.compute.build_timeout,
+                                        CONF.compute.build_interval):
+                raise exceptions.TimeoutException('Timeout while verifying '
+                                                  'metadata on server.')
+
+        # Verify metadata on config drive
+        if CONF.compute_feature_enabled.config_drive:
+            cmd_blkid = 'blkid -t LABEL=config-2 -o device'
+            LOG.info('Attempting to verify tagged devices in server %s via '
+                     'the config drive.', server['id'])
+            dev_name = self.ssh_client.exec_command(cmd_blkid)
+            dev_name = dev_name.rstrip()
+            self.ssh_client.exec_command('sudo mount %s /mnt' % dev_name)
+            cmd_md = 'sudo cat /mnt/openstack/latest/meta_data.json'
+            md_json = self.ssh_client.exec_command(cmd_md)
+            self.verify_device_metadata(md_json)
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index aba0240..ff8ea6e 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -94,12 +94,8 @@
         self._update_server_with_disk_config(server['id'],
                                              disk_config='MANUAL')
         # Resize with auto option
-        self.client.resize_server(server['id'], self.flavor_ref_alt,
-                                  disk_config='AUTO')
-        waiters.wait_for_server_status(self.client, server['id'],
-                                       'VERIFY_RESIZE')
-        self.client.confirm_resize_server(server['id'])
-        waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
+        self.resize_server(server['id'], self.flavor_ref_alt,
+                           disk_config='AUTO')
 
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
@@ -114,12 +110,8 @@
         self._update_server_with_disk_config(server['id'],
                                              disk_config='AUTO')
         # Resize with manual option
-        self.client.resize_server(server['id'], self.flavor_ref_alt,
-                                  disk_config='MANUAL')
-        waiters.wait_for_server_status(self.client, server['id'],
-                                       'VERIFY_RESIZE')
-        self.client.confirm_resize_server(server['id'])
-        waiters.wait_for_server_status(self.client, server['id'], 'ACTIVE')
+        self.resize_server(server['id'], self.flavor_ref_alt,
+                           disk_config='MANUAL')
 
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index a229df8..e50881f 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -28,17 +28,17 @@
     @classmethod
     def resource_setup(cls):
         super(InstanceActionsTestJSON, cls).resource_setup()
-        server = cls.create_test_server(wait_until='ACTIVE')
-        cls.request_id = server.response['x-compute-request-id']
-        cls.server_id = server['id']
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
+        cls.request_id = cls.server.response['x-compute-request-id']
 
     @test.idempotent_id('77ca5cc5-9990-45e0-ab98-1de8fead201a')
     def test_list_instance_actions(self):
         # List actions of the provided server
-        self.client.reboot_server(self.server_id, type='HARD')
-        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
+        self.client.reboot_server(self.server['id'], type='HARD')
+        waiters.wait_for_server_status(self.client,
+                                       self.server['id'], 'ACTIVE')
 
-        body = (self.client.list_instance_actions(self.server_id)
+        body = (self.client.list_instance_actions(self.server['id'])
                 ['instanceActions'])
         self.assertEqual(len(body), 2, str(body))
         self.assertEqual(sorted([i['action'] for i in body]),
@@ -48,8 +48,8 @@
     def test_get_instance_action(self):
         # Get the action details of the provided server
         body = self.client.show_instance_action(
-            self.server_id, self.request_id)['instanceAction']
-        self.assertEqual(self.server_id, body['instance_uuid'])
+            self.server['id'], self.request_id)['instanceAction']
+        self.assertEqual(self.server['id'], body['instance_uuid'])
         self.assertEqual('create', body['action'])
 
 
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 54ec6aa..33fed08 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -29,8 +29,7 @@
     @classmethod
     def resource_setup(cls):
         super(InstanceActionsNegativeTestJSON, cls).resource_setup()
-        server = cls.create_test_server(wait_until='ACTIVE')
-        cls.server_id = server['id']
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('67e1fce6-7ec2-45c6-92d4-0a8f1a632910')
@@ -46,4 +45,4 @@
     def test_get_instance_action_invalid_request(self):
         # Get the action details of the provided server with invalid request
         self.assertRaises(lib_exc.NotFound, self.client.show_instance_action,
-                          self.server_id, '999')
+                          self.server['id'], '999')
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index fcd5a24..3e408d2 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -40,14 +40,9 @@
             srv = cls.create_test_server(wait_until='ACTIVE')
             cls.existing_fixtures.append(srv)
 
-        srv = cls.create_test_server()
+        srv = cls.create_test_server(wait_until='ACTIVE')
         cls.client.delete_server(srv['id'])
-        # We ignore errors on termination because the server may
-        # be put into ERROR status on a quick spawn, then delete,
-        # as the compute node expects the instance local status
-        # to be spawning, not deleted. See LP Bug#1061167
-        waiters.wait_for_server_termination(cls.client, srv['id'],
-                                            ignore_error=True)
+        waiters.wait_for_server_termination(cls.client, srv['id'])
         cls.deleted_fixtures.append(srv)
 
     @test.attr(type=['negative'])
@@ -66,8 +61,7 @@
     @test.idempotent_id('ff01387d-c7ad-47b4-ae9e-64fa214638fe')
     def test_list_servers_by_non_existing_image(self):
         # Listing servers for a non existing image returns empty list
-        non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
-        body = self.client.list_servers(image=non_existing_image)
+        body = self.client.list_servers(image='non_existing_image')
         servers = body['servers']
         self.assertEqual([], servers)
 
@@ -75,8 +69,7 @@
     @test.idempotent_id('5913660b-223b-44d4-a651-a0fbfd44ca75')
     def test_list_servers_by_non_existing_flavor(self):
         # Listing servers by non existing flavor returns empty list
-        non_existing_flavor = 1234
-        body = self.client.list_servers(flavor=non_existing_flavor)
+        body = self.client.list_servers(flavor='non_existing_flavor')
         servers = body['servers']
         self.assertEqual([], servers)
 
@@ -84,8 +77,7 @@
     @test.idempotent_id('e2c77c4a-000a-4af3-a0bd-629a328bde7c')
     def test_list_servers_by_non_existing_server_name(self):
         # Listing servers for a non existent server name returns empty list
-        non_existing_name = 'junk_server_1234'
-        body = self.client.list_servers(name=non_existing_name)
+        body = self.client.list_servers(name='non_existing_server_name')
         servers = body['servers']
         self.assertEqual([], servers)
 
@@ -93,8 +85,7 @@
     @test.idempotent_id('fcdf192d-0f74-4d89-911f-1ec002b822c4')
     def test_list_servers_status_non_existing(self):
         # Return an empty list when invalid status is specified
-        non_existing_status = 'BALONEY'
-        body = self.client.list_servers(status=non_existing_status)
+        body = self.client.list_servers(status='non_existing_status')
         servers = body['servers']
         self.assertEqual([], servers)
 
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 4dd26af..9fc30f9 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -14,26 +14,16 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest import test
 
 
 class MultipleCreateTestJSON(base.BaseV2ComputeTest):
-    _name = 'multiple-create-test'
-
-    def _create_multiple_servers(self, **kwargs):
-        # This is the right way to create_multiple servers and manage to get
-        # the created servers into the servers list to be cleaned up after all.
-        kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
-        body = self.create_test_server(**kwargs)
-
-        return body
 
     @test.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
-        body = self._create_multiple_servers(wait_until='ACTIVE',
-                                             min_count=1,
-                                             max_count=2)
+        body = self.create_test_server(wait_until='ACTIVE',
+                                       min_count=1,
+                                       max_count=2)
         # NOTE(maurosr): do status response check and also make sure that
         # reservation_id is not in the response body when the request send
         # contains return_reservation_id=False
@@ -41,8 +31,8 @@
 
     @test.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
     def test_multiple_create_with_reservation_return(self):
-        body = self._create_multiple_servers(wait_until='ACTIVE',
-                                             min_count=1,
-                                             max_count=2,
-                                             return_reservation_id=True)
+        body = self.create_test_server(wait_until='ACTIVE',
+                                       min_count=1,
+                                       max_count=2,
+                                       return_reservation_id=True)
         self.assertIn('reservation_id', body)
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index c4dbe23..d9fb4ca 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -14,48 +14,38 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 
 class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
-    _name = 'multiple-create-test'
-
-    def _create_multiple_servers(self, **kwargs):
-        # This is the right way to create_multiple servers and manage to get
-        # the created servers into the servers list to be cleaned up after all.
-        kwargs['name'] = kwargs.get('name', data_utils.rand_name(self._name))
-        body = self.create_test_server(**kwargs)
-
-        return body
 
     @test.attr(type=['negative'])
     @test.idempotent_id('daf29d8d-e928-4a01-9a8c-b129603f3fc0')
     def test_min_count_less_than_one(self):
         invalid_min_count = 0
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('999aa722-d624-4423-b813-0d1ac9884d7a')
     def test_min_count_non_integer(self):
         invalid_min_count = 2.5
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a6f9c2ab-e060-4b82-b23c-4532cb9390ff')
     def test_max_count_less_than_one(self):
         invalid_max_count = 0
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9c5698d1-d7af-4c80-b971-9d403135eea2')
     def test_max_count_non_integer(self):
         invalid_max_count = 2.5
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
@@ -63,6 +53,6 @@
     def test_max_count_less_than_min_count(self):
         min_count = 3
         max_count = 2
-        self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
+        self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=min_count,
                           max_count=max_count)
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 9077801..0a94d5e 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -13,8 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
+from oslo_log import log as logging
 from six.moves.urllib import parse as urlparse
 import testtools
 
@@ -131,8 +130,8 @@
                 server=server,
                 servers_client=self.client)
             new_boot_time = linux_client.get_boot_time()
-            self.assertTrue(new_boot_time > boot_time,
-                            '%s > %s' % (new_boot_time, boot_time))
+            self.assertGreater(new_boot_time, boot_time,
+                               '%s > %s' % (new_boot_time, boot_time))
 
     @test.attr(type='smoke')
     @test.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
@@ -458,8 +457,8 @@
 
             # NOTE: This test tries to get full length console log, and the
             # length should be bigger than the one of test_get_console_output.
-            self.assertTrue(lines > 10, "Cannot get enough console log length."
-                                        " (lines: %s)" % lines)
+            self.assertGreater(lines, 10, "Cannot get enough console log "
+                                          "length. (lines: %s)" % lines)
 
         self.wait_for(_check_full_length_console_log)
 
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 864f38f..d31b6f8 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -49,9 +49,9 @@
 
         # We do not know the exact network configuration, but an instance
         # should at least have a single public or private address
-        self.assertTrue(len(addresses) >= 1)
+        self.assertGreaterEqual(len(addresses), 1)
         for network_name, network_addresses in six.iteritems(addresses):
-            self.assertTrue(len(network_addresses) >= 1)
+            self.assertGreaterEqual(len(network_addresses), 1)
             for address in network_addresses:
                 self.assertTrue(address['addr'])
                 self.assertTrue(address['version'])
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 9c07677..847b7a1 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -23,23 +23,21 @@
     def setup_clients(cls):
         super(ServerMetadataTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
-        cls.quotas = cls.quotas_client
 
     @classmethod
     def resource_setup(cls):
         super(ServerMetadataTestJSON, cls).resource_setup()
-        server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
-        cls.server_id = server['id']
+        cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
 
     def setUp(self):
         super(ServerMetadataTestJSON, self).setUp()
         meta = {'key1': 'value1', 'key2': 'value2'}
-        self.client.set_server_metadata(self.server_id, meta)['metadata']
+        self.client.set_server_metadata(self.server['id'], meta)['metadata']
 
     @test.idempotent_id('479da087-92b3-4dcf-aeb3-fd293b2d14ce')
     def test_list_server_metadata(self):
         # All metadata key/value pairs for a server should be returned
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
 
         # Verify the expected metadata items are in the list
@@ -51,12 +49,12 @@
         # The server's metadata should be replaced with the provided values
         # Create a new set of metadata for the server
         req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
-        self.client.set_server_metadata(self.server_id,
+        self.client.set_server_metadata(self.server['id'],
                                         req_metadata)['metadata']
 
         # Verify the expected values are correct, and that the
         # previous values have been removed
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
         self.assertEqual(resp_metadata, req_metadata)
 
@@ -65,10 +63,10 @@
         # The server's metadata values should be updated to the
         # provided values
         meta = {'key1': 'alt1', 'key3': 'value3'}
-        self.client.update_server_metadata(self.server_id, meta)
+        self.client.update_server_metadata(self.server['id'], meta)
 
         # Verify the values have been updated to the proper values
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
         expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
         self.assertEqual(expected, resp_metadata)
@@ -78,8 +76,8 @@
         # The original metadata should not be lost if empty metadata body is
         # passed
         meta = {}
-        self.client.update_server_metadata(self.server_id, meta)
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        self.client.update_server_metadata(self.server['id'], meta)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
         expected = {'key1': 'value1', 'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
@@ -87,7 +85,7 @@
     @test.idempotent_id('3043c57d-7e0e-49a6-9a96-ad569c265e6a')
     def test_get_server_metadata_item(self):
         # The value for a specific metadata key should be returned
-        meta = self.client.show_server_metadata_item(self.server_id,
+        meta = self.client.show_server_metadata_item(self.server['id'],
                                                      'key2')['meta']
         self.assertEqual('value2', meta['key2'])
 
@@ -96,10 +94,10 @@
         # The item's value should be updated to the provided value
         # Update the metadata value
         meta = {'nova': 'alt'}
-        self.client.set_server_metadata_item(self.server_id, 'nova', meta)
+        self.client.set_server_metadata_item(self.server['id'], 'nova', meta)
 
         # Verify the meta item's value has been updated
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
         expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
         self.assertEqual(expected, resp_metadata)
@@ -107,10 +105,10 @@
     @test.idempotent_id('127642d6-4c7b-4486-b7cd-07265a378658')
     def test_delete_server_metadata_item(self):
         # The metadata value/key pair should be deleted from the server
-        self.client.delete_server_metadata_item(self.server_id, 'key1')
+        self.client.delete_server_metadata_item(self.server['id'], 'key1')
 
         # Verify the metadata item has been removed
-        resp_metadata = (self.client.list_server_metadata(self.server_id)
+        resp_metadata = (self.client.list_server_metadata(self.server['id'])
                          ['metadata'])
         expected = {'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index cbe70e2..62b8962 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -25,15 +25,12 @@
     def setup_clients(cls):
         super(ServerMetadataNegativeTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
-        cls.quotas = cls.quotas_client
 
     @classmethod
     def resource_setup(cls):
         super(ServerMetadataNegativeTestJSON, cls).resource_setup()
         cls.tenant_id = cls.client.tenant_id
-        server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
-
-        cls.server_id = server['id']
+        cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('fe114a8f-3a57-4eff-9ee2-4e14628df049')
@@ -87,7 +84,7 @@
         meta = {'testkey': 'testvalue'}
         self.assertRaises(lib_exc.BadRequest,
                           self.client.set_server_metadata_item,
-                          self.server_id, 'key', meta)
+                          self.server['id'], 'key', meta)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('0df38c2a-3d4e-4db5-98d8-d4d9fa843a12')
@@ -118,7 +115,7 @@
         meta = {'': 'data1'}
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_server_metadata,
-                          self.server_id, meta=meta)
+                          self.server['id'], meta=meta)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('6bbd88e1-f8b3-424d-ba10-ae21c45ada8d')
@@ -136,7 +133,8 @@
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
         # will be raised while exceeding metadata items limit for
         # tenant.
-        quota_set = self.quotas.show_quota_set(self.tenant_id)['quota_set']
+        quota_set = self.quotas_client.show_quota_set(
+            self.tenant_id)['quota_set']
         quota_metadata = quota_set['metadata_items']
         if quota_metadata == -1:
             raise self.skipException("No limit for metadata_items")
@@ -146,14 +144,14 @@
             req_metadata['key' + str(num)] = 'val' + str(num)
         self.assertRaises((lib_exc.OverLimit, lib_exc.Forbidden),
                           self.client.set_server_metadata,
-                          self.server_id, req_metadata)
+                          self.server['id'], req_metadata)
 
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
         # will be raised while exceeding metadata items limit for
         # tenant.
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.client.update_server_metadata,
-                          self.server_id, req_metadata)
+                          self.server['id'], req_metadata)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
@@ -163,7 +161,7 @@
         meta = {'': 'data1'}
         self.assertRaises(lib_exc.BadRequest,
                           self.client.set_server_metadata,
-                          self.server_id, meta=meta)
+                          self.server['id'], meta=meta)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('64a91aee-9723-4863-be44-4c9d9f1e7d0e')
@@ -173,4 +171,4 @@
         meta = {'meta1': 'data1'}
         self.assertRaises(lib_exc.BadRequest,
                           self.client.set_server_metadata,
-                          self.server_id, meta=meta, no_metadata_field=True)
+                          self.server['id'], meta=meta, no_metadata_field=True)
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index e5ad7b4..ab291b4 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -118,10 +118,12 @@
             raise self.skipException("No limit for personality files")
         person = []
         for i in range(0, int(max_file_limit)):
-            path = '/etc/test' + str(i) + '.txt'
+            # NOTE(andreaf) The cirros disk image is blank before boot
+            # so we can only inject safely to /
+            path = '/test' + str(i) + '.txt'
             person.append({
                 'path': path,
-                'contents': base64.encode_as_text(file_contents),
+                'contents': base64.encode_as_text(file_contents + str(i)),
             })
         password = data_utils.rand_password()
         created_server = self.create_test_server(personality=person,
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 89be3f3..1b1b339 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -490,6 +490,36 @@
                           self.client.unshelve_server,
                           self.server_id)
 
+    @test.attr(type=['negative'])
+    @test.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
+    @test.services('volume', 'image')
+    def test_create_server_from_non_bootable_volume(self):
+        # Create a volume
+        volume = self.create_volume()
+
+        # Update volume bootable status to false
+        self.volumes_client.set_bootable_volume(volume['id'],
+                                                bootable=False)
+
+        # Verify bootable flag was updated
+        nonbootable_vol = self.volumes_client.show_volume(
+            volume['id'])['volume']
+        self.assertEqual('false', nonbootable_vol['bootable'])
+
+        # Block device mapping
+        bd_map = [{'boot_index': '0',
+                   'uuid': volume['id'],
+                   'source_type': 'volume',
+                   'destination_type': 'volume',
+                   'delete_on_termination': False}]
+
+        # Try creating a server from non-bootable volume
+        self.assertRaises(lib_exc.BadRequest,
+                          self.create_test_server,
+                          image_id='',
+                          wait_until='ACTIVE',
+                          block_device_mapping_v2=bd_map)
+
 
 class ServersNegativeTestMultiTenantJSON(base.BaseV2ComputeTest):
 
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index e620e03..08c34d3 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -40,8 +40,7 @@
     @classmethod
     def resource_setup(cls):
         super(VirtualInterfacesTestJSON, cls).resource_setup()
-        server = cls.create_test_server(wait_until='ACTIVE')
-        cls.server_id = server['id']
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @test.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
     @test.services('network')
@@ -53,9 +52,9 @@
             # TODO(mriedem): After a microversion implements the API for
             # neutron, a 400 should be a failure for nova-network and neutron.
             with testtools.ExpectedException(exceptions.BadRequest):
-                self.client.list_virtual_interfaces(self.server_id)
+                self.client.list_virtual_interfaces(self.server['id'])
         else:
-            output = self.client.list_virtual_interfaces(self.server_id)
+            output = self.client.list_virtual_interfaces(self.server['id'])
             self.assertIsNotNone(output)
             virt_ifaces = output
             self.assertNotEqual(0, len(virt_ifaces['virtual_interfaces']),
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index ffd274f..f072b81 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -33,7 +33,6 @@
     @classmethod
     def setup_clients(cls):
         super(LiveBlockMigrationNegativeTestJSON, cls).setup_clients()
-        cls.admin_hosts_client = cls.os_adm.hosts_client
         cls.admin_servers_client = cls.os_adm.servers_client
 
     def _migrate_server_to(self, server_id, dest_host):
@@ -49,9 +48,8 @@
         # Migrating to an invalid host should not change the status
         target_host = data_utils.rand_name('host')
         server = self.create_test_server(wait_until="ACTIVE")
-        server_id = server['id']
 
         self.assertRaises(lib_exc.BadRequest, self._migrate_server_to,
-                          server_id, target_host)
-        waiters.wait_for_server_status(self.servers_client, server_id,
+                          server['id'], target_host)
+        waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'ACTIVE')
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 122e7cc..b9e0c35 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -48,7 +48,8 @@
                                      'fixed_ips', 'key_pairs',
                                      'injected_file_path_bytes',
                                      'instances', 'security_group_rules',
-                                     'cores', 'security_groups'))
+                                     'cores', 'security_groups',
+                                     'server_group_members', 'server_groups'))
 
     @test.idempotent_id('f1ef0a97-dbbb-4cca-adc5-c9fbc4f76107')
     def test_get_quotas(self):
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index d4831b1..1edadef 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import logging
 import testtools
 
 from tempest.api.compute import base
@@ -20,18 +21,17 @@
 from tempest.common.utils.linux import remote_client
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 CONF = config.CONF
 
+LOG = logging.getLogger(__name__)
+
 
 class AttachVolumeTestJSON(base.BaseV2ComputeTest):
     max_microversion = '2.19'
 
-    def __init__(self, *args, **kwargs):
-        super(AttachVolumeTestJSON, self).__init__(*args, **kwargs)
-        self.attachment = None
-
     @classmethod
     def skip_checks(cls):
         super(AttachVolumeTestJSON, cls).skip_checks()
@@ -47,50 +47,52 @@
     @classmethod
     def resource_setup(cls):
         cls.set_validation_resources()
-
         super(AttachVolumeTestJSON, cls).resource_setup()
         cls.device = CONF.compute.volume_device_name
 
-    def _detach(self, server_id, volume_id):
-        if self.attachment:
-            self.servers_client.detach_volume(server_id, volume_id)
-            waiters.wait_for_volume_status(self.volumes_client,
-                                           volume_id, 'available')
-
     def _create_server(self):
         # Start a server and wait for it to become ready
         server = self.create_test_server(
             validatable=True,
             wait_until='ACTIVE',
             adminPass=self.image_ssh_password)
-
         # Record addresses so that we can ssh later
         server['addresses'] = self.servers_client.list_addresses(
             server['id'])['addresses']
         return server
 
-    def _create_and_attach_volume(self, server):
-        # Create a volume and wait for it to become ready
-        volume = self.create_volume()
-        self.addCleanup(self.delete_volume, volume['id'])
+    def _detach_volume(self, server_id, volume_id):
+        try:
+            self.servers_client.detach_volume(server_id, volume_id)
+            waiters.wait_for_volume_status(self.volumes_client,
+                                           volume_id, 'available')
+        except lib_exc.NotFound:
+            LOG.warning("Unable to detach volume %s from server %s "
+                        "possibly it was already detached" % (volume_id,
+                                                              server_id))
 
+    def _attach_volume(self, server_id, volume_id, device=None):
         # Attach the volume to the server
-        self.attachment = self.servers_client.attach_volume(
-            server['id'],
-            volumeId=volume['id'],
-            device='/dev/%s' % self.device)['volumeAttachment']
+        kwargs = {'volumeId': volume_id}
+        if device:
+            kwargs.update({'device': '/dev/%s' % device})
+        attachment = self.servers_client.attach_volume(
+            server_id, **kwargs)['volumeAttachment']
         waiters.wait_for_volume_status(self.volumes_client,
-                                       volume['id'], 'in-use')
+                                       volume_id, 'in-use')
+        self.addCleanup(self._detach_volume, server_id,
+                        volume_id)
 
-        self.addCleanup(self._detach, server['id'], volume['id'])
-        return volume
+        return attachment
 
     @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
         server = self._create_server()
-        volume = self._create_and_attach_volume(server)
+        volume = self.create_volume()
+        attachment = self._attach_volume(server['id'], volume['id'],
+                                         device=self.device)
 
         self.servers_client.stop_server(server['id'])
         waiters.wait_for_server_status(self.servers_client, server['id'],
@@ -109,12 +111,11 @@
                 server=server,
                 servers_client=self.servers_client)
 
-            partitions = linux_client.get_partitions()
-            device_name_to_match = ' ' + self.device + '\n'
-            self.assertIn(device_name_to_match, partitions)
+            disks = linux_client.get_disks()
+            device_name_to_match = '\n' + self.device + ' '
+            self.assertIn(device_name_to_match, disks)
 
-        self._detach(server['id'], volume['id'])
-        self.attachment = None
+        self._detach_volume(server['id'], attachment['volumeId'])
         self.servers_client.stop_server(server['id'])
         waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'SHUTOFF')
@@ -132,28 +133,58 @@
                 server=server,
                 servers_client=self.servers_client)
 
-            partitions = linux_client.get_partitions()
-            self.assertNotIn(device_name_to_match, partitions)
+            disks = linux_client.get_disks()
+            self.assertNotIn(device_name_to_match, disks)
 
     @test.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
     def test_list_get_volume_attachments(self):
-        # Create Server, Volume and attach that Volume to Server
+        # List volume attachment of the server
         server = self._create_server()
-        volume = self._create_and_attach_volume(server)
-
-        # List Volume attachment of the server
+        volume = self.create_volume()
+        attachment = self._attach_volume(server['id'], volume['id'],
+                                         device=self.device)
         body = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
         self.assertEqual(1, len(body))
-        self.assertIn(self.attachment, body)
+        self.assertIn(attachment, body)
 
-        # Get Volume attachment of the server
+        # Get volume attachment of the server
         body = self.servers_client.show_volume_attachment(
             server['id'],
-            self.attachment['id'])['volumeAttachment']
+            attachment['id'])['volumeAttachment']
         self.assertEqual(server['id'], body['serverId'])
         self.assertEqual(volume['id'], body['volumeId'])
-        self.assertEqual(self.attachment['id'], body['id'])
+        self.assertEqual(attachment['id'], body['id'])
+
+    @test.idempotent_id('757d488b-a951-4bc7-b3cd-f417028da08a')
+    def test_list_get_two_volume_attachments(self):
+        # NOTE: This test is using the volume device auto-assignment
+        # without specifying the device ("/dev/sdb", etc). The feature
+        # is supported since Nova Liberty release or later. So this should
+        # be skipped on older clouds.
+        server = self._create_server()
+        volume_1st = self.create_volume()
+        volume_2nd = self.create_volume()
+        attachment_1st = self._attach_volume(server['id'], volume_1st['id'])
+        attachment_2nd = self._attach_volume(server['id'], volume_2nd['id'])
+
+        body = self.servers_client.list_volume_attachments(
+            server['id'])['volumeAttachments']
+        self.assertEqual(2, len(body))
+
+        body = self.servers_client.show_volume_attachment(
+            server['id'],
+            attachment_1st['id'])['volumeAttachment']
+        self.assertEqual(server['id'], body['serverId'])
+        self.assertEqual(attachment_1st['volumeId'], body['volumeId'])
+        self.assertEqual(attachment_1st['id'], body['id'])
+
+        body = self.servers_client.show_volume_attachment(
+            server['id'],
+            attachment_2nd['id'])['volumeAttachment']
+        self.assertEqual(server['id'], body['serverId'])
+        self.assertEqual(attachment_2nd['volumeId'], body['volumeId'])
+        self.assertEqual(attachment_2nd['id'], body['id'])
 
 
 class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
@@ -219,19 +250,21 @@
         # Create server, count number of volumes on it, shelve
         # server and attach pre-created volume to shelved server
         server = self._create_server()
+        volume = self.create_volume()
         num_vol = self._count_volumes(server)
         self._shelve_server(server)
-        self._create_and_attach_volume(server)
+        attachment = self._attach_volume(server['id'], volume['id'],
+                                         device=self.device)
 
         # Unshelve the instance and check that attached volume exists
         self._unshelve_server_and_check_volumes(server, num_vol + 1)
 
-        # Get Volume attachment of the server
+        # Get volume attachment of the server
         volume_attachment = self.servers_client.show_volume_attachment(
             server['id'],
-            self.attachment['id'])['volumeAttachment']
+            attachment['id'])['volumeAttachment']
         self.assertEqual(server['id'], volume_attachment['serverId'])
-        self.assertEqual(self.attachment['id'], volume_attachment['id'])
+        self.assertEqual(attachment['id'], volume_attachment['id'])
         # Check the mountpoint is not None after unshelve server even in
         # case of shelved_offloaded.
         self.assertIsNotNone(volume_attachment['device'])
@@ -240,16 +273,15 @@
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     def test_detach_volume_shelved_or_offload_server(self):
-        # Create server, count number of volumes on it, shelve
+        # Count number of volumes on instance, shelve
         # server and attach pre-created volume to shelved server
         server = self._create_server()
+        volume = self.create_volume()
         num_vol = self._count_volumes(server)
         self._shelve_server(server)
-        volume = self._create_and_attach_volume(server)
-
+        self._attach_volume(server['id'], volume['id'], device=self.device)
         # Detach the volume
-        self._detach(server['id'], volume['id'])
-        self.attachment = None
+        self._detach_volume(server['id'], volume['id'])
 
         # Unshelve the instance and check that we have the expected number of
         # volume(s)
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index b7fa0fe..1f18bfe 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -29,6 +29,7 @@
             skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
 
+    @test.related_bug('1630783', status_code=500)
     @test.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
     def test_delete_attached_volume(self):
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index 460c882..01718cc 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
@@ -39,6 +41,8 @@
         cls.snapshots_client = cls.snapshots_extensions_client
 
     @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
+    @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+                          'Cinder volume snapshots are disabled')
     def test_volume_snapshot_create_get_list_delete(self):
         volume = self.create_volume()
         self.addCleanup(self.delete_volume, volume['id'])
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index d599431..7549d4a 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -54,8 +54,8 @@
         self.assertEqual(volume['displayName'], v_name,
                          "The created volume name is not equal "
                          "to the requested name")
-        self.assertTrue(volume['id'] is not None,
-                        "Field volume id is empty or not found.")
+        self.assertIsNotNone(volume['id'],
+                             "Field volume id is empty or not found.")
         # Wait for Volume status to become ACTIVE
         waiters.wait_for_volume_status(self.client, volume['id'], 'available')
         # GET Volume
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index c60fcca..82cc653 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -14,8 +14,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
 from tempest import test
 
@@ -48,39 +46,11 @@
         cls.volume_list = []
         cls.volume_id_list = []
         for i in range(3):
-            v_name = data_utils.rand_name(cls.__name__ + '-volume')
             metadata = {'Type': 'work'}
-            try:
-                volume = cls.client.create_volume(size=CONF.volume.volume_size,
-                                                  display_name=v_name,
-                                                  metadata=metadata)['volume']
-                waiters.wait_for_volume_status(cls.client,
-                                               volume['id'], 'available')
-                volume = cls.client.show_volume(volume['id'])['volume']
-                cls.volume_list.append(volume)
-                cls.volume_id_list.append(volume['id'])
-            except Exception:
-                if cls.volume_list:
-                    # We could not create all the volumes, though we were able
-                    # to create *some* of the volumes. This is typically
-                    # because the backing file size of the volume group is
-                    # too small. So, here, we clean up whatever we did manage
-                    # to create and raise a SkipTest
-                    for volume in cls.volume_list:
-                        cls.delete_volume(volume['id'])
-                    msg = ("Failed to create ALL necessary volumes to run "
-                           "test. This typically means that the backing file "
-                           "size of the nova-volumes group is too small to "
-                           "create the 3 volumes needed by this test case")
-                    raise cls.skipException(msg)
-                raise
-
-    @classmethod
-    def resource_cleanup(cls):
-        # Delete the created Volumes
-        for volume in cls.volume_list:
-            cls.delete_volume(volume['id'])
-        super(VolumesTestJSON, cls).resource_cleanup()
+            volume = cls.create_volume(metadata=metadata)
+            volume = cls.client.show_volume(volume['id'])['volume']
+            cls.volume_list.append(volume)
+            cls.volume_id_list.append(volume['id'])
 
     @test.idempotent_id('bc2dd1a0-15af-48e5-9990-f2e75a48325d')
     def test_volume_list(self):
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index 5fe4cb3..c4041cb 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -66,7 +66,7 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
-    def test_create_volume_with_out_passing_size(self):
+    def test_create_volume_without_passing_size(self):
         # Negative: Should not be able to create volume without passing size
         # in request
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 3ed51f0..7973a03 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -38,7 +38,7 @@
         service_data = self.services_client.create_service(
             name=name, type=s_type,
             description=description)['OS-KSADM:service']
-        self.assertFalse(service_data['id'] is None)
+        self.assertIsNotNone(service_data['id'])
         self.addCleanup(self._del_service, service_data['id'])
         # Verifying response body of create service
         self.assertIn('id', service_data)
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 59ffc19..361ff31 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -36,7 +36,8 @@
     def test_default_project_id(self):
         # create a domain
         dom_name = data_utils.rand_name('dom')
-        domain_body = self.domains_client.create_domain(dom_name)['domain']
+        domain_body = self.domains_client.create_domain(
+            name=dom_name)['domain']
         dom_id = domain_body['id']
         self.addCleanup(self._delete_domain, dom_id)
 
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index cbf1439..e71341f 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -32,7 +32,7 @@
         cls.setup_domains = list()
         for i in range(3):
             domain = cls.domains_client.create_domain(
-                data_utils.rand_name('domain'),
+                name=data_utils.rand_name('domain'),
                 description=data_utils.rand_name('domain-desc'),
                 enabled=i < 2)['domain']
             cls.setup_domains.append(domain)
@@ -67,7 +67,7 @@
         # List domains filtering by name
         params = {'name': self.setup_domains[0]['name']}
         fetched_domains = self.domains_client.list_domains(
-            params=params)['domains']
+            **params)['domains']
         # Verify the filtered list is correct, domain names are unique
         # so exactly one domain should be found with the provided name
         self.assertEqual(1, len(fetched_domains))
@@ -79,7 +79,7 @@
         # List domains filtering by enabled domains
         params = {'enabled': True}
         fetched_domains = self.domains_client.list_domains(
-            params=params)['domains']
+            **params)['domains']
         # Verify the filtered list is correct
         self.assertIn(self.setup_domains[0], fetched_domains)
         self.assertIn(self.setup_domains[1], fetched_domains)
@@ -93,7 +93,7 @@
         d_name = data_utils.rand_name('domain')
         d_desc = data_utils.rand_name('domain-desc')
         domain = self.domains_client.create_domain(
-            d_name, description=d_desc)['domain']
+            name=d_name, description=d_desc)['domain']
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self._delete_domain, domain['id'])
         self.assertIn('id', domain)
@@ -138,7 +138,7 @@
         d_name = data_utils.rand_name('domain')
         d_desc = data_utils.rand_name('domain-desc')
         domain = self.domains_client.create_domain(
-            d_name, description=d_desc, enabled=False)['domain']
+            name=d_name, description=d_desc, enabled=False)['domain']
         self.addCleanup(self.domains_client.delete_domain, domain['id'])
         self.assertEqual(d_name, domain['name'])
         self.assertFalse(domain['enabled'])
@@ -148,11 +148,15 @@
     def test_create_domain_without_description(self):
         # Create domain only with name
         d_name = data_utils.rand_name('domain')
-        domain = self.domains_client.create_domain(d_name)['domain']
+        domain = self.domains_client.create_domain(name=d_name)['domain']
         self.addCleanup(self._delete_domain, domain['id'])
         self.assertIn('id', domain)
         expected_data = {'name': d_name, 'enabled': True}
-        self.assertIsNone(domain['description'])
+        # TODO(gmann): there is bug in keystone liberty version where
+        # description is not being returned if it is not being passed in
+        # request. Bug#1649245. Once bug is fixed then we can enable the below
+        # check.
+        # self.assertEqual('', domain['description'])
         self.assertDictContainsSubset(expected_data, domain)
 
 
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 4330cab..100a121 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -28,7 +28,7 @@
         d_name = data_utils.rand_name('domain')
         d_desc = data_utils.rand_name('domain-desc')
         domain = self.domains_client.create_domain(
-            d_name,
+            name=d_name,
             description=d_desc)['domain']
         domain_id = domain['id']
 
@@ -51,7 +51,8 @@
         # Domain name length should not ne greater than 64 characters
         d_name = 'a' * 65
         self.assertRaises(lib_exc.BadRequest,
-                          self.domains_client.create_domain, d_name)
+                          self.domains_client.create_domain,
+                          name=d_name)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('43781c07-764f-4cf2-a405-953c1916f605')
@@ -64,9 +65,10 @@
     @test.idempotent_id('e6f9e4a2-4f36-4be8-bdbc-4e199ae29427')
     def test_domain_create_duplicate(self):
         domain_name = data_utils.rand_name('domain-dup')
-        domain = self.domains_client.create_domain(domain_name)['domain']
+        domain = self.domains_client.create_domain(name=domain_name)['domain']
         domain_id = domain['id']
         self.addCleanup(self.delete_domain, domain_id)
         # Domain name should be unique
         self.assertRaises(
-            lib_exc.Conflict, self.domains_client.create_domain, domain_name)
+            lib_exc.Conflict, self.domains_client.create_domain,
+            name=domain_name)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 50cf258..655e4ef 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -23,7 +23,6 @@
     @classmethod
     def setup_clients(cls):
         super(EndPointsTestJSON, cls).setup_clients()
-        cls.identity_client = cls.client
         cls.client = cls.endpoints_client
 
     @classmethod
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index b16605e..f0f8707 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -25,7 +25,6 @@
     @classmethod
     def setup_clients(cls):
         super(EndpointsNegativeTestJSON, cls).setup_clients()
-        cls.identity_client = cls.client
         cls.client = cls.endpoints_client
 
     @classmethod
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 955b6fb..33fce8d 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -31,7 +31,7 @@
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_name('pass-')
         cls.domain = cls.domains_client.create_domain(
-            data_utils.rand_name('domain-'),
+            name=data_utils.rand_name('domain-'),
             description=data_utils.rand_name('domain-desc-'))['domain']
         cls.project = cls.projects_client.create_project(
             data_utils.rand_name('project-'),
@@ -168,15 +168,16 @@
             self.domain['id'], self.user['id'], src_role['id'])
 
         # List "effective" role assignments from user on the parent project
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                self.project['id'], self.user['id']))['role_assignments']
+        params = {'scope.project.id': self.project['id'],
+                  'user.id': self.user['id']}
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertNotEmpty(assignments)
 
         # List "effective" role assignments from user on the leaf project
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                leaf_project['id'], self.user['id']))['role_assignments']
+        params['scope.project.id'] = leaf_project['id']
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertNotEmpty(assignments)
 
         # Revoke role from domain
@@ -185,16 +186,16 @@
 
         # List "effective" role assignments from user on the parent project
         # should return an empty list
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                self.project['id'], self.user['id']))['role_assignments']
+        params['scope.project.id'] = self.project['id']
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertEmpty(assignments)
 
         # List "effective" role assignments from user on the leaf project
         # should return an empty list
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                leaf_project['id'], self.user['id']))['role_assignments']
+        params['scope.project.id'] = leaf_project['id']
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertEmpty(assignments)
 
     @test.idempotent_id('9f02ccd9-9b57-46b4-8f77-dd5a736f3a06')
@@ -217,9 +218,10 @@
             self.project['id'], self.user['id'], src_role['id'])
 
         # List "effective" role assignments from user on the leaf project
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                leaf_project['id'], self.user['id']))['role_assignments']
+        params = {'scope.project.id': leaf_project['id'],
+                  'user.id': self.user['id']}
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertNotEmpty(assignments)
 
         # Revoke role from parent project
@@ -228,7 +230,6 @@
 
         # List "effective" role assignments from user on the leaf project
         # should return an empty list
-        assignments = (
-            self.role_assignments.list_user_project_effective_assignments(
-                leaf_project['id'], self.user['id']))['role_assignments']
+        assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
         self.assertEmpty(assignments)
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index f5bf923..670cb2f 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -34,7 +34,7 @@
         u_email = '%s@testmail.tm' % u_name
         cls.u_password = data_utils.rand_password()
         cls.domain = cls.domains_client.create_domain(
-            data_utils.rand_name('domain'),
+            name=data_utils.rand_name('domain'),
             description=data_utils.rand_name('domain-desc'))['domain']
         cls.project = cls.projects_client.create_project(
             data_utils.rand_name('project'),
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index d5bed96..b410da6 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -34,6 +34,7 @@
         # it to be 'default'
         token_id, resp = self.non_admin_token.get_token(
             user_id=user_id,
+            username=username,
             user_domain_id=user_domain_id,
             password=password,
             auth_data=True)
@@ -49,9 +50,19 @@
         self.assertGreater(expires_at, now)
 
         subject_id = resp['user']['id']
-        self.assertEqual(subject_id, user_id)
+        if user_id:
+            self.assertEqual(subject_id, user_id)
+        else:
+            # Expect a user ID, but don't know what it will be.
+            self.assertGreaterEqual(len(subject_id), 0,
+                                    'Expected user ID in token.')
 
         subject_name = resp['user']['name']
-        self.assertEqual(subject_name, username)
+        if username:
+            self.assertEqual(subject_name, username)
+        else:
+            # Expect a user name, but don't know what it will be.
+            self.assertGreaterEqual(len(subject_name), 0,
+                                    'Expected user name in token.')
 
         self.assertEqual(resp['methods'][0], 'password')
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
index 9844a67..f22f321 100644
--- a/tempest/api/image/admin/v2/test_images.py
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -34,11 +34,10 @@
     def test_admin_deactivate_reactivate_image(self):
         # Create image by non-admin tenant
         image_name = data_utils.rand_name('image')
-        image = self.client.create_image(name=image_name,
-                                         container_format='bare',
-                                         disk_format='raw',
-                                         visibility='private')
-        self.addCleanup(self.client.delete_image, image['id'])
+        image = self.create_image(name=image_name,
+                                  container_format='bare',
+                                  disk_format='raw',
+                                  visibility='private')
         # upload an image file
         content = data_utils.random_bytes()
         image_file = six.BytesIO(content)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 1cc3fa2..812c436 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -141,6 +141,7 @@
         cls.client = cls.os.image_client_v2
         cls.namespaces_client = cls.os.namespaces_client
         cls.resource_types_client = cls.os.resource_types_client
+        cls.namespace_properties_client = cls.os.namespace_properties_client
         cls.schemas_client = cls.os.schemas_client
 
     def create_namespace(cls, namespace_name=None, visibility='public',
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 269e297..9fbdcd7 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -238,7 +238,7 @@
     def test_index_max_size(self):
         images_list = self.client.list_images(size_max=42)['images']
         for image in images_list:
-            self.assertTrue(image['size'] <= 42)
+            self.assertLessEqual(image['size'], 42)
         result_set = set(map(lambda x: x['id'], images_list))
         self.assertTrue(self.size42_set <= result_set)
         self.assertFalse(self.created_set - self.size42_set <= result_set)
@@ -247,7 +247,7 @@
     def test_index_min_size(self):
         images_list = self.client.list_images(size_min=142)['images']
         for image in images_list:
-            self.assertTrue(image['size'] >= 142)
+            self.assertGreaterEqual(image['size'], 142)
         result_set = set(map(lambda x: x['id'], images_list))
         self.assertTrue(self.size142_set <= result_set)
         self.assertFalse(self.size42_set <= result_set)
@@ -261,7 +261,7 @@
         top_size = images_list[0]['size']  # We have non-zero sized images
         for image in images_list:
             size = image['size']
-            self.assertTrue(size <= top_size)
+            self.assertLessEqual(size, top_size)
             top_size = size
             self.assertEqual(image['status'], 'active')
 
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 6f8d239..7b9244b 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -83,10 +83,10 @@
         image_name = data_utils.rand_name('image')
         container_format = CONF.image.container_formats[0]
         disk_format = CONF.image.disk_formats[0]
-        image = self.client.create_image(name=image_name,
-                                         container_format=container_format,
-                                         disk_format=disk_format,
-                                         visibility='private')
+        image = self.create_image(name=image_name,
+                                  container_format=container_format,
+                                  disk_format=disk_format,
+                                  visibility='private')
         # Delete Image
         self.client.delete_image(image['id'])
         self.client.wait_for_resource_deletion(image['id'])
@@ -105,11 +105,10 @@
         image_name = data_utils.rand_name('image')
         container_format = CONF.image.container_formats[0]
         disk_format = CONF.image.disk_formats[0]
-        image = self.client.create_image(name=image_name,
-                                         container_format=container_format,
-                                         disk_format=disk_format,
-                                         visibility='private')
-        self.addCleanup(self.client.delete_image, image['id'])
+        image = self.create_image(name=image_name,
+                                  container_format=container_format,
+                                  disk_format=disk_format,
+                                  visibility='private')
         self.assertEqual('queued', image['status'])
 
         # Now try uploading an image file
@@ -129,7 +128,6 @@
 
 
 class ListImagesTest(base.BaseV2ImageTest):
-    """Here we test the listing of image information"""
 
     @classmethod
     def resource_setup(cls):
@@ -157,23 +155,49 @@
         """
         size = random.randint(1024, 4096)
         image_file = six.BytesIO(data_utils.random_bytes(size))
+        tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
         image = cls.create_image(container_format=container_format,
                                  disk_format=disk_format,
-                                 visibility='private')
+                                 visibility='private',
+                                 tags=tags)
         cls.client.store_image_file(image['id'], data=image_file)
+        # Keep the data of one test image so it can be used to filter lists
+        cls.test_data = image
+        cls.test_data['size'] = size
 
         return image['id']
 
+
+class ListUserImagesTest(ListImagesTest):
+    """Here we test the listing of image information"""
+
     def _list_by_param_value_and_assert(self, params):
         """Perform list action with given params and validates result."""
-
+        # Retrieve the list of images that meet the filter
         images_list = self.client.list_images(params=params)['images']
         # Validating params of fetched images
+        msg = 'No images were found that met the filter criteria.'
+        self.assertNotEmpty(images_list, msg)
         for image in images_list:
             for key in params:
                 msg = "Failed to list images by %s" % key
                 self.assertEqual(params[key], image[key], msg)
 
+    def _list_sorted_by_image_size_and_assert(self, params, desc=False):
+        """Validate an image list that has been sorted by size
+
+        Perform list action with given params and validates the results are
+        sorted by image size in either ascending or descending order.
+        """
+        # Retrieve the list of images that meet the filter
+        images_list = self.client.list_images(params=params)['images']
+        # Validate that the list was fetched sorted accordingly
+        msg = 'No images were found that met the filter criteria.'
+        self.assertNotEmpty(images_list, msg)
+        sorted_list = [image['size'] for image in images_list]
+        msg = 'The list of images was not sorted correctly.'
+        self.assertEqual(sorted(sorted_list, reverse=desc), sorted_list, msg)
+
     @test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
     def test_list_no_params(self):
         # Simple test to see all fixture images returned
@@ -185,8 +209,8 @@
 
     @test.idempotent_id('9959ca1d-1aa7-4b7a-a1ea-0fff0499b37e')
     def test_list_images_param_container_format(self):
-        # Test to get all images with container_format='bare'
-        params = {"container_format": "bare"}
+        # Test to get all images with a specific container_format
+        params = {"container_format": self.test_data['container_format']}
         self._list_by_param_value_and_assert(params)
 
     @test.idempotent_id('4a4735a7-f22f-49b6-b0d9-66e1ef7453eb')
@@ -224,9 +248,10 @@
         image_size_list = map(lambda x: x['size'], images_list)
 
         for image_size in image_size_list:
-            self.assertTrue(image_size >= params['size_min'] and
-                            image_size <= params['size_max'],
-                            "Failed to get images by size_min and size_max")
+            self.assertGreaterEqual(image_size, params['size_min'],
+                                    "Failed to get images by size_min")
+            self.assertLessEqual(image_size, params['size_max'],
+                                 "Failed to get images by size_max")
 
     @test.idempotent_id('7fc9e369-0f58-4d05-9aa5-0969e2d59d15')
     def test_list_images_param_status(self):
@@ -253,6 +278,37 @@
         params = {"owner": image['owner']}
         self._list_by_param_value_and_assert(params)
 
+    @test.idempotent_id('55c8f5f5-bfed-409d-a6d5-4caeda985d7b')
+    def test_list_images_param_name(self):
+        # Test to get images by name
+        params = {'name': self.test_data['name']}
+        self._list_by_param_value_and_assert(params)
+
+    @test.idempotent_id('aa8ac4df-cff9-418b-8d0f-dd9c67b072c9')
+    def test_list_images_param_tag(self):
+        # Test to get images matching a tag
+        params = {'tag': self.test_data['tags'][0]}
+        images_list = self.client.list_images(params=params)['images']
+        # Validating properties of fetched images
+        self.assertNotEmpty(images_list)
+        for image in images_list:
+            msg = ("The image {image_name} does not have the expected tag "
+                   "{expected_tag} among its tags: {observerd_tags}."
+                   .format(image_name=image['name'],
+                           expected_tag=self.test_data['tags'][0],
+                           observerd_tags=image['tags']))
+            self.assertIn(self.test_data['tags'][0], image['tags'], msg)
+
+    @test.idempotent_id('eeadce49-04e0-43b7-aec7-52535d903e7a')
+    def test_list_images_param_sort(self):
+        params = {'sort': 'size:desc'}
+        self._list_sorted_by_image_size_and_assert(params, desc=True)
+
+    @test.idempotent_id('9faaa0c2-c3a5-43e1-8f61-61c54b409a49')
+    def test_list_images_param_sort_key_dir(self):
+        params = {'sort_key': 'size', 'sort_dir': 'desc'}
+        self._list_sorted_by_image_size_and_assert(params, desc=True)
+
     @test.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
     def test_get_image_schema(self):
         # Test to get image schema
@@ -266,3 +322,32 @@
         schema = "images"
         body = self.schemas_client.show_schema(schema)
         self.assertEqual("images", body['name'])
+
+
+class ListSharedImagesTest(ListImagesTest):
+    """Here we test the listing of a shared image information"""
+
+    credentials = ['primary', 'alt']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ListSharedImagesTest, cls).setup_clients()
+        cls.image_member_client = cls.os.image_member_client_v2
+        cls.alt_img_client = cls.os_alt.image_client_v2
+
+    @test.idempotent_id('3fa50be4-8e38-4c02-a8db-7811bb780122')
+    def test_list_images_param_member_status(self):
+        # Share one of the images created with the alt user
+        self.image_member_client.create_image_member(
+            image_id=self.test_data['id'],
+            member=self.alt_img_client.tenant_id)
+        # Update the info on the test data so it remains accurate
+        self.test_data['updated_at'] = self.client.show_image(
+            self.test_data['id'])['updated_at']
+        # As an image consumer you need to provide the member_status parameter
+        # along with the visibility=shared parameter in order for it to show
+        # results
+        params = {'member_status': 'pending', 'visibility': 'shared'}
+        fetched_images = self.alt_img_client.list_images(params)['images']
+        self.assertEqual(1, len(fetched_images))
+        self.assertEqual(self.test_data['id'], fetched_images[0]['id'])
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index fe8dd65..8a4b334 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -21,6 +21,8 @@
         image_id = self._create_image()
         member = self.image_member_client.create_image_member(
             image_id, member=self.alt_tenant_id)
+        self.addCleanup(self.image_member_client.delete_image_member,
+                        image_id, self.alt_tenant_id)
         self.assertEqual(member['member_id'], self.alt_tenant_id)
         self.assertEqual(member['image_id'], image_id)
         self.assertEqual(member['status'], 'pending')
@@ -42,6 +44,8 @@
         image_id = self._create_image()
         member = self.image_member_client.create_image_member(
             image_id, member=self.alt_tenant_id)
+        self.addCleanup(self.image_member_client.delete_image_member,
+                        image_id, self.alt_tenant_id)
         self.assertEqual(member['member_id'], self.alt_tenant_id)
         self.assertEqual(member['image_id'], image_id)
         self.assertEqual(member['status'], 'pending')
@@ -56,6 +60,8 @@
         image_id = self._create_image()
         self.image_member_client.create_image_member(
             image_id, member=self.alt_tenant_id)
+        self.addCleanup(self.image_member_client.delete_image_member,
+                        image_id, self.alt_tenant_id)
         self.alt_image_member_client.update_image_member(image_id,
                                                          self.alt_tenant_id,
                                                          status='accepted')
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_properties.py b/tempest/api/image/v2/test_images_metadefs_namespace_properties.py
new file mode 100644
index 0000000..7113db4
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_properties.py
@@ -0,0 +1,57 @@
+#    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.common.utils import data_utils
+from tempest import test
+
+
+class MetadataNamespacePropertiesTest(base.BaseV2ImageTest):
+    """Test the Metadata definition namespace property basic functionality"""
+
+    @test.idempotent_id('b1a3765e-3a5d-4f6d-a3a7-3ca3476ae768')
+    def test_basic_meta_def_namespace_property(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']
+        enum = ["xen", "qemu", "kvm", "lxc", "uml", "vmware", "hyperv"]
+        # 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)
+        # Create a property
+        property_title = data_utils.rand_name('property')
+        body = self.namespace_properties_client.create_namespace_property(
+            namespace=namespace['namespace'], title=property_title,
+            name=resource_name, type="string", enum=enum)
+        self.assertEqual(property_title, body['title'])
+        # Show namespace property
+        body = self.namespace_properties_client.show_namespace_properties(
+            namespace['namespace'], resource_name)
+        self.assertEqual(resource_name, body['name'])
+        # Update namespace property
+        update_property_title = data_utils.rand_name('update-property')
+        body = self.namespace_properties_client.update_namespace_properties(
+            namespace['namespace'], resource_name,
+            title=update_property_title, type="string",
+            enum=enum, name=resource_name)
+        self.assertEqual(update_property_title, body['title'])
+        # Delete namespace property
+        self.namespace_properties_client.delete_namespace_property(
+            namespace['namespace'], resource_name)
+        # List namespace properties and validate deletion
+        namespace_property = [
+            namespace_property['title'] for namespace_property in
+            self.namespace_properties_client.list_namespace_properties(
+                namespace['namespace'])['properties']]
+        self.assertNotIn(update_property_title, namespace_property)
diff --git a/tempest/api/image/v2/test_images_metadefs_schema.py b/tempest/api/image/v2/test_images_metadefs_schema.py
new file mode 100644
index 0000000..7edf1af
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_schema.py
@@ -0,0 +1,81 @@
+# Copyright 2016 EasyStack.
+# 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 MetadataSchemaTest(base.BaseV2ImageTest):
+    """Test to get metadata schema"""
+
+    @test.idempotent_id('e9e44891-3cb8-3b40-a532-e0a39fea3dab')
+    def test_get_metadata_namespace_schema(self):
+        # Test to get namespace schema
+        body = self.schemas_client.show_schema("metadefs/namespace")
+        self.assertEqual("namespace", body['name'])
+
+    @test.idempotent_id('ffe44891-678b-3ba0-a3e2-e0a3967b3aeb')
+    def test_get_metadata_namespaces_schema(self):
+        # Test to get namespaces schema
+        body = self.schemas_client.show_schema("metadefs/namespaces")
+        self.assertEqual("namespaces", body['name'])
+
+    @test.idempotent_id('fde34891-678b-3b40-ae32-e0a3e67b6beb')
+    def test_get_metadata_resource_type_schema(self):
+        # Test to get resource_type schema
+        body = self.schemas_client.show_schema("metadefs/resource_type")
+        self.assertEqual("resource_type_association", body['name'])
+
+    @test.idempotent_id('dfe4a891-b38b-3bf0-a3b2-e03ee67b3a3a')
+    def test_get_metadata_resources_types_schema(self):
+        # Test to get resource_types schema
+        body = self.schemas_client.show_schema("metadefs/resource_types")
+        self.assertEqual("resource_type_associations", body['name'])
+
+    @test.idempotent_id('dff4a891-b38b-3bf0-a3b2-e03ee67b3a3b')
+    def test_get_metadata_object_schema(self):
+        # Test to get object schema
+        body = self.schemas_client.show_schema("metadefs/object")
+        self.assertEqual("object", body['name'])
+
+    @test.idempotent_id('dee4a891-b38b-3bf0-a3b2-e03ee67b3a3c')
+    def test_get_metadata_objects_schema(self):
+        # Test to get objects schema
+        body = self.schemas_client.show_schema("metadefs/objects")
+        self.assertEqual("objects", body['name'])
+
+    @test.idempotent_id('dae4a891-b38b-3bf0-a3b2-e03ee67b3a3d')
+    def test_get_metadata_property_schema(self):
+        # Test to get property schema
+        body = self.schemas_client.show_schema("metadefs/property")
+        self.assertEqual("property", body['name'])
+
+    @test.idempotent_id('dce4a891-b38b-3bf0-a3b2-e03ee67b3a3e')
+    def test_get_metadata_properties_schema(self):
+        # Test to get properties schema
+        body = self.schemas_client.show_schema("metadefs/properties")
+        self.assertEqual("properties", body['name'])
+
+    @test.idempotent_id('dde4a891-b38b-3bf0-a3b2-e03ee67b3a3e')
+    def test_get_metadata_tag_schema(self):
+        # Test to get tag schema
+        body = self.schemas_client.show_schema("metadefs/tag")
+        self.assertEqual("tag", body['name'])
+
+    @test.idempotent_id('cde4a891-b38b-3bf0-a3b2-e03ee67b3a3a')
+    def test_get_metadata_tags_schema(self):
+        # Test to get tags schema
+        body = self.schemas_client.show_schema("metadefs/tags")
+        self.assertEqual("tags", body['name'])
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 7b037d5..c256b5b 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -38,11 +38,6 @@
             msg = "quotas extension not enabled."
             raise cls.skipException(msg)
 
-    @classmethod
-    def setup_clients(cls):
-        super(QuotasNegativeTest, cls).setup_clients()
-        cls.identity_admin_client = cls.os_adm.identity_client
-
     @test.idempotent_id('644f4e1b-1bf9-4af0-9fd8-eb56ac0f51cf')
     def test_network_quota_exceeding(self):
         # Set the network quota to two
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 3a264ff..978fb8f 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -43,11 +43,6 @@
             msg = "quotas extension not enabled."
             raise cls.skipException(msg)
 
-    @classmethod
-    def setup_clients(cls):
-        super(QuotasTest, cls).setup_clients()
-        cls.identity_admin_client = cls.os_adm.identity_client
-
     def _check_quotas(self, new_quotas):
         # Add a project to conduct the test
         project = data_utils.rand_name('test_project_')
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 36cb15f..aaac921 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.network import base_routers as base
 from tempest.common.utils import data_utils
 from tempest import test
@@ -80,6 +82,8 @@
         self.assertFalse(router['router']['distributed'])
 
     @test.idempotent_id('acd43596-c1fb-439d-ada8-31ad48ae3c2e')
+    @testtools.skipUnless(test.is_extension_enabled('l3-ha', 'network'),
+                          'HA routers are not available.')
     def test_centralized_router_update_to_dvr(self):
         """Test centralized router update
 
@@ -94,13 +98,22 @@
         attribute will be set to True
         """
         name = data_utils.rand_name('router')
+        tenant_id = self.routers_client.tenant_id
         # router needs to be in admin state down in order to be upgraded to DVR
+        # l3ha routers are not upgradable to dvr, make it explicitly non ha
         router = self.admin_routers_client.create_router(name=name,
                                                          distributed=False,
-                                                         admin_state_up=False)
+                                                         admin_state_up=False,
+                                                         ha=False,
+                                                         tenant_id=tenant_id)
+        router_id = router['router']['id']
         self.addCleanup(self.admin_routers_client.delete_router,
-                        router['router']['id'])
+                        router_id)
         self.assertFalse(router['router']['distributed'])
         router = self.admin_routers_client.update_router(
-            router['router']['id'], distributed=True)
+            router_id, distributed=True)
         self.assertTrue(router['router']['distributed'])
+        show_body = self.admin_routers_client.show_router(router_id)
+        self.assertTrue(show_body['router']['distributed'])
+        show_body = self.routers_client.show_router(router_id)
+        self.assertNotIn('distributed', show_body['router'])
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 629926d..c2c42bb 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -81,6 +81,7 @@
         cls.security_group_rules_client = (
             cls.os.security_group_rules_client)
         cls.network_versions_client = cls.os.network_versions_client
+        cls.service_providers_client = cls.os.service_providers_client
 
     @classmethod
     def resource_setup(cls):
@@ -135,12 +136,12 @@
         super(BaseNetworkTest, cls).resource_cleanup()
 
     @classmethod
-    def create_network(cls, network_name=None):
+    def create_network(cls, network_name=None, **kwargs):
         """Wrapper utility that returns a test network."""
         network_name = network_name or data_utils.rand_name(
-            cls.__name__ + "-network")
+            cls.__name__ + '-test-network')
 
-        body = cls.networks_client.create_network(name=network_name)
+        body = cls.networks_client.create_network(name=network_name, **kwargs)
         network = body['network']
         cls.networks.append(network)
         return network
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 4bc4262..84c48ec 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -348,9 +348,7 @@
 
     def _create_subnet_router(self, kwargs):
         subnet = self.create_subnet(self.network, **kwargs)
-        router = self.create_router(
-            router_name=data_utils.rand_name("routerv6-"),
-            admin_state_up=True)
+        router = self.create_router(admin_state_up=True)
         port = self.create_router_interface(router['id'],
                                             subnet['id'])
         body = self.ports_client.show_port(port['port_id'])
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 963d99d..7ffc30f 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -15,7 +15,6 @@
 #    under the License.
 
 from tempest.api.network 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
@@ -45,7 +44,7 @@
         # Create a network with a subnet connected to a router.
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
-        cls.router = cls.create_router(data_utils.rand_name('router'))
+        cls.router = cls.create_router()
         cls.create_router_interface(cls.router['id'], cls.subnet['id'])
         cls.port = cls.create_port(cls.network)
 
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index dadaaba..acac22b 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -27,39 +27,11 @@
 CONF = config.CONF
 
 
-class NetworksTest(base.BaseNetworkTest):
-    """Tests the following operations in the Neutron API:
-
-        create a network for a project
-        list project's networks
-        show a project network details
-        create a subnet for a project
-        list project's subnets
-        show a project subnet details
-        network update
-        subnet update
-        delete a network also deletes its subnets
-        list external networks
-
-        All subnet tests are run once with ipv4 and once with ipv6.
-
-    v2.0 of the Neutron API is assumed. It is also assumed that the following
-    options are defined in the [network] section of etc/tempest.conf:
-
-        project_network_cidr with a block of cidr's from which smaller blocks
-        can be allocated for project ipv4 subnets
-
-        project_network_v6_cidr is the equivalent for ipv6 subnets
-
-        project_network_mask_bits with the mask bits to be used to partition
-        the block defined by project_network_cidr
-
-        project_network_v6_mask_bits is the equivalent for ipv6 subnets
-    """
+class BaseNetworkTestResources(base.BaseNetworkTest):
 
     @classmethod
     def resource_setup(cls):
-        super(NetworksTest, cls).resource_setup()
+        super(BaseNetworkTestResources, cls).resource_setup()
         cls.network = cls.create_network()
         cls.name = cls.network['name']
         cls.subnet = cls._create_subnet_with_last_subnet_block(cls.network,
@@ -171,6 +143,37 @@
         self.networks.pop()
         self.subnets.pop()
 
+
+class NetworksTest(BaseNetworkTestResources):
+    """Tests the following operations in the Neutron API:
+
+        create a network for a project
+        list project's networks
+        show a project network details
+        create a subnet for a project
+        list project's subnets
+        show a project subnet details
+        network update
+        subnet update
+        delete a network also deletes its subnets
+        list external networks
+
+        All subnet tests are run once with ipv4 and once with ipv6.
+
+    v2.0 of the Neutron API is assumed. It is also assumed that the following
+    options are defined in the [network] section of etc/tempest.conf:
+
+        project_network_cidr with a block of cidr's from which smaller blocks
+        can be allocated for project ipv4 subnets
+
+        project_network_v6_cidr is the equivalent for ipv6 subnets
+
+        project_network_mask_bits with the mask bits to be used to partition
+        the block defined by project_network_cidr
+
+        project_network_v6_mask_bits is the equivalent for ipv6 subnets
+    """
+
     @test.attr(type='smoke')
     @test.idempotent_id('0e269138-0da6-4efc-a46d-578161e7b221')
     def test_create_update_delete_network_subnet(self):
@@ -206,12 +209,16 @@
     def test_show_network_fields(self):
         # Verify specific fields of a network
         fields = ['id', 'name']
+        if test.is_extension_enabled('net-mtu', 'network'):
+            fields.append('mtu')
         body = self.networks_client.show_network(self.network['id'],
                                                  fields=fields)
         network = body['network']
         self.assertEqual(sorted(network.keys()), sorted(fields))
         for field_name in fields:
             self.assertEqual(network[field_name], self.network[field_name])
+        self.assertNotIn('tenant_id', network)
+        self.assertNotIn('project_id', network)
 
     @test.attr(type='smoke')
     @test.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
@@ -226,6 +233,8 @@
     def test_list_networks_fields(self):
         # Verify specific fields of the networks
         fields = ['id', 'name']
+        if test.is_extension_enabled('net-mtu', 'network'):
+            fields.append('mtu')
         body = self.networks_client.list_networks(fields=fields)
         networks = body['networks']
         self.assertNotEmpty(networks, "Network list returned is empty")
@@ -276,29 +285,22 @@
     @test.idempotent_id('f04f61a9-b7f3-4194-90b2-9bcf660d1bfe')
     def test_delete_network_with_subnet(self):
         # Creates a network
-        name = data_utils.rand_name('network-')
-        body = self.networks_client.create_network(name=name)
-        network = body['network']
+        network = self.create_network()
         net_id = network['id']
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.networks_client.delete_network, net_id)
+                        self._delete_network, network)
 
         # Find a cidr that is not in use yet and create a subnet with it
         subnet = self.create_subnet(network)
         subnet_id = subnet['id']
 
         # Delete network while the subnet still exists
-        body = self.networks_client.delete_network(net_id)
+        self.networks_client.delete_network(net_id)
 
         # Verify that the subnet got automatically deleted.
         self.assertRaises(lib_exc.NotFound, self.subnets_client.show_subnet,
                           subnet_id)
 
-        # Since create_subnet adds the subnet to the delete list, and it is
-        # actually deleted here - this will create and issue, hence remove
-        # it from the list.
-        self.subnets.pop()
-
     @test.idempotent_id('d2d596e2-8e76-47a9-ac51-d4648009f4d3')
     def test_create_delete_subnet_without_gateway(self):
         self._create_verify_delete_subnet()
@@ -389,6 +391,21 @@
             network_id=CONF.network.public_network_id)
         self.assertEmpty(body['subnets'], "Public subnets visible")
 
+    @test.idempotent_id('c72c1c0c-2193-4aca-ccc4-b1442640bbbb')
+    @test.requires_ext(extension="standard-attr-description",
+                       service="network")
+    def test_create_update_network_description(self):
+        body = self.create_network(description='d1')
+        self.assertEqual('d1', body['description'])
+        net_id = body['id']
+        body = self.networks_client.list_networks(id=net_id)['networks'][0]
+        self.assertEqual('d1', body['description'])
+        body = self.networks_client.update_network(body['id'],
+                                                   description='d2')
+        self.assertEqual('d2', body['network']['description'])
+        body = self.networks_client.list_networks(id=net_id)['networks'][0]
+        self.assertEqual('d2', body['description'])
+
 
 class BulkNetworkOpsTest(base.BaseNetworkTest):
     """Tests the following operations in the Neutron API:
@@ -566,7 +583,9 @@
                              'Subnet are not in the same network')
 
 
-class NetworksIpV6TestAttrs(NetworksIpV6Test):
+class NetworksIpV6TestAttrs(BaseNetworkTestResources):
+
+    _ip_version = 6
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 2979f7d..5b46088 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -199,7 +199,7 @@
         self.addCleanup(self.networks_client.delete_network, network['id'])
         subnet = self.create_subnet(network)
         self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
-        router = self.create_router(data_utils.rand_name('router-'))
+        router = self.create_router()
         self.addCleanup(self.routers_client.delete_router, router['id'])
         port = self.ports_client.create_port(network_id=network['id'])
         # Add router interface to port created above
@@ -360,11 +360,6 @@
 class PortsAdminExtendedAttrsTestJSON(base.BaseAdminNetworkTest):
 
     @classmethod
-    def setup_clients(cls):
-        super(PortsAdminExtendedAttrsTestJSON, cls).setup_clients()
-        cls.identity_client = cls.os_adm.identity_client
-
-    @classmethod
     def resource_setup(cls):
         super(PortsAdminExtendedAttrsTestJSON, cls).resource_setup()
         cls.network = cls.create_network()
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index de2e71f..f2170ad 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -34,11 +34,6 @@
             raise cls.skipException(msg)
 
     @classmethod
-    def setup_clients(cls):
-        super(RoutersTest, cls).setup_clients()
-        cls.identity_admin_client = cls.os_adm.identity_client
-
-    @classmethod
     def resource_setup(cls):
         super(RoutersTest, cls).resource_setup()
         cls.tenant_cidr = (CONF.network.project_network_cidr
@@ -49,41 +44,31 @@
     @test.idempotent_id('f64403e2-8483-4b34-8ccd-b09a87bcc68c')
     def test_create_show_list_update_delete_router(self):
         # Create a router
-        # NOTE(salv-orlando): Do not invoke self.create_router
-        # as we need to check the response code
-        name = data_utils.rand_name('router-')
-        create_body = self.routers_client.create_router(
-            name=name, external_gateway_info={
-                "network_id": CONF.network.public_network_id},
-            admin_state_up=False)
-        self.addCleanup(self._delete_router, create_body['router']['id'])
-        self.assertEqual(create_body['router']['name'], name)
+        router = self._create_router(
+            admin_state_up=False,
+            external_network_id=CONF.network.public_network_id)
+        self.assertEqual(router['admin_state_up'], False)
         self.assertEqual(
-            create_body['router']['external_gateway_info']['network_id'],
+            router['external_gateway_info']['network_id'],
             CONF.network.public_network_id)
-        self.assertEqual(create_body['router']['admin_state_up'], False)
         # Show details of the created router
-        show_body = self.routers_client.show_router(
-            create_body['router']['id'])
-        self.assertEqual(show_body['router']['name'], name)
+        router_show = self.routers_client.show_router(
+            router['id'])['router']
+        self.assertEqual(router_show['name'], router['name'])
         self.assertEqual(
-            show_body['router']['external_gateway_info']['network_id'],
+            router_show['external_gateway_info']['network_id'],
             CONF.network.public_network_id)
-        self.assertEqual(show_body['router']['admin_state_up'], False)
         # List routers and verify if created router is there in response
-        list_body = self.routers_client.list_routers()
-        routers_list = list()
-        for router in list_body['routers']:
-            routers_list.append(router['id'])
-        self.assertIn(create_body['router']['id'], routers_list)
+        routers = self.routers_client.list_routers()['routers']
+        self.assertIn(router['id'], map(lambda x: x['id'], routers))
         # Update the name of router and verify if it is updated
-        updated_name = 'updated ' + name
-        update_body = self.routers_client.update_router(
-            create_body['router']['id'], name=updated_name)
-        self.assertEqual(update_body['router']['name'], updated_name)
-        show_body = self.routers_client.show_router(
-            create_body['router']['id'])
-        self.assertEqual(show_body['router']['name'], updated_name)
+        updated_name = 'updated' + router['name']
+        router_update = self.routers_client.update_router(
+            router['id'], name=updated_name)['router']
+        self.assertEqual(router_update['name'], updated_name)
+        router_show = self.routers_client.show_router(
+            router['id'])['router']
+        self.assertEqual(router_show['name'], updated_name)
 
     @test.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
     def test_create_router_setting_project_id(self):
@@ -390,35 +375,3 @@
 
 class RoutersIpV6Test(RoutersTest):
     _ip_version = 6
-
-
-class DvrRoutersTest(base.BaseRouterTest):
-
-    @classmethod
-    def skip_checks(cls):
-        super(DvrRoutersTest, cls).skip_checks()
-        if not test.is_extension_enabled('dvr', 'network'):
-            msg = "DVR extension not enabled."
-            raise cls.skipException(msg)
-
-    @test.idempotent_id('141297aa-3424-455d-aa8d-f2d95731e00a')
-    def test_create_distributed_router(self):
-        name = data_utils.rand_name('router')
-        create_body = self.admin_routers_client.create_router(
-            name=name, distributed=True)
-        self.addCleanup(self._delete_router,
-                        create_body['router']['id'],
-                        self.admin_routers_client)
-        self.assertTrue(create_body['router']['distributed'])
-
-    @test.idempotent_id('644d7a4a-01a1-4b68-bb8d-0c0042cb1729')
-    def test_convert_centralized_router(self):
-        router = self._create_router()
-        self.assertNotIn('distributed', router)
-        update_body = self.admin_routers_client.update_router(router['id'],
-                                                              distributed=True)
-        self.assertTrue(update_body['router']['distributed'])
-        show_body = self.admin_routers_client.show_router(router['id'])
-        self.assertTrue(show_body['router']['distributed'])
-        show_body = self.routers_client.show_router(router['id'])
-        self.assertNotIn('distributed', show_body['router'])
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 354e6d1..b3983de 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -134,7 +134,5 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
     def test_router_create_tenant_distributed_returns_forbidden(self):
-        self.assertRaises(lib_exc.Forbidden,
-                          self.create_router,
-                          data_utils.rand_name('router'),
+        self.assertRaises(lib_exc.Forbidden, self.create_router,
                           distributed=True)
diff --git a/tempest/api/network/test_service_providers.py b/tempest/api/network/test_service_providers.py
new file mode 100644
index 0000000..be17b3e
--- /dev/null
+++ b/tempest/api/network/test_service_providers.py
@@ -0,0 +1,28 @@
+#    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 testtools
+
+from tempest.api.network import base
+from tempest import test
+
+
+class ServiceProvidersTest(base.BaseNetworkTest):
+
+    @test.idempotent_id('2cbbeea9-f010-40f6-8df5-4eaa0c918ea6')
+    @testtools.skipUnless(
+        test.is_extension_enabled('service-type', 'network'),
+        'service-type extension not enabled.')
+    def test_service_providers_list(self):
+        body = self.service_providers_client.list_service_providers()
+        self.assertIn('service_providers', body)
+        self.assertIsInstance(body['service_providers'], list)
diff --git a/tempest/api/network/test_service_type_management.py b/tempest/api/network/test_service_type_management.py
deleted file mode 100644
index f49f082..0000000
--- a/tempest/api/network/test_service_type_management.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#    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.network import base
-from tempest.lib import decorators
-from tempest import test
-
-
-class ServiceTypeManagementTestJSON(base.BaseNetworkTest):
-
-    @classmethod
-    def skip_checks(cls):
-        super(ServiceTypeManagementTestJSON, cls).skip_checks()
-        if not test.is_extension_enabled('service-type', 'network'):
-            msg = "Neutron Service Type Management not enabled."
-            raise cls.skipException(msg)
-
-    @decorators.skip_because(bug="1400370")
-    @test.idempotent_id('2cbbeea9-f010-40f6-8df5-4eaa0c918ea6')
-    def test_service_provider_list(self):
-        body = self.client.list_service_providers()
-        self.assertIsInstance(body['service_providers'], list)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index fd973c6..eb313d2 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.common import custom_matchers
 from tempest import config
 from tempest.lib.common.utils import data_utils
@@ -48,6 +50,7 @@
         cls.object_client = cls.os.object_client
         cls.container_client = cls.os.container_client
         cls.account_client = cls.os.account_client
+        cls.capabilities_client = cls.os.capabilities_client
 
     @classmethod
     def resource_setup(cls):
@@ -63,7 +66,7 @@
         cls.policies = None
 
         if CONF.object_storage_feature_enabled.discoverability:
-            _, body = cls.account_client.list_extensions()
+            _, body = cls.capabilities_client.list_capabilities()
 
             if 'swift' in body and 'policies' in body['swift']:
                 cls.policies = body['swift']['policies']
@@ -102,6 +105,10 @@
         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.
+        After delete all the objects from a container, it will wait 2
+        seconds before delete the container itself, in order to deployments
+        using HA proxy sync the deletion properly, otherwise, the container
+        might fail to be deleted because it's not empty.
 
         :param container_client: if None, use cls.container_client, this means
             that the default testing user will be used (see 'username' in
@@ -114,11 +121,16 @@
             object_client = cls.object_client
         for cont in cls.containers:
             try:
-                objlist = container_client.list_all_container_objects(cont)
+                params = {'limit': 9999, 'format': 'json'}
+                resp, objlist = container_client.list_container_contents(
+                    cont, params)
                 # delete every object in the container
                 for obj in objlist:
                     test_utils.call_and_ignore_notfound_exc(
                         object_client.delete_object, cont, obj['name'])
+                # sleep 2 seconds to sync the deletion of the objects
+                # in HA deployment
+                time.sleep(2)
                 container_client.delete_container(cont)
             except lib_exc.NotFound:
                 pass
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index 7292ee9..a75ed98 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -66,7 +66,7 @@
         self.assertNotIn(container_name, body)
 
     @test.idempotent_id('a407de51-1983-47cc-9f14-47c2b059413c')
-    @test.requires_ext(extension='bulk', service='object')
+    @test.requires_ext(extension='bulk_upload', service='object')
     def test_extract_archive(self):
         # Test bulk operation of file upload with an archived file
         filepath, container_name, object_name = self._create_archive()
@@ -102,7 +102,7 @@
         self.assertIn(object_name, [c['name'] for c in contents_list])
 
     @test.idempotent_id('c075e682-0d2a-43b2-808d-4116200d736d')
-    @test.requires_ext(extension='bulk', service='object')
+    @test.requires_ext(extension='bulk_delete', service='object')
     def test_bulk_delete(self):
         # Test bulk operation of deleting multiple files
         filepath, container_name, object_name = self._create_archive()
@@ -129,7 +129,7 @@
         self._check_contents_deleted(container_name)
 
     @test.idempotent_id('dbea2bcb-efbb-4674-ac8a-a5a0e33d1d79')
-    @test.requires_ext(extension='bulk', service='object')
+    @test.requires_ext(extension='bulk_delete', service='object')
     def test_bulk_delete_by_POST(self):
         # Test bulk operation of deleting multiple files
         filepath, container_name, object_name = self._create_archive()
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 33e5852..59129e5 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -15,6 +15,7 @@
 
 import random
 
+import six
 import testtools
 
 from tempest.api.object_storage import base
@@ -60,8 +61,10 @@
         self.assertHeaders(resp, 'Account', 'GET')
 
         self.assertIsNotNone(container_list)
+
         for container_name in self.containers:
-            self.assertIn(container_name, container_list)
+            self.assertIn(six.text_type(container_name).encode('utf-8'),
+                          container_list)
 
     @test.idempotent_id('884ec421-fbad-4fcc-916b-0580f2699565')
     def test_list_no_containers(self):
@@ -121,7 +124,7 @@
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertIsNotNone(container_list)
         self.assertEqual(container_list.tag, 'account')
-        self.assertTrue('name' in container_list.keys())
+        self.assertIn('name', container_list.keys())
         self.assertEqual(container_list.find(".//container").tag, 'container')
         self.assertEqual(container_list.find(".//name").tag, 'name')
         self.assertEqual(container_list.find(".//count").tag, 'count')
@@ -132,7 +135,7 @@
         not CONF.object_storage_feature_enabled.discoverability,
         'Discoverability function is disabled')
     def test_list_extensions(self):
-        resp, extensions = self.account_client.list_extensions()
+        resp, extensions = self.capabilities_client.list_capabilities()
 
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
@@ -209,7 +212,8 @@
                 self.account_client.list_account_containers(params=params)
             self.assertHeaders(resp, 'Account', 'GET')
 
-            self.assertTrue(len(container_list) <= limit, str(container_list))
+            self.assertLessEqual(len(container_list), limit,
+                                 str(container_list))
 
     @test.idempotent_id('888a3f0e-7214-4806-8e50-5e0c9a69bb5e')
     def test_list_containers_with_limit_and_end_marker(self):
@@ -245,7 +249,8 @@
             params=params)
         self.assertHeaders(resp, 'Account', 'GET')
         for container in container_list:
-            self.assertEqual(True, container.startswith(prefix))
+            self.assertEqual(True, container.decode(
+                'utf-8').startswith(prefix))
 
     @test.attr(type='smoke')
     @test.idempotent_id('4894c312-6056-4587-8d6f-86ffbf861f80')
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index dbe8b4a..9ce1b18 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -205,7 +205,7 @@
 
         self.assertIsNotNone(object_list)
         self.assertEqual(object_list.tag, 'container')
-        self.assertTrue('name' in object_list.keys())
+        self.assertIn('name', object_list.keys())
         self.assertEqual(object_list.find(".//object").tag, 'object')
         self.assertEqual(object_list.find(".//name").tag, 'name')
         self.assertEqual(object_list.find(".//hash").tag, 'hash')
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index ed99eb2..f63c518 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.py
@@ -13,11 +13,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.object_storage import base
+from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import exceptions
 from tempest import test
 
+CONF = config.CONF
+
 
 class ContainerNegativeTest(base.BaseObjectTest):
 
@@ -25,12 +30,16 @@
     def resource_setup(cls):
         super(ContainerNegativeTest, cls).resource_setup()
 
-        # use /info to get default constraints
-        _, body = cls.account_client.list_extensions()
-        cls.constraints = body['swift']
+        if CONF.object_storage_feature_enabled.discoverability:
+            # use /info to get default constraints
+            _, body = cls.capabilities_client.list_capabilities()
+            cls.constraints = body['swift']
 
     @test.attr(type=["negative"])
     @test.idempotent_id('30686921-4bed-4764-a038-40d741ed4e78')
+    @testtools.skipUnless(
+        CONF.object_storage_feature_enabled.discoverability,
+        'Discoverability function is disabled')
     def test_create_container_name_exceeds_max_length(self):
         # Attempts to create a container name that is longer than max
         max_length = self.constraints['max_container_name_length']
@@ -44,6 +53,9 @@
 
     @test.attr(type=["negative"])
     @test.idempotent_id('41e645bf-2e68-4f84-bf7b-c71aa5cd76ce')
+    @testtools.skipUnless(
+        CONF.object_storage_feature_enabled.discoverability,
+        'Discoverability function is disabled')
     def test_create_container_metadata_name_exceeds_max_length(self):
         # Attempts to create container with metadata name
         # that is longer than max.
@@ -58,6 +70,9 @@
 
     @test.attr(type=["negative"])
     @test.idempotent_id('81e36922-326b-4b7c-8155-3bbceecd7a82')
+    @testtools.skipUnless(
+        CONF.object_storage_feature_enabled.discoverability,
+        'Discoverability function is disabled')
     def test_create_container_metadata_value_exceeds_max_length(self):
         # Attempts to create container with metadata value
         # that is longer than max.
@@ -72,6 +87,9 @@
 
     @test.attr(type=["negative"])
     @test.idempotent_id('ac666539-d566-4f02-8ceb-58e968dfb732')
+    @testtools.skipUnless(
+        CONF.object_storage_feature_enabled.discoverability,
+        'Discoverability function is disabled')
     def test_create_container_metadata_exceeds_overall_metadata_count(self):
         # Attempts to create container with metadata that exceeds the
         # default count
@@ -92,47 +110,39 @@
     def test_get_metadata_headers_with_invalid_container_name(self):
         # Attempts to retrieve metadata headers with an invalid
         # container name.
-        invalid_name = data_utils.rand_name(name="TestInvalidContainer")
-
         self.assertRaises(exceptions.NotFound,
                           self.container_client.list_container_metadata,
-                          invalid_name)
+                          'invalid_container_name')
 
     @test.attr(type=["negative"])
     @test.idempotent_id('125a24fa-90a7-4cfc-b604-44e49d788390')
     def test_update_metadata_with_nonexistent_container_name(self):
         # Attempts to update metadata using a nonexistent container name.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
         metadata = {'animal': 'penguin'}
 
         self.assertRaises(exceptions.NotFound,
                           self.container_client.update_container_metadata,
-                          nonexistent_name, metadata)
+                          'nonexistent_container_name', metadata)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('65387dbf-a0e2-4aac-9ddc-16eb3f1f69ba')
     def test_delete_with_nonexistent_container_name(self):
         # Attempts to delete metadata using a nonexistent container name.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
         metadata = {'animal': 'penguin'}
 
         self.assertRaises(exceptions.NotFound,
                           self.container_client.delete_container_metadata,
-                          nonexistent_name, metadata)
+                          'nonexistent_container_name', metadata)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('14331d21-1e81-420a-beea-19cb5e5207f5')
     def test_list_all_container_objects_with_nonexistent_container(self):
         # Attempts to get a listing of all objects on a container
         # that doesn't exist.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
-
+        params = {'limit': 9999, 'format': 'json'}
         self.assertRaises(exceptions.NotFound,
-                          self.container_client.list_all_container_objects,
-                          nonexistent_name)
+                          self.container_client.list_container_contents,
+                          'nonexistent_container_name', params)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('86b2ab08-92d5-493d-acd2-85f0c848819e')
@@ -143,10 +153,10 @@
         # delete container
         resp, _ = self.container_client.delete_container(container_name)
         self.assertHeaders(resp, 'Container', 'DELETE')
-
+        params = {'limit': 9999, 'format': 'json'}
         self.assertRaises(exceptions.NotFound,
-                          self.container_client.list_all_container_objects,
-                          container_name)
+                          self.container_client.list_container_contents,
+                          container_name, params)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('42da116e-1e8c-4c96-9e06-2f13884ed2b1')
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 3f45634..6d27502 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -10,15 +10,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
-import logging
-
 import netaddr
+from oslo_log import log as logging
 
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest import exceptions
+from tempest.lib import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -79,7 +77,7 @@
             cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
             resources = (cls.client.list_resources(cls.stack_identifier)
                          ['resources'])
-        except exceptions.TimeoutException as e:
+        except exceptions.TimeoutException:
             if CONF.compute_feature_enabled.console_output:
                 # attempt to log the server console to help with debugging
                 # the cause of the server not signalling the waitcondition
@@ -91,7 +89,7 @@
                 output = cls.servers_client.get_console_output(
                     server_id)['output']
                 LOG.debug(output)
-            raise e
+            raise
 
         cls.test_resources = {}
         for resource in resources:
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 8d12e75..16d8180 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -78,12 +78,12 @@
         self.assertIn('-----BEGIN', output_map['KeyPair_PrivateKey'])
         # Test that second key generated public key, and private key is not
         # in the output due to save_private_key = false
-        self.assertTrue('KeyPairDontSavePrivate_PublicKey' in output_map)
-        self.assertTrue('Generated' in
-                        output_map['KeyPairDontSavePrivate_PublicKey'])
-        self.assertTrue(u'KeyPairDontSavePrivate_PrivateKey' in output_map)
+        self.assertIn('KeyPairDontSavePrivate_PublicKey', output_map)
+        self.assertIn('Generated',
+                      output_map['KeyPairDontSavePrivate_PublicKey'])
+        self.assertIn(u'KeyPairDontSavePrivate_PrivateKey', output_map)
         private_key = output_map['KeyPairDontSavePrivate_PrivateKey']
-        self.assertTrue(len(private_key) == 0)
+        self.assertEqual(0, len(private_key))
 
 
 class NovaKeyPairResourcesAWSTest(NovaKeyPairResourcesYAMLTest):
diff --git a/tempest/api/orchestration/stacks/test_templates_negative.py b/tempest/api/orchestration/stacks/test_templates_negative.py
index 24e10dd..f8245c1 100644
--- a/tempest/api/orchestration/stacks/test_templates_negative.py
+++ b/tempest/api/orchestration/stacks/test_templates_negative.py
@@ -27,7 +27,7 @@
     Type: AWS::IAM::User
 """
 
-    invalid_template_url = 'http://www.example.com/template.yaml'
+    invalid_template_url = 'http:///template.yaml'
 
     @classmethod
     def resource_setup(cls):
@@ -57,4 +57,4 @@
 }
 """
 
-    invalid_template_url = 'http://www.example.com/template.template'
+    invalid_template_url = 'http:///template.template'
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 120dbb1..5703313 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -129,7 +129,7 @@
         volume1_host = volume['os-vol-host-attr:host']
         msg = ("multi-backend reporting incorrect values for volume %s" %
                volume_id)
-        self.assertTrue(len(volume1_host.split("@")) > 1, msg)
+        self.assertGreater(len(volume1_host.split("@")), 1, msg)
 
     def _test_backend_name_distinction(self, volume_id_list):
         # this test checks that the volumes created at setUp don't
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 1468e90..29a161b 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
 
@@ -29,25 +28,14 @@
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
-    def setup_clients(cls):
-        super(SnapshotsActionsV2Test, cls).setup_clients()
-        cls.client = cls.snapshots_client
-
-    @classmethod
     def resource_setup(cls):
         super(SnapshotsActionsV2Test, cls).resource_setup()
 
         # Create a test shared volume for tests
-        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.create_volume(**params)
+        cls.volume = cls.create_volume()
 
         # 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.create_snapshot(
-            volume_id=cls.volume['id'], **params)
+        cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
 
     def tearDown(self):
         # Set snapshot's status to available after test
@@ -66,7 +54,7 @@
                 reset_snapshot_status(temp_snapshot['id'], status)
         self.admin_snapshots_client.\
             force_delete_snapshot(temp_snapshot['id'])
-        self.client.wait_for_resource_deletion(temp_snapshot['id'])
+        self.snapshots_client.wait_for_resource_deletion(temp_snapshot['id'])
 
     def _get_progress_alias(self):
         return 'os-extended-snapshot-attributes:progress'
@@ -92,8 +80,9 @@
         progress = '80%'
         status = 'error'
         progress_alias = self._get_progress_alias()
-        self.client.update_snapshot_status(self.snapshot['id'],
-                                           status=status, progress=progress)
+        self.snapshots_client.update_snapshot_status(self.snapshot['id'],
+                                                     status=status,
+                                                     progress=progress)
         snapshot_get = self.admin_snapshots_client.show_snapshot(
             self.snapshot['id'])['snapshot']
         self.assertEqual(status, snapshot_get['status'])
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index b58c525..f6de9a6 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -22,8 +22,8 @@
     @test.idempotent_id('d5f3efa2-6684-4190-9ced-1c2f526352ad')
     def test_list_hosts(self):
         hosts = self.admin_hosts_client.list_hosts()['hosts']
-        self.assertTrue(len(hosts) >= 2, "No. of hosts are < 2,"
-                        "response of list hosts is: % s" % hosts)
+        self.assertGreaterEqual(len(hosts), 2, "No. of hosts are < 2,"
+                                "response of list hosts is: % s" % hosts)
 
 
 class VolumeHostsAdminV1TestsJSON(VolumeHostsAdminV2TestsJSON):
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 99f0a6b..3098cab 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -51,8 +51,7 @@
                   'size': CONF.volume.volume_size}
 
         # Create volume
-        volume = self.volumes_client.create_volume(**params)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
+        volume = self.create_volume(**params)
         self.assertEqual(volume_types[0]['name'], volume["volume_type"])
         self.assertEqual(volume[self.name_field], vol_name,
                          "The created volume name is not equal "
@@ -102,8 +101,8 @@
         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.")
+        self.assertIsNotNone(body['id'],
+                             "Field volume_type id is empty or not found.")
         fetched_volume_type = self.admin_volume_types_client.show_volume_type(
             body['id'])['volume_type']
         self.assertEqual(name, fetched_volume_type['name'],
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index e7a3f62..a63cbf0 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -14,32 +14,11 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class VolumesActionsV2Test(base.BaseVolumeAdminTest):
 
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesActionsV2Test, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesActionsV2Test, cls).resource_setup()
-
-        # Create a test shared volume for tests
-        cls.volume = cls.create_volume()
-
-    def tearDown(self):
-        # Set volume's status to available after test
-        self.admin_volume_client.reset_volume_status(
-            self.volume['id'], status='available')
-        super(VolumesActionsV2Test, self).tearDown()
-
     def _create_reset_and_force_delete_temp_volume(self, status=None):
         # Create volume, reset volume status, and force delete temp volume
         temp_volume = self.create_volume()
@@ -47,16 +26,18 @@
             self.admin_volume_client.reset_volume_status(
                 temp_volume['id'], status=status)
         self.admin_volume_client.force_delete_volume(temp_volume['id'])
-        self.client.wait_for_resource_deletion(temp_volume['id'])
+        self.volumes_client.wait_for_resource_deletion(temp_volume['id'])
 
     @test.idempotent_id('d063f96e-a2e0-4f34-8b8a-395c42de1845')
     def test_volume_reset_status(self):
         # test volume reset status : available->error->available
-        self.admin_volume_client.reset_volume_status(
-            self.volume['id'], status='error')
-        volume_get = self.admin_volume_client.show_volume(
-            self.volume['id'])['volume']
-        self.assertEqual('error', volume_get['status'])
+        volume = self.create_volume()
+        for status in ['error', 'available']:
+            self.admin_volume_client.reset_volume_status(
+                volume['id'], status=status)
+            volume_get = self.admin_volume_client.show_volume(
+                volume['id'])['volume']
+            self.assertEqual(status, volume_get['status'])
 
     @test.idempotent_id('21737d5a-92f2-46d7-b009-a0cc0ee7a570')
     def test_volume_force_delete_when_volume_is_creating(self):
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 73f1f8f..61d4ba7 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -33,12 +33,6 @@
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesBackupsAdminV2Test, cls).resource_setup()
-
-        cls.volume = cls.create_volume()
-
     def _delete_backup(self, backup_id):
         self.admin_backups_client.delete_backup(backup_id)
         self.admin_backups_client.wait_for_resource_deletion(backup_id)
@@ -62,14 +56,13 @@
         Cinder allows exporting DB backup information through its API so it can
         be imported back in case of a DB loss.
         """
+        volume = self.create_volume()
         # Create 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'])
+        backup = (self.create_backup(backup_client=self.admin_backups_client,
+                                     volume_id=volume['id'],
+                                     name=backup_name))
         self.assertEqual(backup_name, backup['name'])
-        waiters.wait_for_backup_status(self.admin_backups_client,
-                                       backup['id'], 'available')
 
         # Export Backup
         export_backup = (self.admin_backups_client.export_backup(backup['id'])
@@ -126,16 +119,15 @@
 
     @test.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
     def test_volume_backup_reset_status(self):
+        # Create a volume
+        volume = self.create_volume()
         # 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'])
+        backup = self.create_backup(backup_client=self.admin_backups_client,
+                                    volume_id=volume['id'],
+                                    name=backup_name)
         self.assertEqual(backup_name, backup['name'])
-        waiters.wait_for_backup_status(self.admin_backups_client,
-                                       backup['id'], 'available')
         # Reset backup status to error
         self.admin_backups_client.reset_backup_status(backup_id=backup['id'],
                                                       status="error")
diff --git a/tempest/api/volume/admin/test_backends_capabilities.py b/tempest/api/volume/admin/v2/test_backends_capabilities.py
similarity index 90%
rename from tempest/api/volume/admin/test_backends_capabilities.py
rename to tempest/api/volume/admin/v2/test_backends_capabilities.py
index 8a21853..fc9066c 100644
--- a/tempest/api/volume/admin/test_backends_capabilities.py
+++ b/tempest/api/volume/admin/v2/test_backends_capabilities.py
@@ -38,13 +38,13 @@
         # Get host list, formation: host@backend-name
         cls.hosts = [
             pool['name'] for pool in
-            cls.admin_volume_client.show_pools()['pools']
+            cls.admin_scheduler_stats_client.list_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(
+        backend = self.admin_capabilities_client.show_backend_capabilities(
             self.hosts[0])
 
         # Verify getting capabilities parameters from a backend
@@ -62,12 +62,12 @@
         # Get list backend capabilities using show_pools
         cinder_pools = [
             pool['capabilities'] for pool in
-            self.admin_volume_client.show_pools(detail=True)['pools']
+            self.admin_scheduler_stats_client.list_pools(detail=True)['pools']
         ]
 
         # Get list backends capabilities using show_backend_capabilities
         capabilities = [
-            self.admin_volume_client.show_backend_capabilities(
+            self.admin_capabilities_client.show_backend_capabilities(
                 host=host) for host in self.hosts
         ]
 
diff --git a/tempest/api/volume/admin/v2/test_volume_pools.py b/tempest/api/volume/admin/v2/test_volume_pools.py
index c662e8c..8544a6a 100644
--- a/tempest/api/volume/admin/v2/test_volume_pools.py
+++ b/tempest/api/volume/admin/v2/test_volume_pools.py
@@ -25,19 +25,18 @@
         # Create a test shared volume for tests
         cls.volume = cls.create_volume()
 
-    @test.idempotent_id('0248a46c-e226-4933-be10-ad6fca8227e7')
-    def test_get_pools_without_details(self):
-        volume_info = self.admin_volume_client. \
-            show_volume(self.volume['id'])['volume']
-        cinder_pools = self.admin_volume_client.show_pools()['pools']
+    def _assert_host_volume_in_pools(self, with_detail=False):
+        volume_info = self.admin_volume_client.show_volume(
+            self.volume['id'])['volume']
+        cinder_pools = self.admin_volume_client.show_pools(
+            detail=with_detail)['pools']
         self.assertIn(volume_info['os-vol-host-attr:host'],
                       [pool['name'] for pool in cinder_pools])
 
+    @test.idempotent_id('0248a46c-e226-4933-be10-ad6fca8227e7')
+    def test_get_pools_without_details(self):
+        self._assert_host_volume_in_pools()
+
     @test.idempotent_id('d4bb61f7-762d-4437-b8a4-5785759a0ced')
     def test_get_pools_with_details(self):
-        volume_info = self.admin_volume_client. \
-            show_volume(self.volume['id'])['volume']
-        cinder_pools = self.admin_volume_client.\
-            show_pools(detail=True)['pools']
-        self.assertIn(volume_info['os-vol-host-attr:host'],
-                      [pool['name'] for pool in cinder_pools])
+        self._assert_host_volume_in_pools(with_detail=True)
diff --git a/tempest/api/volume/admin/v2/test_volume_type_access.py b/tempest/api/volume/admin/v2/test_volume_type_access.py
index 91ff5af..80dbf12 100644
--- a/tempest/api/volume/admin/v2/test_volume_type_access.py
+++ b/tempest/api/volume/admin/v2/test_volume_type_access.py
@@ -16,7 +16,6 @@
 import operator
 
 from tempest.api.volume import base
-from tempest.common import waiters
 from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -52,13 +51,7 @@
                         project=self.volumes_client.tenant_id)
 
         # Creating a volume from primary tenant
-        volume = self.volumes_client.create_volume(
-            volume_type=volume_type['id'],
-            size=CONF.volume.volume_size)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
-        waiters.wait_for_volume_status(self.volumes_client, volume['id'],
-                                       'available')
-
+        volume = self.create_volume(volume_type=volume_type['id'])
         # Validating the created volume is based on the volume type
         self.assertEqual(volume_type['name'], volume['volume_type'])
 
diff --git a/tempest/api/volume/admin/v2/test_volumes_list.py b/tempest/api/volume/admin/v2/test_volumes_list.py
index 4437803..cdd9df9 100644
--- a/tempest/api/volume/admin/v2/test_volumes_list.py
+++ b/tempest/api/volume/admin/v2/test_volumes_list.py
@@ -29,7 +29,9 @@
     def resource_setup(cls):
         super(VolumesListAdminV2TestJSON, cls).resource_setup()
         # Create 3 test volumes
-        cls.volume_list = []
+        # NOTE(zhufl): When using pre-provisioned credentials, the project
+        # may have volumes other than those created below.
+        cls.volume_list = cls.volumes_client.list_volumes()['volumes']
         for i in range(3):
             volume = cls.create_volume()
             # Fetch volume details
@@ -59,5 +61,6 @@
         # primary tenant
         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
+        expected_tenant_id = [self.volumes_client.tenant_id] * \
+            len(self.volume_list)
         self.assertEqual(expected_tenant_id, fetched_tenant_id)
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/v3/test_user_messages.py
index 39a5dfa..257a434 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/v3/test_user_messages.py
@@ -15,9 +15,7 @@
 
 from tempest.api.volume.v3 import base
 from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -47,21 +45,11 @@
                        'vendor_name': bad_vendor}
         vol_type_name = data_utils.rand_name(
             self.__class__.__name__ + '-volume-type')
-        bogus_type = self.admin_volume_types_client.create_volume_type(
-            name=vol_type_name,
-            extra_specs=extra_specs)['volume_type']
-        self.addCleanup(self.admin_volume_types_client.delete_volume_type,
-                        bogus_type['id'])
+        bogus_type = self.create_volume_type(
+            name=vol_type_name, extra_specs=extra_specs)
         params = {'volume_type': bogus_type['id'],
                   'size': CONF.volume.volume_size}
-        volume = self.volumes_client.create_volume(**params)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
-        try:
-            waiters.wait_for_volume_status(self.volumes_client, volume['id'],
-                                           'error')
-        except exceptions.VolumeBuildErrorException:
-            # Error state is expected and desired
-            pass
+        volume = self.create_volume(wait_until="error", **params)
         messages = self.messages_client.list_messages()['messages']
         message_id = None
         for message in messages:
diff --git a/tempest/api/volume/api_microversion_fixture.py b/tempest/api/volume/api_microversion_fixture.py
index 6817eaa..64bc537 100644
--- a/tempest/api/volume/api_microversion_fixture.py
+++ b/tempest/api/volume/api_microversion_fixture.py
@@ -13,7 +13,7 @@
 
 import fixtures
 
-from tempest.services.volume.base import base_v3_client
+from tempest.lib.services.volume.v3 import base_client
 
 
 class APIMicroversionFixture(fixtures.Fixture):
@@ -23,8 +23,8 @@
 
     def _setUp(self):
         super(APIMicroversionFixture, self)._setUp()
-        base_v3_client.VOLUME_MICROVERSION = self.volume_microversion
+        base_client.VOLUME_MICROVERSION = self.volume_microversion
         self.addCleanup(self._reset_volume_microversion)
 
     def _reset_volume_microversion(self):
-        base_v3_client.VOLUME_MICROVERSION = None
+        base_client.VOLUME_MICROVERSION = None
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index b788d54..9f522bd 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -73,6 +73,7 @@
             cls.volumes_extension_client = cls.os.volumes_extension_client
             cls.availability_zone_client = (
                 cls.os.volume_availability_zone_client)
+            cls.volume_limits_client = cls.os.volume_limits_client
         else:
             cls.snapshots_client = cls.os.snapshots_v2_client
             cls.volumes_client = cls.os.volumes_v2_client
@@ -80,6 +81,7 @@
             cls.volumes_extension_client = cls.os.volumes_v2_extension_client
             cls.availability_zone_client = (
                 cls.os.volume_v2_availability_zone_client)
+            cls.volume_limits_client = cls.os.volume_v2_limits_client
 
     @classmethod
     def resource_setup(cls):
@@ -108,26 +110,39 @@
         super(BaseVolumeTest, cls).resource_cleanup()
 
     @classmethod
-    def create_volume(cls, **kwargs):
-        """Wrapper utility that returns a test volume."""
+    def create_volume(cls, wait_until='available', **kwargs):
+        """Wrapper utility that returns a test volume.
+
+           :param wait_until: wait till volume status.
+        """
         if 'size' not in kwargs:
             kwargs['size'] = CONF.volume.volume_size
 
-        name = data_utils.rand_name(cls.__name__ + '-Volume')
+        if 'imageRef' in kwargs:
+            image = cls.compute_images_client.show_image(
+                kwargs['imageRef'])['image']
+            min_disk = image.get('minDisk')
+            kwargs['size'] = max(kwargs['size'], min_disk)
 
         name_field = cls.special_fields['name_field']
+        if name_field not in kwargs:
+            name = data_utils.rand_name(cls.__name__ + '-Volume')
+            kwargs[name_field] = name
 
-        kwargs[name_field] = name
         volume = cls.volumes_client.create_volume(**kwargs)['volume']
-
         cls.volumes.append(volume)
-        waiters.wait_for_volume_status(cls.volumes_client,
-                                       volume['id'], 'available')
+        waiters.wait_for_volume_status(cls.volumes_client, volume['id'],
+                                       wait_until)
         return volume
 
     @classmethod
     def create_snapshot(cls, volume_id=1, **kwargs):
         """Wrapper utility that returns a test snapshot."""
+        name_field = cls.special_fields['name_field']
+        if name_field not in kwargs:
+            name = data_utils.rand_name(cls.__name__ + '-Snapshot')
+            kwargs[name_field] = name
+
         snapshot = cls.snapshots_client.create_snapshot(
             volume_id=volume_id, **kwargs)['snapshot']
         cls.snapshots.append(snapshot)
@@ -135,6 +150,18 @@
                                          snapshot['id'], 'available')
         return snapshot
 
+    def create_backup(self, volume_id, backup_client=None, **kwargs):
+        """Wrapper utility that returns a test backup."""
+        if backup_client is None:
+            backup_client = self.backups_client
+
+        backup = backup_client.create_backup(
+            volume_id=volume_id, **kwargs)['backup']
+        self.addCleanup(backup_client.delete_backup, backup['id'])
+        waiters.wait_for_backup_status(backup_client, backup['id'],
+                                       'available')
+        return backup
+
     # NOTE(afazekas): these create_* and clean_* could be defined
     # only in a single location in the source, and could be more general.
 
@@ -144,6 +171,18 @@
         client.delete_volume(volume_id)
         client.wait_for_resource_deletion(volume_id)
 
+    def attach_volume(self, server_id, volume_id):
+        """Attachs a volume to a server"""
+        self.servers_client.attach_volume(
+            server_id, volumeId=volume_id,
+            device='/dev/%s' % CONF.compute.volume_device_name)
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       volume_id, 'in-use')
+        self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
+                        volume_id, 'available')
+        self.addCleanup(self.servers_client.detach_volume, server_id,
+                        volume_id)
+
     @classmethod
     def clear_volumes(cls):
         for volume in cls.volumes:
@@ -173,7 +212,7 @@
                 pass
 
     def create_server(self, **kwargs):
-        name = kwargs.get(
+        name = kwargs.pop(
             'name',
             data_utils.rand_name(self.__class__.__name__ + '-instance'))
 
@@ -213,6 +252,7 @@
             cls.admin_encryption_types_client = \
                 cls.os_adm.encryption_types_client
             cls.admin_quotas_client = cls.os_adm.volume_quotas_client
+            cls.admin_volume_limits_client = cls.os_adm.volume_limits_client
         elif cls._api_version == 2:
             cls.admin_volume_qos_client = cls.os_adm.volume_qos_v2_client
             cls.admin_volume_services_client = \
@@ -225,6 +265,11 @@
             cls.admin_encryption_types_client = \
                 cls.os_adm.encryption_types_v2_client
             cls.admin_quotas_client = cls.os_adm.volume_quotas_v2_client
+            cls.admin_volume_limits_client = cls.os_adm.volume_v2_limits_client
+            cls.admin_capabilities_client = \
+                cls.os_adm.volume_capabilities_v2_client
+            cls.admin_scheduler_stats_client = \
+                cls.os_adm.volume_scheduler_stats_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index fe51375..ae4b8f9 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -30,7 +30,7 @@
         # List of availability zone
         availability_zone = (self.client.list_availability_zones()
                              ['availabilityZoneInfo'])
-        self.assertTrue(len(availability_zone) > 0)
+        self.assertGreater(len(availability_zone), 0)
 
 
 class AvailabilityZoneV1TestJSON(AvailabilityZoneV2TestJSON):
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index 688baf5..d0fa07e 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -30,70 +30,53 @@
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
-    def setup_clients(cls):
-        super(SnapshotV2MetadataTestJSON, cls).setup_clients()
-        cls.client = cls.snapshots_client
-
-    @classmethod
     def resource_setup(cls):
         super(SnapshotV2MetadataTestJSON, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
         # Create a snapshot
         cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
-        cls.snapshot_id = cls.snapshot['id']
 
     def tearDown(self):
         # Update the metadata to {}
-        self.client.update_snapshot_metadata(self.snapshot_id, metadata={})
+        self.snapshots_client.update_snapshot_metadata(
+            self.snapshot['id'], metadata={})
         super(SnapshotV2MetadataTestJSON, self).tearDown()
 
     @test.idempotent_id('a2f20f99-e363-4584-be97-bc33afb1a56c')
-    def test_create_get_delete_snapshot_metadata(self):
+    def test_crud_snapshot_metadata(self):
         # Create metadata for the snapshot
         metadata = {"key1": "value1",
                     "key2": "value2",
                     "key3": "value3"}
-        expected = {"key2": "value2",
-                    "key3": "value3"}
-        body = self.client.create_snapshot_metadata(
-            self.snapshot_id, metadata)['metadata']
-        # Get the metadata of the snapshot
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
-
-        # Delete one item metadata of the snapshot
-        self.client.delete_snapshot_metadata_item(
-            self.snapshot_id, "key1")
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(expected.items()))
-        self.assertNotIn("key1", body)
-
-    @test.idempotent_id('bd2363bc-de92-48a4-bc98-28943c6e4be1')
-    def test_update_snapshot_metadata(self):
-        # Update metadata for the snapshot
-        metadata = {"key1": "value1",
-                    "key2": "value2",
-                    "key3": "value3"}
         update = {"key3": "value3_update",
                   "key4": "value4"}
-        # Create metadata for the snapshot
-        body = self.client.create_snapshot_metadata(
-            self.snapshot_id, metadata)['metadata']
-        # Get the metadata of the snapshot
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
+        expect = {"key4": "value4"}
+        # Create metadata
+        body = self.snapshots_client.create_snapshot_metadata(
+            self.snapshot['id'], metadata)['metadata']
 
-        # Update metadata item
-        body = self.client.update_snapshot_metadata(
-            self.snapshot_id, metadata=update)['metadata']
         # Get the metadata of the snapshot
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
-        self.assertEqual(update, body)
+        body = self.snapshots_client.show_snapshot_metadata(
+            self.snapshot['id'])['metadata']
+        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()),
+                        'Create snapshot metadata failed')
+
+        # Update metadata
+        body = self.snapshots_client.update_snapshot_metadata(
+            self.snapshot['id'], metadata=update)['metadata']
+        body = self.snapshots_client.show_snapshot_metadata(
+            self.snapshot['id'])['metadata']
+        self.assertEqual(update, body, 'Update snapshot metadata failed')
+
+        # Delete one item metadata of the snapshot
+        self.snapshots_client.delete_snapshot_metadata_item(
+            self.snapshot['id'], "key3")
+        body = self.snapshots_client.show_snapshot_metadata(
+            self.snapshot['id'])['metadata']
+        self.assertThat(body.items(), matchers.ContainsAll(expect.items()),
+                        'Delete one item metadata of the snapshot failed')
+        self.assertNotIn("key3", body)
 
     @test.idempotent_id('e8ff85c5-8f97-477f-806a-3ac364a949ed')
     def test_update_snapshot_metadata_item(self):
@@ -106,18 +89,18 @@
                   "key2": "value2",
                   "key3": "value3_update"}
         # Create metadata for the snapshot
-        body = self.client.create_snapshot_metadata(
-            self.snapshot_id, metadata)['metadata']
+        body = self.snapshots_client.create_snapshot_metadata(
+            self.snapshot['id'], metadata)['metadata']
         # Get the metadata of the snapshot
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
+        body = self.snapshots_client.show_snapshot_metadata(
+            self.snapshot['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
         # Update metadata item
-        body = self.client.update_snapshot_metadata_item(
-            self.snapshot_id, "key3", meta=update_item)['meta']
+        body = self.snapshots_client.update_snapshot_metadata_item(
+            self.snapshot['id'], "key3", meta=update_item)['meta']
         # Get the metadata of the snapshot
-        body = self.client.show_snapshot_metadata(
-            self.snapshot_id)['metadata']
+        body = self.snapshots_client.show_snapshot_metadata(
+            self.snapshot['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
 
 
diff --git a/tempest/api/volume/test_volume_absolute_limits.py b/tempest/api/volume/test_volume_absolute_limits.py
new file mode 100644
index 0000000..bc7694a
--- /dev/null
+++ b/tempest/api/volume/test_volume_absolute_limits.py
@@ -0,0 +1,49 @@
+# 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.
+
+from tempest.api.volume import base
+from tempest import config
+from tempest import test
+
+
+CONF = config.CONF
+
+
+class AbsoluteLimitsV2Tests(base.BaseVolumeTest):
+
+    @classmethod
+    def resource_setup(cls):
+        super(AbsoluteLimitsV2Tests, cls).resource_setup()
+        # Create a shared volume for tests
+        cls.volume = cls.create_volume()
+
+    @test.idempotent_id('8e943f53-e9d6-4272-b2e9-adcf2f7c29ad')
+    def test_get_volume_absolute_limits(self):
+        # get volume limit for a tenant
+        absolute_limits = \
+            self.volume_limits_client.show_limits(
+            )['limits']['absolute']
+
+        # verify volume limits and defaults per tenants
+        self.assertEqual(absolute_limits['totalGigabytesUsed'],
+                         CONF.volume.volume_size)
+        self.assertEqual(absolute_limits['totalVolumesUsed'], 1)
+        self.assertEqual(absolute_limits['totalSnapshotsUsed'], 0)
+        self.assertEqual(absolute_limits['totalBackupsUsed'], 0)
+        self.assertEqual(absolute_limits['totalBackupGigabytesUsed'], 0)
+
+
+class AbsoluteLimitsV1Tests(AbsoluteLimitsV2Tests):
+    _api_version = 1
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index ee1744d..c125bb8 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -33,52 +33,39 @@
         super(VolumesV2MetadataTest, self).tearDown()
 
     @test.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
-    def test_create_get_delete_volume_metadata(self):
+    def test_crud_volume_metadata(self):
         # Create metadata for the volume
         metadata = {"key1": "value1",
                     "key2": "value2",
                     "key3": "value3",
                     "key4": "<value&special_chars>"}
+        update = {"key4": "value4",
+                  "key1": "value1_update"}
+        expected = {"key4": "value4"}
 
         body = self.volumes_client.create_volume_metadata(self.volume['id'],
                                                           metadata)['metadata']
         # Get the metadata of the volume
         body = self.volumes_client.show_volume_metadata(
             self.volume['id'])['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
+        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()),
+                        'Create metadata for the volume failed')
+
+        # Update metadata
+        body = self.volumes_client.update_volume_metadata(
+            self.volume['id'], update)['metadata']
+        body = self.volumes_client.show_volume_metadata(
+            self.volume['id'])['metadata']
+        self.assertEqual(update, body, 'Update metadata failed')
+
         # Delete one item metadata of the volume
         self.volumes_client.delete_volume_metadata_item(
             self.volume['id'], "key1")
         body = self.volumes_client.show_volume_metadata(
             self.volume['id'])['metadata']
         self.assertNotIn("key1", body)
-        del metadata["key1"]
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
-
-    @test.idempotent_id('774d2918-9beb-4f30-b3d1-2a4e8179ec0a')
-    def test_update_volume_metadata(self):
-        # Update metadata for the volume
-        metadata = {"key1": "value1",
-                    "key2": "value2",
-                    "key3": "value3"}
-
-        update = {"key4": "value4",
-                  "key1": "value1_update"}
-
-        # Create metadata for the volume
-        body = self.volumes_client.create_volume_metadata(
-            self.volume['id'], metadata)['metadata']
-        # Get the metadata of the volume
-        body = self.volumes_client.show_volume_metadata(
-            self.volume['id'])['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
-        # Update metadata
-        body = self.volumes_client.update_volume_metadata(
-            self.volume['id'], update)['metadata']
-        # Get the metadata of the volume
-        body = self.volumes_client.show_volume_metadata(
-            self.volume['id'])['metadata']
-        self.assertEqual(update, body)
+        self.assertThat(body.items(), matchers.ContainsAll(expected.items()),
+                        'Delete one item metadata of the volume failed')
 
     @test.idempotent_id('862261c5-8df4-475a-8c21-946e50e36a20')
     def test_update_volume_metadata_item(self):
@@ -93,7 +80,8 @@
         # Create metadata for the volume
         body = self.volumes_client.create_volume_metadata(
             self.volume['id'], metadata)['metadata']
-        self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
+        self.assertThat(body.items(),
+                        matchers.ContainsAll(metadata.items()))
         # Update metadata item
         body = self.volumes_client.update_volume_metadata_item(
             self.volume['id'], "key3", update_item)['meta']
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 737ce5e..d8d6b9a 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -12,7 +12,6 @@
 #    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 testtools
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
@@ -67,8 +66,6 @@
                                        self.volume['id'], 'available')
 
     @test.idempotent_id('63e21b4c-0a0c-41f6-bfc3-7c2816815599')
-    @testtools.skipUnless(CONF.volume_feature_enabled.bootable,
-                          'Update bootable status of a volume is not enabled.')
     def test_volume_bootable(self):
         # Verify that a volume bootable flag is retrieved
         for bool_bootable in [True, False]:
@@ -77,8 +74,11 @@
             fetched_volume = self.client.show_volume(
                 self.volume['id'])['volume']
             # Get Volume information
-            bool_flag = self._is_true(fetched_volume['bootable'])
-            self.assertEqual(bool_bootable, bool_flag)
+            # NOTE(masayukig): 'bootable' is "true" or "false" in the current
+            # cinder implementation. So we need to cast boolean values to str
+            # and make it lower to compare here.
+            self.assertEqual(str(bool_bootable).lower(),
+                             fetched_volume['bootable'])
 
     @test.idempotent_id('9516a2c8-9135-488c-8dd6-5677a7e5f371')
     @test.services('compute')
@@ -139,9 +139,6 @@
         body = self.client.show_volume(self.volume['id'])['volume']
         self.assertIn('available', body['status'])
 
-    def _is_true(self, val):
-        return val in ['true', 'True', True]
-
     @test.idempotent_id('fff74e1e-5bd3-4b33-9ea9-24c103bc3f59')
     def test_volume_readonly_update(self):
         for readonly in [True, False]:
@@ -151,8 +148,11 @@
             # Get Volume information
             fetched_volume = self.client.show_volume(
                 self.volume['id'])['volume']
-            bool_flag = self._is_true(fetched_volume['metadata']['readonly'])
-            self.assertEqual(readonly, bool_flag)
+            # NOTE(masayukig): 'readonly' is "True" or "False" in the current
+            # cinder implementation. So we need to cast boolean values to str
+            # to compare here.
+            self.assertEqual(str(readonly),
+                             fetched_volume['metadata']['readonly'])
 
 
 class VolumesV1ActionsTest(VolumesV2ActionsTest):
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 141336f..0091027 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -38,20 +38,18 @@
                         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'])
+        description = data_utils.rand_name("volume-backup-description")
+        backup = self.create_backup(volume_id=volume['id'],
+                                    name=backup_name,
+                                    description=description)
         self.assertEqual(backup_name, backup['name'])
         waiters.wait_for_volume_status(self.volumes_client,
                                        volume['id'], 'available')
-        waiters.wait_for_backup_status(self.backups_client,
-                                       backup['id'], 'available')
 
         # Get a given backup
         backup = self.backups_client.show_backup(backup['id'])['backup']
         self.assertEqual(backup_name, backup['name'])
+        self.assertEqual(description, backup['description'])
 
         # Get all backups with detail
         backups = self.backups_client.list_backups(
@@ -97,12 +95,8 @@
         # Create backup using force flag
         backup_name = data_utils.rand_name(
             self.__class__.__name__ + '-Backup')
-        backup = self.backups_client.create_backup(
-            volume_id=volume['id'],
-            name=backup_name, force=True)['backup']
-        self.addCleanup(self.backups_client.delete_backup, backup['id'])
-        waiters.wait_for_backup_status(self.backups_client,
-                                       backup['id'], 'available')
+        backup = self.create_backup(volume_id=volume['id'],
+                                    name=backup_name, force=True)
         self.assertEqual(backup_name, backup['name'])
 
 
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index 7529dc2..2cedb4e 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -21,11 +21,11 @@
 CONF = config.CONF
 
 
-class VolumesCloneTest(base.BaseVolumeTest):
+class VolumesV2CloneTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesCloneTest, cls).skip_checks()
+        super(VolumesV2CloneTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
@@ -45,6 +45,22 @@
         self.assertEqual(volume['source_volid'], src_vol['id'])
         self.assertEqual(int(volume['size']), src_size + 1)
 
+    @test.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
+    def test_create_from_bootable_volume(self):
+        # Create volume from image
+        img_uuid = CONF.compute.image_ref
+        src_vol = self.create_volume(imageRef=img_uuid)
 
-class VolumesV1CloneTest(VolumesCloneTest):
+        # Create a volume from the bootable volume
+        cloned_vol = self.create_volume(source_volid=src_vol['id'])
+        cloned_vol_details = self.volumes_client.show_volume(
+            cloned_vol['id'])['volume']
+
+        # Verify cloned volume creation as expected
+        self.assertEqual('true', cloned_vol_details['bootable'])
+        self.assertEqual(src_vol['id'], cloned_vol_details['source_volid'])
+        self.assertEqual(src_vol['size'], cloned_vol_details['size'])
+
+
+class VolumesV1CloneTest(VolumesV2CloneTest):
     _api_version = 1
diff --git a/tempest/api/volume/test_volumes_clone_negative.py b/tempest/api/volume/test_volumes_clone_negative.py
index d1bedb4..5c54e1e 100644
--- a/tempest/api/volume/test_volumes_clone_negative.py
+++ b/tempest/api/volume/test_volumes_clone_negative.py
@@ -22,11 +22,11 @@
 CONF = config.CONF
 
 
-class VolumesCloneTest(base.BaseVolumeTest):
+class VolumesV2CloneNegativeTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesCloneTest, cls).skip_checks()
+        super(VolumesV2CloneNegativeTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
@@ -44,5 +44,5 @@
                           source_volid=src_vol['id'])
 
 
-class VolumesV1CloneTest(VolumesCloneTest):
+class VolumesV1CloneNegativeTest(VolumesV2CloneNegativeTest):
     _api_version = 1
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 7aea1c4..c3d6dbb 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -20,20 +20,16 @@
 
 class VolumesV2ExtendTest(base.BaseVolumeTest):
 
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV2ExtendTest, cls).setup_clients()
-        cls.client = cls.volumes_client
-
     @test.idempotent_id('9a36df71-a257-43a5-9555-dc7c88e66e0e')
     def test_volume_extend(self):
         # Extend Volume Test.
         self.volume = self.create_volume()
         extend_size = int(self.volume['size']) + 1
-        self.client.extend_volume(self.volume['id'], new_size=extend_size)
-        waiters.wait_for_volume_status(self.client,
+        self.volumes_client.extend_volume(self.volume['id'],
+                                          new_size=extend_size)
+        waiters.wait_for_volume_status(self.volumes_client,
                                        self.volume['id'], 'available')
-        volume = self.client.show_volume(self.volume['id'])['volume']
+        volume = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertEqual(int(volume['size']), extend_size)
 
 
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 07f799b..65e461c 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -27,39 +27,31 @@
 
 class VolumesV2GetTest(base.BaseVolumeTest):
 
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV2GetTest, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesV2GetTest, cls).resource_setup()
-
-        cls.name_field = cls.special_fields['name_field']
-        cls.descrip_field = cls.special_fields['descrip_field']
-
     def _volume_create_get_update_delete(self, **kwargs):
+        name_field = self.special_fields['name_field']
+        descrip_field = self.special_fields['descrip_field']
+
         # Create a volume, Get it's details and Delete the volume
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'Test'}
         # Create a volume
-        kwargs[self.name_field] = v_name
+        kwargs[name_field] = v_name
         kwargs['metadata'] = metadata
-        volume = self.client.create_volume(**kwargs)['volume']
+        volume = self.volumes_client.create_volume(**kwargs)['volume']
         self.assertIn('id', volume)
-        self.addCleanup(self.delete_volume, self.client, volume['id'])
-        waiters.wait_for_volume_status(self.client, volume['id'], 'available')
-        self.assertIn(self.name_field, volume)
-        self.assertEqual(volume[self.name_field], v_name,
+        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
+        waiters.wait_for_volume_status(self.volumes_client, volume['id'],
+                                       'available')
+        self.assertIn(name_field, volume)
+        self.assertEqual(volume[name_field], v_name,
                          "The created volume name is not equal "
                          "to the requested name")
-        self.assertTrue(volume['id'] is not None,
-                        "Field volume id is empty or not found.")
+
         # Get Volume information
-        fetched_volume = self.client.show_volume(volume['id'])['volume']
+        fetched_volume = self.volumes_client.show_volume(
+            volume['id'])['volume']
         self.assertEqual(v_name,
-                         fetched_volume[self.name_field],
+                         fetched_volume[name_field],
                          'The fetched Volume name is different '
                          'from the created Volume')
         self.assertEqual(volume['id'],
@@ -73,53 +65,56 @@
 
         if 'imageRef' in kwargs:
             self.assertEqual('true', fetched_volume['bootable'])
-        if 'imageRef' not in kwargs:
+        else:
             self.assertEqual('false', fetched_volume['bootable'])
 
         # Update Volume
         # Test volume update when display_name is same with original value
-        params = {self.name_field: v_name}
-        self.client.update_volume(volume['id'], **params)
+        params = {name_field: v_name}
+        self.volumes_client.update_volume(volume['id'], **params)
         # Test volume update when display_name is new
         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}
-        update_volume = self.client.update_volume(
+        params = {name_field: new_v_name,
+                  descrip_field: new_desc}
+        update_volume = self.volumes_client.update_volume(
             volume['id'], **params)['volume']
         # Assert response body for update_volume method
-        self.assertEqual(new_v_name, update_volume[self.name_field])
-        self.assertEqual(new_desc, update_volume[self.descrip_field])
+        self.assertEqual(new_v_name, update_volume[name_field])
+        self.assertEqual(new_desc, update_volume[descrip_field])
         # Assert response body for show_volume method
-        updated_volume = self.client.show_volume(volume['id'])['volume']
+        updated_volume = self.volumes_client.show_volume(
+            volume['id'])['volume']
         self.assertEqual(volume['id'], updated_volume['id'])
-        self.assertEqual(new_v_name, updated_volume[self.name_field])
-        self.assertEqual(new_desc, updated_volume[self.descrip_field])
+        self.assertEqual(new_v_name, updated_volume[name_field])
+        self.assertEqual(new_desc, updated_volume[descrip_field])
         self.assertThat(updated_volume['metadata'].items(),
                         matchers.ContainsAll(metadata.items()),
                         'The fetched Volume metadata misses data '
                         'from the created Volume')
+
         # Test volume create when display_name is none and display_description
         # contains specific characters,
         # then test volume update if display_name is duplicated
         new_v_desc = data_utils.rand_name('@#$%^* description')
-        params = {self.descrip_field: new_v_desc,
+        params = {descrip_field: new_v_desc,
                   'availability_zone': volume['availability_zone'],
                   'size': CONF.volume.volume_size}
-        new_volume = self.client.create_volume(**params)['volume']
+        new_volume = self.volumes_client.create_volume(**params)['volume']
         self.assertIn('id', new_volume)
-        self.addCleanup(self.delete_volume, self.client, new_volume['id'])
-        waiters.wait_for_volume_status(self.client,
+        self.addCleanup(self.delete_volume, self.volumes_client,
+                        new_volume['id'])
+        waiters.wait_for_volume_status(self.volumes_client,
                                        new_volume['id'], 'available')
 
-        params = {self.name_field: volume[self.name_field],
-                  self.descrip_field: volume[self.descrip_field]}
-        self.client.update_volume(new_volume['id'], **params)
+        params = {name_field: volume[name_field],
+                  descrip_field: volume[descrip_field]}
+        self.volumes_client.update_volume(new_volume['id'], **params)
 
         if 'imageRef' in kwargs:
             self.assertEqual('true', updated_volume['bootable'])
-        if 'imageRef' not in kwargs:
+        else:
             self.assertEqual('false', updated_volume['bootable'])
 
     @test.attr(type='smoke')
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 40793ec..030ea6c 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -55,11 +55,6 @@
                              [str_vol(v) for v in fetched_list]))
 
     @classmethod
-    def setup_clients(cls):
-        super(VolumesV2ListTestJSON, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @classmethod
     def resource_setup(cls):
         super(VolumesV2ListTestJSON, cls).resource_setup()
         cls.name = cls.VOLUME_FIELDS[1]
@@ -68,16 +63,17 @@
         cls.metadata = {'Type': 'work'}
         for i in range(3):
             volume = cls.create_volume(metadata=cls.metadata)
-            volume = cls.client.show_volume(volume['id'])['volume']
+            volume = cls.volumes_client.show_volume(volume['id'])['volume']
             cls.volume_list.append(volume)
 
     def _list_by_param_value_and_assert(self, params, with_detail=False):
         """list or list_details with given params and validates result"""
         if with_detail:
             fetched_vol_list = \
-                self.client.list_volumes(detail=True, params=params)['volumes']
+                self.volumes_client.list_volumes(detail=True,
+                                                 params=params)['volumes']
         else:
-            fetched_vol_list = self.client.list_volumes(
+            fetched_vol_list = self.volumes_client.list_volumes(
                 params=params)['volumes']
 
         # Validating params of fetched volumes
@@ -103,7 +99,7 @@
     def test_volume_list(self):
         # Get a list of Volumes
         # Fetch all volumes
-        fetched_list = self.client.list_volumes()['volumes']
+        fetched_list = self.volumes_client.list_volumes()['volumes']
         self.assertVolumesIn(fetched_list, self.volume_list,
                              fields=self.VOLUME_FIELDS)
 
@@ -111,14 +107,15 @@
     def test_volume_list_with_details(self):
         # Get a list of Volumes with details
         # Fetch all Volumes
-        fetched_list = self.client.list_volumes(detail=True)['volumes']
+        fetched_list = self.volumes_client.list_volumes(detail=True)['volumes']
         self.assertVolumesIn(fetched_list, self.volume_list)
 
     @test.idempotent_id('a28e8da4-0b56-472f-87a8-0f4d3f819c02')
     def test_volume_list_by_name(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {self.name: volume[self.name]}
-        fetched_vol = self.client.list_volumes(params=params)['volumes']
+        fetched_vol = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self.assertEqual(1, len(fetched_vol), str(fetched_vol))
         self.assertEqual(fetched_vol[0][self.name],
                          volume[self.name])
@@ -127,7 +124,7 @@
     def test_volume_list_details_by_name(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {self.name: volume[self.name]}
-        fetched_vol = self.client.list_volumes(
+        fetched_vol = self.volumes_client.list_volumes(
             detail=True, params=params)['volumes']
         self.assertEqual(1, len(fetched_vol), str(fetched_vol))
         self.assertEqual(fetched_vol[0][self.name],
@@ -136,7 +133,8 @@
     @test.idempotent_id('39654e13-734c-4dab-95ce-7613bf8407ce')
     def test_volumes_list_by_status(self):
         params = {'status': 'available'}
-        fetched_list = self.client.list_volumes(params=params)['volumes']
+        fetched_list = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self._list_by_param_value_and_assert(params)
         self.assertVolumesIn(fetched_list, self.volume_list,
                              fields=self.VOLUME_FIELDS)
@@ -144,7 +142,7 @@
     @test.idempotent_id('2943f712-71ec-482a-bf49-d5ca06216b9f')
     def test_volumes_list_details_by_status(self):
         params = {'status': 'available'}
-        fetched_list = self.client.list_volumes(
+        fetched_list = self.volumes_client.list_volumes(
             detail=True, params=params)['volumes']
         for volume in fetched_list:
             self.assertEqual('available', volume['status'])
@@ -158,7 +156,8 @@
         in volume_list are not a bootable volume.
         """
         params = {'bootable': 'false'}
-        fetched_list = self.client.list_volumes(params=params)['volumes']
+        fetched_list = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self._list_by_param_value_and_assert(params)
         self.assertVolumesIn(fetched_list, self.volume_list,
                              fields=self.VOLUME_FIELDS)
@@ -166,7 +165,7 @@
     @test.idempotent_id('2016a939-72ec-482a-bf49-d5ca06216b9f')
     def test_volumes_list_details_by_bootable(self):
         params = {'bootable': 'false'}
-        fetched_list = self.client.list_volumes(
+        fetched_list = self.volumes_client.list_volumes(
             detail=True, params=params)['volumes']
         for volume in fetched_list:
             self.assertEqual('false', volume['bootable'])
@@ -177,7 +176,8 @@
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
-        fetched_list = self.client.list_volumes(params=params)['volumes']
+        fetched_list = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self._list_by_param_value_and_assert(params)
         self.assertVolumesIn(fetched_list, self.volume_list,
                              fields=self.VOLUME_FIELDS)
@@ -187,7 +187,7 @@
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
-        fetched_list = self.client.list_volumes(
+        fetched_list = self.volumes_client.list_volumes(
             detail=True, params=params)['volumes']
         for volume in fetched_list:
             self.assertEqual(zone, volume['availability_zone'])
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index fda0dda..c45ace6 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -22,11 +22,6 @@
 class VolumesV2NegativeTest(base.BaseVolumeTest):
 
     @classmethod
-    def setup_clients(cls):
-        super(VolumesV2NegativeTest, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @classmethod
     def resource_setup(cls):
         super(VolumesV2NegativeTest, cls).resource_setup()
 
@@ -40,14 +35,14 @@
     @test.idempotent_id('f131c586-9448-44a4-a8b0-54ca838aa43e')
     def test_volume_get_nonexistent_volume_id(self):
         # Should not be able to get a non-existent volume
-        self.assertRaises(lib_exc.NotFound, self.client.show_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @test.idempotent_id('555efa6e-efcd-44ef-8a3b-4a7ca4837a29')
     def test_volume_delete_nonexistent_volume_id(self):
         # Should not be able to delete a non-existent Volume
-        self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
@@ -57,17 +52,19 @@
         # in request
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
-    def test_create_volume_with_out_passing_size(self):
+    def test_create_volume_without_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
@@ -76,7 +73,8 @@
         # Should not be able to create volume with size zero
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
@@ -85,7 +83,8 @@
         # Should not be able to create volume with size negative
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.create_volume,
                           size='-1', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
@@ -94,7 +93,7 @@
         # Should not be able to create volume with non-existent volume type
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.create_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', volume_type=data_utils.rand_uuid(),
                           display_name=v_name, metadata=metadata)
 
@@ -104,7 +103,7 @@
         # Should not be able to create volume with non-existent snapshot
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.create_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', snapshot_id=data_utils.rand_uuid(),
                           display_name=v_name, metadata=metadata)
 
@@ -114,7 +113,7 @@
         # Should not be able to create volume with non-existent source volume
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.create_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', source_volid=data_utils.rand_uuid(),
                           display_name=v_name, metadata=metadata)
 
@@ -123,7 +122,7 @@
     def test_update_volume_with_nonexistent_volume_id(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.update_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id=data_utils.rand_uuid(),
                           display_name=v_name,
                           metadata=metadata)
@@ -133,7 +132,7 @@
     def test_update_volume_with_invalid_volume_id(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.update_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id='#$%%&^&^', display_name=v_name,
                           metadata=metadata)
 
@@ -142,7 +141,7 @@
     def test_update_volume_with_empty_volume_id(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
-        self.assertRaises(lib_exc.NotFound, self.client.update_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id='', display_name=v_name,
                           metadata=metadata)
 
@@ -150,27 +149,29 @@
     @test.idempotent_id('30799cfd-7ee4-446c-b66c-45b383ed211b')
     def test_get_invalid_volume_id(self):
         # Should not be able to get volume with invalid id
-        self.assertRaises(lib_exc.NotFound, self.client.show_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           '#$%%&^&^')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('c6c3db06-29ad-4e91-beb0-2ab195fe49e3')
     def test_get_volume_without_passing_volume_id(self):
         # Should not be able to get volume when empty ID is passed
-        self.assertRaises(lib_exc.NotFound, self.client.show_volume, '')
+        self.assertRaises(lib_exc.NotFound,
+                          self.volumes_client.show_volume, '')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('1f035827-7c32-4019-9240-b4ec2dbd9dfd')
     def test_delete_invalid_volume_id(self):
         # Should not be able to delete volume when invalid ID is passed
-        self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           '!@#$%^&*()')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('441a1550-5d44-4b30-af0f-a6d402f52026')
     def test_delete_volume_without_passing_volume_id(self):
         # Should not be able to delete volume when empty ID is passed
-        self.assertRaises(lib_exc.NotFound, self.client.delete_volume, '')
+        self.assertRaises(lib_exc.NotFound,
+                          self.volumes_client.delete_volume, '')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
@@ -179,7 +180,7 @@
         server = self.create_server(wait_until='ACTIVE')
 
         self.assertRaises(lib_exc.NotFound,
-                          self.client.attach_volume,
+                          self.volumes_client.attach_volume,
                           data_utils.rand_uuid(),
                           instance_uuid=server['id'],
                           mountpoint=self.mountpoint)
@@ -188,7 +189,7 @@
     @test.idempotent_id('9f9c24e4-011d-46b5-b992-952140ce237a')
     def test_detach_volumes_with_invalid_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
-                          self.client.detach_volume,
+                          self.volumes_client.detach_volume,
                           'xxx')
 
     @test.attr(type=['negative'])
@@ -196,7 +197,8 @@
     def test_volume_extend_with_size_smaller_than_original_size(self):
         # Extend volume with smaller size than original size.
         extend_size = 0
-        self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
     @test.attr(type=['negative'])
@@ -204,7 +206,8 @@
     def test_volume_extend_with_non_number_size(self):
         # Extend volume when size is non number.
         extend_size = 'abc'
-        self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
     @test.attr(type=['negative'])
@@ -212,7 +215,8 @@
     def test_volume_extend_with_None_size(self):
         # Extend volume with None size.
         extend_size = None
-        self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
+        self.assertRaises(lib_exc.BadRequest,
+                          self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
     @test.attr(type=['negative'])
@@ -220,7 +224,7 @@
     def test_volume_extend_with_nonexistent_volume_id(self):
         # Extend volume size when volume is nonexistent.
         extend_size = int(self.volume['size']) + 1
-        self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           data_utils.rand_uuid(), new_size=extend_size)
 
     @test.attr(type=['negative'])
@@ -228,41 +232,42 @@
     def test_volume_extend_without_passing_volume_id(self):
         # Extend volume size when passing volume id is None.
         extend_size = int(self.volume['size']) + 1
-        self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
+        self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           None, new_size=extend_size)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('ac6084c0-0546-45f9-b284-38a367e0e0e2')
     def test_reserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
-                          self.client.reserve_volume,
+                          self.volumes_client.reserve_volume,
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @test.idempotent_id('eb467654-3dc1-4a72-9b46-47c29d22654c')
     def test_unreserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
-                          self.client.unreserve_volume,
+                          self.volumes_client.unreserve_volume,
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @test.idempotent_id('449c4ed2-ecdd-47bb-98dc-072aeccf158c')
     def test_reserve_volume_with_negative_volume_status(self):
         # Mark volume as reserved.
-        self.client.reserve_volume(self.volume['id'])
+        self.volumes_client.reserve_volume(self.volume['id'])
         # Mark volume which is marked as reserved before
         self.assertRaises(lib_exc.BadRequest,
-                          self.client.reserve_volume,
+                          self.volumes_client.reserve_volume,
                           self.volume['id'])
         # Unmark volume as reserved.
-        self.client.unreserve_volume(self.volume['id'])
+        self.volumes_client.unreserve_volume(self.volume['id'])
 
     @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(self.__class__.__name__ + '-Volume')
         params = {self.name_field: v_name}
-        fetched_volume = self.client.list_volumes(params=params)['volumes']
+        fetched_volume = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
     @test.attr(type=['negative'])
@@ -271,14 +276,16 @@
         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']
+            self.volumes_client.list_volumes(
+                detail=True, params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
     @test.attr(type=['negative'])
     @test.idempotent_id('143b279b-7522-466b-81be-34a87d564a7c')
     def test_list_volumes_with_invalid_status(self):
         params = {'status': 'null'}
-        fetched_volume = self.client.list_volumes(params=params)['volumes']
+        fetched_volume = self.volumes_client.list_volumes(
+            params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
     @test.attr(type=['negative'])
@@ -286,7 +293,8 @@
     def test_list_volumes_detail_with_invalid_status(self):
         params = {'status': 'null'}
         fetched_volume = \
-            self.client.list_volumes(detail=True, params=params)['volumes']
+            self.volumes_client.list_volumes(detail=True,
+                                             params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
 
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 7be31d1..3c7a2c8 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -12,7 +12,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
 
@@ -46,27 +45,57 @@
         # Create a snapshot when volume status is in-use
         # Create a test instance
         server = self.create_server(wait_until='ACTIVE')
-        self.servers_client.attach_volume(
-            server['id'], volumeId=self.volume_origin['id'],
-            device='/dev/%s' % CONF.compute.volume_device_name)
-        waiters.wait_for_volume_status(self.volumes_client,
-                                       self.volume_origin['id'], 'in-use')
-        self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
-                        self.volume_origin['id'], 'available')
-        self.addCleanup(self.servers_client.detach_volume, server['id'],
-                        self.volume_origin['id'])
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
         # Snapshot a volume even if it's attached to an instance
         snapshot = self.create_snapshot(self.volume_origin['id'],
                                         force=True)
         # Delete the snapshot
         self.cleanup_snapshot(snapshot)
 
+    @test.idempotent_id('8567b54c-4455-446d-a1cf-651ddeaa3ff2')
+    @test.services('compute')
+    def test_snapshot_delete_with_volume_in_use(self):
+        # Create a test instance
+        server = self.create_server(wait_until='ACTIVE')
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
+        # Snapshot a volume attached to an instance
+        snapshot1 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot2 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot3 = self.create_snapshot(self.volume_origin['id'], force=True)
+
+        # Delete the snapshots. Some snapshot implementations can take
+        # different paths according to order they are deleted.
+        self.cleanup_snapshot(snapshot1)
+        self.cleanup_snapshot(snapshot3)
+        self.cleanup_snapshot(snapshot2)
+
+    @test.idempotent_id('5210a1de-85a0-11e6-bb21-641c676a5d61')
+    @test.services('compute')
+    def test_snapshot_create_offline_delete_online(self):
+
+        # Create a snapshot while it is not attached
+        snapshot1 = self.create_snapshot(self.volume_origin['id'])
+
+        # Create a server and attach it
+        server = self.create_server(wait_until='ACTIVE')
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
+        # Now that the volume is attached, create another snapshots
+        snapshot2 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot3 = self.create_snapshot(self.volume_origin['id'], force=True)
+
+        # Delete the snapshots. Some snapshot implementations can take
+        # different paths according to order they are deleted.
+        self.cleanup_snapshot(snapshot3)
+        self.cleanup_snapshot(snapshot1)
+        self.cleanup_snapshot(snapshot2)
+
     @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(self.__class__.__name__ + '-snap')
-        params = {self.name_field: s_name}
-        snapshot = self.create_snapshot(self.volume_origin['id'], **params)
+        snapshot = self.create_snapshot(self.volume_origin['id'])
 
         # Get the snap and check for some of its details
         snap_get = self.snapshots_client.show_snapshot(
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 60a35b0..fb8c65d 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -33,11 +33,6 @@
     """
 
     @classmethod
-    def setup_clients(cls):
-        super(VolumesV2ListTestJSON, cls).setup_clients()
-        cls.client = cls.volumes_client
-
-    @classmethod
     def resource_setup(cls):
         super(VolumesV2ListTestJSON, cls).resource_setup()
 
@@ -45,7 +40,7 @@
         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']
+        existing_volumes = cls.volumes_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)
@@ -63,7 +58,7 @@
                       'sort_dir': sort_dir,
                       'sort_key': sort_key
                       }
-            fetched_volume = self.client.list_volumes(
+            fetched_volume = self.volumes_client.list_volumes(
                 detail=True, params=params)['volumes']
             self.assertEqual(limit, len(fetched_volume),
                              "The count of volumes is %s, expected:%s " %
@@ -73,11 +68,13 @@
             val0 = fetched_volume[0][sort_key]
             val1 = fetched_volume[1][sort_key]
             if sort_dir == 'asc':
-                self.assertTrue(val0 < val1,
-                                "%s < %s" % (val0, val1))
+                self.assertLess(val0, val1,
+                                "list is not in asc order with sort_key: %s."
+                                " %s" % (sort_key, fetched_volume))
             elif sort_dir == 'desc':
-                self.assertTrue(val0 > val1,
-                                "%s > %s" % (val0, val1))
+                self.assertGreater(val0, val1,
+                                   "list is not in desc order with sort_key: "
+                                   "%s. %s" % (sort_key, fetched_volume))
 
         _list_details_with_multiple_params()
         _list_details_with_multiple_params(sort_dir='desc')
@@ -190,8 +187,8 @@
         params = {'marker': random_volume}
 
         # Running volume list using marker parameter
-        vol_with_marker = self.client.list_volumes(detail=True,
-                                                   params=params)['volumes']
+        vol_with_marker = self.volumes_client.list_volumes(
+            detail=True, params=params)['volumes']
 
         # Fetching the index of the random volume from volume_id_list
         index_marker = self.volume_id_list.index(random_volume)
diff --git a/tempest/api/volume/v3/base.py b/tempest/api/volume/v3/base.py
index c31c83c..31fc1eb 100644
--- a/tempest/api/volume/v3/base.py
+++ b/tempest/api/volume/v3/base.py
@@ -44,7 +44,7 @@
     @classmethod
     def setup_clients(cls):
         super(VolumesV3Test, cls).setup_clients()
-        cls.messages_client = cls.os.volume_messages_client
+        cls.messages_client = cls.os.volume_v3_messages_client
 
     def setUp(self):
         super(VolumesV3Test, self).setUp()
@@ -52,7 +52,8 @@
             self.request_microversion))
 
 
-class VolumesV3AdminTest(VolumesV3Test):
+class VolumesV3AdminTest(VolumesV3Test,
+                         base.BaseVolumeAdminTest):
     """Base test case class for all v3 Volume Admin API tests."""
 
     credentials = ['primary', 'admin']
@@ -60,5 +61,5 @@
     @classmethod
     def setup_clients(cls):
         super(VolumesV3AdminTest, cls).setup_clients()
-        cls.admin_messages_client = cls.os_adm.volume_messages_client
+        cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
         cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
diff --git a/tempest/clients.py b/tempest/clients.py
index be6bc02..1ab7cfe 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -17,17 +17,13 @@
 
 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 clients
-from tempest.services import baremetal
 from tempest.services import identity
 from tempest.services import object_storage
 from tempest.services import orchestration
-from tempest.services import volume
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
@@ -38,14 +34,6 @@
 
     default_params = config.service_client_config()
 
-    # TODO(andreaf) This is only used by baremetal clients,
-    # and should be removed once they are out of Tempest
-    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)
-
     def __init__(self, credentials, service=None, scope='project'):
         """Initialization of Manager class.
 
@@ -69,12 +57,6 @@
         self._set_image_clients()
         self._set_network_clients()
 
-        self.baremetal_client = baremetal.BaremetalClient(
-            self.auth_provider,
-            CONF.baremetal.catalog_type,
-            CONF.identity.region,
-            endpoint_type=CONF.baremetal.endpoint_type,
-            **self.default_params_with_timeout_values)
         self.orchestration_client = orchestration.OrchestrationClient(
             self.auth_provider,
             CONF.orchestration.catalog_type,
@@ -83,8 +65,6 @@
             build_interval=CONF.orchestration.build_interval,
             build_timeout=CONF.orchestration.build_timeout,
             **self.default_params)
-        self.negative_client = negative_rest_client.NegativeRestClient(
-            self.auth_provider, service, **self.default_params)
 
     def _prepare_configuration(self):
         """Map values from CONF into Manager parameters
@@ -132,6 +112,7 @@
             self.network.SecurityGroupRulesClient())
         self.security_groups_client = self.network.SecurityGroupsClient()
         self.network_versions_client = self.network.NetworkVersionsClient()
+        self.service_providers_client = self.network.ServiceProvidersClient()
 
     def _set_image_clients(self):
         if CONF.service_available.glance:
@@ -142,6 +123,8 @@
             self.namespaces_client = self.image_v2.NamespacesClient()
             self.resource_types_client = self.image_v2.ResourceTypesClient()
             self.schemas_client = self.image_v2.SchemasClient()
+            self.namespace_properties_client = \
+                self.image_v2.NamespacePropertiesClient()
 
     def _set_compute_clients(self):
         self.agents_client = self.compute.AgentsClient()
@@ -179,7 +162,6 @@
         self.instance_usages_audit_log_client = (
             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.
@@ -277,55 +259,39 @@
                 raise lib_exc.InvalidConfiguration(msg)
 
     def _set_volume_clients(self):
-        # Mandatory parameters (always defined)
-        params = self.parameters['volume']
 
-        self.volume_qos_client = volume.v1.QosSpecsClient(self.auth_provider,
-                                                          **params)
-        self.volume_qos_v2_client = volume.v2.QosSpecsClient(
-            self.auth_provider, **params)
-        self.volume_services_client = volume.v1.ServicesClient(
-            self.auth_provider, **params)
-        self.volume_services_v2_client = volume.v2.ServicesClient(
-            self.auth_provider, **params)
-        self.backups_client = volume.v1.BackupsClient(self.auth_provider,
-                                                      **params)
-        self.backups_v2_client = volume.v2.BackupsClient(self.auth_provider,
-                                                         **params)
-        self.encryption_types_client = volume.v1.EncryptionTypesClient(
-            self.auth_provider, **params)
-        self.encryption_types_v2_client = volume.v2.EncryptionTypesClient(
-            self.auth_provider, **params)
-        self.snapshots_client = volume.v1.SnapshotsClient(self.auth_provider,
-                                                          **params)
-        self.snapshots_v2_client = volume.v2.SnapshotsClient(
-            self.auth_provider, **params)
-        self.volumes_client = volume.v1.VolumesClient(self.auth_provider,
-                                                      **params)
-        self.volumes_v2_client = volume.v2.VolumesClient(self.auth_provider,
-                                                         **params)
-        self.volume_messages_client = volume.v3.MessagesClient(
-            self.auth_provider, **params)
-        self.volume_types_client = volume.v1.TypesClient(self.auth_provider,
-                                                         **params)
-        self.volume_types_v2_client = volume.v2.TypesClient(self.auth_provider,
-                                                            **params)
-        self.volume_hosts_client = volume.v1.HostsClient(self.auth_provider,
-                                                         **params)
-        self.volume_hosts_v2_client = volume.v2.HostsClient(self.auth_provider,
-                                                            **params)
-        self.volume_quotas_client = volume.v1.QuotasClient(self.auth_provider,
-                                                           **params)
-        self.volume_quotas_v2_client = volume.v2.QuotasClient(
-            self.auth_provider, **params)
-        self.volumes_extension_client = volume.v1.ExtensionsClient(
-            self.auth_provider, **params)
-        self.volumes_v2_extension_client = volume.v2.ExtensionsClient(
-            self.auth_provider, **params)
+        self.volume_qos_client = self.volume_v1.QosSpecsClient()
+        self.volume_qos_v2_client = self.volume_v2.QosSpecsClient()
+        self.volume_services_client = self.volume_v1.ServicesClient()
+        self.volume_services_v2_client = self.volume_v2.ServicesClient()
+        self.backups_client = self.volume_v1.BackupsClient()
+        self.backups_v2_client = self.volume_v2.BackupsClient()
+        self.encryption_types_client = self.volume_v1.EncryptionTypesClient()
+        self.encryption_types_v2_client = \
+            self.volume_v2.EncryptionTypesClient()
+        self.snapshots_client = self.volume_v1.SnapshotsClient()
+        self.snapshots_v2_client = self.volume_v2.SnapshotsClient()
+        self.volumes_client = self.volume_v1.VolumesClient()
+        self.volumes_v2_client = self.volume_v2.VolumesClient()
+        self.volume_v3_messages_client = self.volume_v3.MessagesClient()
+        self.volume_types_client = self.volume_v1.TypesClient()
+        self.volume_types_v2_client = self.volume_v2.TypesClient()
+        self.volume_hosts_client = self.volume_v1.HostsClient()
+        self.volume_hosts_v2_client = self.volume_v2.HostsClient()
+        self.volume_quotas_client = self.volume_v1.QuotasClient()
+        self.volume_quotas_v2_client = self.volume_v2.QuotasClient()
+        self.volumes_extension_client = self.volume_v1.ExtensionsClient()
+        self.volumes_v2_extension_client = self.volume_v2.ExtensionsClient()
         self.volume_availability_zone_client = \
-            volume.v1.AvailabilityZoneClient(self.auth_provider, **params)
+            self.volume_v1.AvailabilityZoneClient()
         self.volume_v2_availability_zone_client = \
-            volume.v2.AvailabilityZoneClient(self.auth_provider, **params)
+            self.volume_v2.AvailabilityZoneClient()
+        self.volume_limits_client = self.volume_v1.LimitsClient()
+        self.volume_v2_limits_client = self.volume_v2.LimitsClient()
+        self.volume_capabilities_v2_client = \
+            self.volume_v2.CapabilitiesClient()
+        self.volume_scheduler_stats_v2_client = \
+            self.volume_v2.SchedulerStatsClient()
 
     def _set_object_storage_clients(self):
         # Mandatory parameters (always defined)
@@ -333,6 +299,8 @@
 
         self.account_client = object_storage.AccountClient(self.auth_provider,
                                                            **params)
+        self.capabilities_client = object_storage.CapabilitiesClient(
+            self.auth_provider, **params)
         self.container_client = object_storage.ContainerClient(
             self.auth_provider, **params)
         self.object_client = object_storage.ObjectClient(self.auth_provider,
@@ -350,7 +318,7 @@
     # kwargs for auth provider match the common ones used by service clients
     default_params = config.service_client_config()
     if credentials is None:
-        raise exceptions.InvalidCredentials(
+        raise lib_exc.InvalidCredentials(
             'Credentials must be specified')
     auth_provider_class, auth_url = get_auth_provider_class(
         credentials)
diff --git a/tempest/cmd/main.py b/tempest/cmd/main.py
index 641d11c..1090c41 100644
--- a/tempest/cmd/main.py
+++ b/tempest/cmd/main.py
@@ -11,11 +11,11 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import logging
 import sys
 
 from cliff import app
 from cliff import commandmanager
+from oslo_log import log as logging
 from pbr import version
 
 
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 381f3df..0a1881c 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -169,7 +169,7 @@
         'nova': os.extensions_client,
         'cinder': os.volumes_extension_client,
         'neutron': os.network_extensions_client,
-        'swift': os.account_client,
+        'swift': os.capabilities_client,
     }
     # NOTE (e0ne): Use Cinder API v2 by default because v1 is deprecated
     if CONF.volume_feature_enabled.api_v2:
@@ -201,7 +201,7 @@
     if service != 'swift':
         resp = extensions_client.list_extensions()
     else:
-        __, resp = extensions_client.list_extensions()
+        __, resp = extensions_client.list_capabilities()
     # For Nova, Cinder and Neutron we use the alias name rather than the
     # 'name' field because the alias is considered to be the canonical
     # name.
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 318eb10..64543fb 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -169,27 +169,28 @@
     return body, servers
 
 
-def shelve_server(client, server_id, force_shelve_offload=False):
+def shelve_server(servers_client, server_id, force_shelve_offload=False):
     """Common wrapper utility to shelve server.
 
     This method is a common wrapper to make server in 'SHELVED'
     or 'SHELVED_OFFLOADED' state.
 
+    :param servers_clients: Compute servers client instance.
     :param server_id: Server to make in shelve state
     :param force_shelve_offload: Forcefully offload shelve server if it
                                  is configured not to offload server
                                  automatically after offload time.
     """
-    client.shelve_server(server_id)
+    servers_client.shelve_server(server_id)
 
     offload_time = CONF.compute.shelved_offload_time
     if offload_time >= 0:
-        waiters.wait_for_server_status(client, server_id,
+        waiters.wait_for_server_status(servers_client, server_id,
                                        'SHELVED_OFFLOADED',
                                        extra_timeout=offload_time)
     else:
-        waiters.wait_for_server_status(client, server_id, 'SHELVED')
+        waiters.wait_for_server_status(servers_client, server_id, 'SHELVED')
         if force_shelve_offload:
-            client.shelve_offload_server(server_id)
-            waiters.wait_for_server_status(client, server_id,
+            servers_client.shelve_offload_server(server_id)
+            waiters.wait_for_server_status(servers_client, server_id,
                                            'SHELVED_OFFLOADED')
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 5634958..bf8d30e 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -88,7 +88,7 @@
             project_network_mask_bits=CONF.network.project_network_mask_bits,
             public_network_id=CONF.network.public_network_id,
             create_networks=(CONF.auth.create_isolated_networks and not
-                             CONF.baremetal.driver_enabled),
+                             CONF.network.shared_physical_network),
             resource_prefix=CONF.resources_prefix,
             **get_dynamic_provider_params())
     else:
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index b6ff241..8410541 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -85,7 +85,7 @@
                     return NonExistentHeader('x-account-container-count')
                 if 'x-account-object-count' not in actual:
                     return NonExistentHeader('x-account-object-count')
-                if actual['x-account-container-count'] > 0:
+                if int(actual['x-account-container-count']) > 0:
                     acct_header = "x-account-storage-policy-"
                     matched_policy_count = 0
 
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 5c12fd8..2763d16 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -17,7 +17,7 @@
 import six
 
 from tempest import clients
-from tempest.common import cred_client
+from tempest.lib.common import cred_client
 from tempest.lib.common import cred_provider
 from tempest.lib.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
diff --git a/tempest/common/generator/__init__.py b/tempest/common/generator/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/common/generator/__init__.py
+++ /dev/null
diff --git a/tempest/common/generator/base_generator.py b/tempest/common/generator/base_generator.py
deleted file mode 100644
index 0647edb..0000000
--- a/tempest/common/generator/base_generator.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Copyright 2014 Deutsche Telekom AG
-# 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 functools
-
-import jsonschema
-import six
-
-
-def _check_for_expected_result(name, schema):
-    expected_result = None
-    if "results" in schema:
-        if name in schema["results"]:
-            expected_result = schema["results"][name]
-    return expected_result
-
-
-def generator_type(*args, **kwargs):
-    def wrapper(func):
-        func.types = args
-        for key in kwargs:
-            setattr(func, key, kwargs[key])
-        return func
-    return wrapper
-
-
-def simple_generator(fn):
-    """Decorator for simple generators that return one value"""
-    @functools.wraps(fn)
-    def wrapped(self, schema):
-        result = fn(self, schema)
-        if result is not None:
-            expected_result = _check_for_expected_result(fn.__name__, schema)
-            return (fn.__name__, result, expected_result)
-        return
-    return wrapped
-
-
-class BasicGeneratorSet(object):
-    _instance = None
-
-    schema = {
-        "type": "object",
-        "properties": {
-            "name": {"type": "string"},
-            "http-method": {
-                "enum": ["GET", "PUT", "HEAD",
-                         "POST", "PATCH", "DELETE", 'COPY']
-            },
-            "admin_client": {"type": "boolean"},
-            "url": {"type": "string"},
-            "default_result_code": {"type": "integer"},
-            "json-schema": {},
-            "resources": {
-                "type": "array",
-                "items": {
-                    "oneOf": [
-                        {"type": "string"},
-                        {
-                            "type": "object",
-                            "properties": {
-                                "name": {"type": "string"},
-                                "expected_result": {"type": "integer"}
-                            }
-                        }
-                    ]
-                }
-            },
-            "results": {
-                "type": "object",
-                "properties": {}
-            }
-        },
-        "required": ["name", "http-method", "url"],
-        "additionalProperties": False,
-    }
-
-    def __init__(self):
-        self.types_dict = {}
-        for m in dir(self):
-            if callable(getattr(self, m)) and not'__' in m:
-                method = getattr(self, m)
-                if hasattr(method, "types"):
-                    for type in method.types:
-                        if type not in self.types_dict:
-                            self.types_dict[type] = []
-                        self.types_dict[type].append(method)
-
-    def validate_schema(self, schema):
-        if "json-schema" in schema:
-            jsonschema.Draft4Validator.check_schema(schema['json-schema'])
-        jsonschema.validate(schema, self.schema)
-
-    def generate_scenarios(self, schema, path=None):
-        """Generate scenario (all possible test cases) out of the given schema
-
-        :param schema: a dict style schema (see ``BasicGeneratorSet.schema``)
-        :param path: the schema path if the given schema is a subschema
-        """
-        schema_type = schema['type']
-        scenarios = []
-
-        if schema_type == 'object':
-            properties = schema["properties"]
-            for attribute, definition in six.iteritems(properties):
-                current_path = copy.copy(path)
-                if path is not None:
-                    current_path.append(attribute)
-                else:
-                    current_path = [attribute]
-                scenarios.extend(
-                    self.generate_scenarios(definition, current_path))
-        elif isinstance(schema_type, list):
-            if "integer" in schema_type:
-                schema_type = "integer"
-            else:
-                raise Exception("non-integer list types not supported")
-        for generator in self.types_dict[schema_type]:
-            if hasattr(generator, "needed_property"):
-                prop = generator.needed_property
-                if (prop not in schema or
-                    schema[prop] is None or
-                    schema[prop] is False):
-                    continue
-
-            name = generator.__name__
-            if ("exclude_tests" in schema and
-               name in schema["exclude_tests"]):
-                continue
-            if path is not None:
-                name = "%s_%s" % ("_".join(path), name)
-            scenarios.append({
-                "_negtest_name": name,
-                "_negtest_generator": generator,
-                "_negtest_schema": schema,
-                "_negtest_path": path})
-        return scenarios
-
-    def generate_payload(self, test, schema):
-        """Generates one jsonschema out of the given test.
-
-        It's mandatory to use generate_scenarios before to register all needed
-        variables to the test.
-
-        :param test: A test object (scenario) with all _negtest variables on it
-        :param schema: schema for the test
-        """
-        generator = test._negtest_generator
-        ret = generator(test._negtest_schema)
-        path = copy.copy(test._negtest_path)
-        expected_result = None
-
-        if ret is not None:
-            generator_result = generator(test._negtest_schema)
-            invalid_snippet = generator_result[1]
-            expected_result = generator_result[2]
-            element = path.pop()
-            if len(path) > 0:
-                schema_snip = six.moves.reduce(dict.get, path, schema)
-                schema_snip[element] = invalid_snippet
-            else:
-                schema[element] = invalid_snippet
-        return expected_result
diff --git a/tempest/common/generator/negative_generator.py b/tempest/common/generator/negative_generator.py
deleted file mode 100644
index 67ace54..0000000
--- a/tempest/common/generator/negative_generator.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2014 Deutsche Telekom AG
-# 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 tempest.common.generator.base_generator as base
-import tempest.common.generator.valid_generator as valid
-
-
-class NegativeTestGenerator(base.BasicGeneratorSet):
-    @base.generator_type("string")
-    @base.simple_generator
-    def gen_int(self, _):
-        return 4
-
-    @base.generator_type("integer")
-    @base.simple_generator
-    def gen_string(self, _):
-        return "XXXXXX"
-
-    @base.generator_type("integer", "string")
-    def gen_none(self, schema):
-        # Note(mkoderer): it's not using the decorator otherwise it'd be
-        # filtered
-        expected_result = base._check_for_expected_result('gen_none', schema)
-        return ('gen_none', None, expected_result)
-
-    @base.generator_type("string")
-    @base.simple_generator
-    def gen_str_min_length(self, schema):
-        min_length = schema.get("minLength", 0)
-        if min_length > 0:
-            return "x" * (min_length - 1)
-
-    @base.generator_type("string", needed_property="maxLength")
-    @base.simple_generator
-    def gen_str_max_length(self, schema):
-        max_length = schema.get("maxLength", -1)
-        return "x" * (max_length + 1)
-
-    @base.generator_type("integer", needed_property="minimum")
-    @base.simple_generator
-    def gen_int_min(self, schema):
-        minimum = schema["minimum"]
-        if "exclusiveMinimum" not in schema:
-            minimum -= 1
-        return minimum
-
-    @base.generator_type("integer", needed_property="maximum")
-    @base.simple_generator
-    def gen_int_max(self, schema):
-        maximum = schema["maximum"]
-        if "exclusiveMaximum" not in schema:
-            maximum += 1
-        return maximum
-
-    @base.generator_type("object", needed_property="additionalProperties")
-    @base.simple_generator
-    def gen_obj_add_attr(self, schema):
-        valid_schema = valid.ValidTestGenerator().generate_valid(schema)
-        new_valid = copy.deepcopy(valid_schema)
-        new_valid["$$$$$$$$$$"] = "xxx"
-        return new_valid
diff --git a/tempest/common/generator/valid_generator.py b/tempest/common/generator/valid_generator.py
deleted file mode 100644
index 3070489..0000000
--- a/tempest/common/generator/valid_generator.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2014 Deutsche Telekom AG
-# 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 six
-
-import tempest.common.generator.base_generator as base
-
-
-class ValidTestGenerator(base.BasicGeneratorSet):
-    @base.generator_type("string")
-    @base.simple_generator
-    def generate_valid_string(self, schema):
-        size = schema.get("minLength", 1)
-        # TODO(dkr mko): handle format and pattern
-        return "x" * size
-
-    @base.generator_type("integer")
-    @base.simple_generator
-    def generate_valid_integer(self, schema):
-        # TODO(dkr mko): handle multipleOf
-        if "minimum" in schema:
-            minimum = schema["minimum"]
-            if "exclusiveMinimum" not in schema:
-                return minimum
-            else:
-                return minimum + 1
-        if "maximum" in schema:
-            maximum = schema["maximum"]
-            if "exclusiveMaximum" not in schema:
-                return maximum
-            else:
-                return maximum - 1
-        return 0
-
-    @base.generator_type("object")
-    @base.simple_generator
-    def generate_valid_object(self, schema):
-        obj = {}
-        for k, v in six.iteritems(schema["properties"]):
-            obj[k] = self.generate_valid(v)
-        return obj
-
-    def generate(self, schema):
-        schema_type = schema["type"]
-        if isinstance(schema_type, list):
-            if "integer" in schema_type:
-                schema_type = "integer"
-            else:
-                raise Exception("non-integer list types not supported")
-        result = []
-        if schema_type not in self.types_dict:
-            raise TypeError("generator (%s) doesn't support type: %s"
-                            % (self.__class__.__name__, schema_type))
-        for generator in self.types_dict[schema_type]:
-            ret = generator(schema)
-            if ret is not None:
-                if isinstance(ret, list):
-                    result.extend(ret)
-                elif isinstance(ret, tuple):
-                    result.append(ret)
-                else:
-                    raise Exception("generator (%s) returns invalid result: %s"
-                                    % (generator, ret))
-        return result
-
-    def generate_valid(self, schema):
-        return self.generate(schema)[0][1]
diff --git a/tempest/common/negative_rest_client.py b/tempest/common/negative_rest_client.py
deleted file mode 100644
index 3495a24..0000000
--- a/tempest/common/negative_rest_client.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# (c) 2014 Deutsche Telekom AG
-# Copyright 2014 Red Hat, Inc.
-# 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 import config
-from tempest.lib.common import rest_client
-
-CONF = config.CONF
-
-
-class NegativeRestClient(rest_client.RestClient):
-    """Version of RestClient that does not raise exceptions."""
-    def __init__(self, auth_provider, service, **kwargs):
-        region, endpoint_type = self._get_region_and_endpoint_type(service)
-        super(NegativeRestClient, self).__init__(
-            auth_provider, service, region, endpoint_type=endpoint_type,
-            **kwargs)
-
-    def _get_region_and_endpoint_type(self, service):
-        """Returns the region for a specific service"""
-        service_region = None
-        service_endpoint_type = None
-        for cfgname in dir(CONF._config):
-            # Find all config.FOO.catalog_type and assume FOO is a service.
-            cfg = getattr(CONF, cfgname)
-            catalog_type = getattr(cfg, 'catalog_type', None)
-            if catalog_type == service:
-                service_region = getattr(cfg, 'region', None)
-                service_endpoint_type = getattr(cfg, 'endpoint_type', None)
-        if not service_region:
-            service_region = CONF.identity.region
-        return service_region, service_endpoint_type
-
-    def _error_checker(self, method, url,
-                       headers, body, resp, resp_body):
-        pass
-
-    def send_request(self, method, url_template, resources, body=None):
-        url = url_template % tuple(resources)
-        if method == "GET":
-            resp, body = self.get(url)
-        elif method == "POST":
-            resp, body = self.post(url, body)
-        elif method == "PUT":
-            resp, body = self.put(url, body)
-        elif method == "PATCH":
-            resp, body = self.patch(url, body)
-        elif method == "HEAD":
-            resp, body = self.head(url)
-        elif method == "DELETE":
-            resp, body = self.delete(url)
-        elif method == "COPY":
-            resp, body = self.copy(url)
-        else:
-            assert False
-
-        return resp, body
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index 5e23696..3f68ae8 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -304,7 +304,9 @@
         if exist_creds and not force_new:
             return exist_creds
         elif exist_creds and force_new:
-            new_index = six.text_type(roles).encode('utf-8') + '-' + \
+            # NOTE(andreaf) In py3.x encode returns bytes, and b'' is bytes
+            # In py2.7 encode returns strings, and b'' is still string
+            new_index = six.text_type(roles).encode('utf-8') + b'-' + \
                 six.text_type(len(self._creds)).encode('utf-8')
             self._creds[new_index] = exist_creds
         net_creds = self._get_creds(roles=roles)
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 9ec217f..d8993bb 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -112,11 +112,22 @@
         output = self.exec_command('grep -c ^processor /proc/cpuinfo')
         return int(output)
 
-    def get_partitions(self):
-        # Return the contents of /proc/partitions
-        command = 'cat /proc/partitions'
+    def get_disks(self):
+        # Select root disk devices as shown by lsblk
+        command = 'lsblk -lb --nodeps'
         output = self.exec_command(command)
-        return output
+        selected = []
+        pos = None
+        for l in output.splitlines():
+            if pos is None and l.find("TYPE") > 0:
+                pos = l.find("TYPE")
+                # Show header line too
+                selected.append(l)
+            # lsblk lists disk type in a column right-aligned with TYPE
+            elif pos > 0 and l[pos:pos + 4] == "disk":
+                selected.append(l)
+
+        return "\n".join(selected)
 
     def get_boot_time(self):
         cmd = 'cut -f1 -d. /proc/uptime'
diff --git a/tempest/common/utils/net_utils.py b/tempest/common/utils/net_utils.py
index f0d3da3..867b3dd 100644
--- a/tempest/common/utils/net_utils.py
+++ b/tempest/common/utils/net_utils.py
@@ -51,3 +51,23 @@
                 return addrs
     msg = "Insufficient IP addresses available"
     raise lib_exc.BadRequest(message=msg)
+
+
+def get_ping_payload_size(mtu, ip_version):
+    """Return the maximum size of ping payload that will fit into MTU."""
+    if not mtu:
+        return None
+    if ip_version == 4:
+        ip_header = 20
+        icmp_header = 8
+    else:
+        ip_header = 40
+        icmp_header = 4
+    res = mtu - ip_header - icmp_header
+    if res < 0:
+        raise lib_exc.BadRequest(
+            message='MTU = %(mtu)d is too low for IPv%(ip_version)d' % {
+                'mtu': mtu,
+                'ip_version': ip_version,
+            })
+    return res
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index c1942d6..fe648a0 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -92,7 +92,7 @@
             caller = test_utils.find_test_caller()
             if caller:
                 message = '(%s) %s' % (caller, message)
-            raise exceptions.TimeoutException(message)
+            raise lib_exc.TimeoutException(message)
         old_status = server_status
         old_task_state = task_state
 
@@ -111,7 +111,7 @@
             raise exceptions.BuildErrorException(server_id=server_id)
 
         if int(time.time()) - start_time >= client.build_timeout:
-            raise exceptions.TimeoutException
+            raise lib_exc.TimeoutException
 
         time.sleep(client.build_interval)
 
@@ -163,7 +163,7 @@
     caller = test_utils.find_test_caller()
     if caller:
         message = '(%s) %s' % (caller, message)
-    raise exceptions.TimeoutException(message)
+    raise lib_exc.TimeoutException(message)
 
 
 def wait_for_volume_status(client, volume_id, status):
@@ -176,7 +176,7 @@
         time.sleep(client.build_interval)
         body = client.show_volume(volume_id)['volume']
         volume_status = body['status']
-        if volume_status == 'error':
+        if volume_status == 'error' and status != 'error':
             raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
         if volume_status == 'error_restoring':
             raise exceptions.VolumeRestoreErrorException(volume_id=volume_id)
@@ -186,7 +186,7 @@
                        'within the required time (%s s).' %
                        (volume_id, status, volume_status,
                         client.build_timeout))
-            raise exceptions.TimeoutException(message)
+            raise lib_exc.TimeoutException(message)
 
 
 def wait_for_snapshot_status(client, snapshot_id, status):
@@ -207,7 +207,7 @@
                        'within the required time (%s s).' %
                        (snapshot_id, status, snapshot_status,
                         client.build_timeout))
-            raise exceptions.TimeoutException(message)
+            raise lib_exc.TimeoutException(message)
 
 
 def wait_for_backup_status(client, backup_id, status):
@@ -228,36 +228,7 @@
                        '(current %s) within the required time (%s s).' %
                        (backup_id, status, backup_status,
                         client.build_timeout))
-            raise exceptions.TimeoutException(message)
-
-
-def wait_for_bm_node_status(client, node_id, attr, status):
-    """Waits for a baremetal node attribute to reach given status.
-
-    The client should have a show_node(node_uuid) method to get the node.
-    """
-    _, node = client.show_node(node_id)
-    start = int(time.time())
-
-    while node[attr] != status:
-        time.sleep(client.build_interval)
-        _, node = client.show_node(node_id)
-        status_curr = node[attr]
-        if status_curr == status:
-            return
-
-        if int(time.time()) - start >= client.build_timeout:
-            message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
-                       'within the required time (%(timeout)s s).' %
-                       {'node_id': node_id,
-                        'attr': attr,
-                        'status': status,
-                        'timeout': client.build_timeout})
-            message += ' Current state of %s: %s.' % (attr, status_curr)
-            caller = test_utils.find_test_caller()
-            if caller:
-                message = '(%s) %s' % (caller, message)
-            raise exceptions.TimeoutException(message)
+            raise lib_exc.TimeoutException(message)
 
 
 def wait_for_qos_operations(client, qos_id, operation, args=None):
@@ -288,5 +259,30 @@
             raise lib_exc.UnprocessableEntity(msg)
 
         if int(time.time()) - start_time >= client.build_timeout:
-            raise exceptions.TimeoutException
+            raise lib_exc.TimeoutException
         time.sleep(client.build_interval)
+
+
+def wait_for_interface_status(client, server, port_id, status):
+    """Waits for an interface to reach a given status."""
+    body = (client.show_interface(server, port_id)
+            ['interfaceAttachment'])
+    interface_status = body['port_state']
+    start = int(time.time())
+
+    while(interface_status != status):
+        time.sleep(client.build_interval)
+        body = (client.show_interface(server, port_id)
+                ['interfaceAttachment'])
+        interface_status = body['port_state']
+
+        timed_out = int(time.time()) - start >= client.build_timeout
+
+        if interface_status != status and timed_out:
+            message = ('Interface %s failed to reach %s status '
+                       '(current %s) within the required time (%s s).' %
+                       (port_id, status, interface_status,
+                        client.build_timeout))
+            raise lib_exc.TimeoutException(message)
+
+    return body
diff --git a/tempest/config.py b/tempest/config.py
index 4b785ec..281e283 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -295,6 +295,11 @@
                      'be utilized by some multinode specific tests to ensure '
                      'that requests match the expected size of the cluster '
                      'you are testing with.')),
+    cfg.StrOpt('hypervisor_type',
+               default=None,
+               help="Hypervisor type of the test target on heterogeneous "
+                    "compute environment. The value can be 'QEMU', 'xen' or "
+                    "something."),
     cfg.StrOpt('min_microversion',
                default=None,
                help="Lower version of the test target microversion range. "
@@ -414,7 +419,10 @@
     cfg.BoolOpt('nova_cert',
                 default=False,
                 help='Does the test environment have the nova cert running?',
-                deprecated_for_removal=True),
+                deprecated_for_removal=True,
+                deprecated_reason="On Nova side, the nova-cert service is "
+                                  "deprecated and the service will be removed "
+                                  "as early as Ocata."),
     cfg.BoolOpt('personality',
                 default=False,
                 help='Does the test environment support server personality'),
@@ -431,10 +439,16 @@
                 default=['all'],
                 help="A list of enabled filters that nova will accept as hints"
                      " to the scheduler when creating a server. A special "
-                     "entry 'all' indicates all filters are enabled. Empty "
-                     "list indicates all filters are disabled. The full "
-                     "available list of filters is in nova.conf: "
-                     "DEFAULT.scheduler_available_filters"),
+                     "entry 'all' indicates all filters that are included "
+                     "with nova are enabled. Empty list indicates all filters "
+                     "are disabled. The full list of available filters is in "
+                     "nova.conf: DEFAULT.scheduler_available_filters. If the "
+                     "default value is overridden in nova.conf by the test "
+                     "environment (which means that a different set of "
+                     "filters is enabled than what is included in Nova by "
+                     "default) then, this option must be configured to "
+                     "contain the same filters that Nova uses in the test "
+                     "environment."),
     cfg.BoolOpt('swap_volume',
                 default=False,
                 help='Does the test environment support in-place swapping of '
@@ -574,6 +588,10 @@
                 default=["1.0.0.0/16", "2.0.0.0/16"],
                 help="List of ip pools"
                      " for subnetpools creation"),
+    cfg.BoolOpt('shared_physical_network',
+                default=False,
+                help="The environment does not support network separation "
+                     "between tenants."),
     # TODO(ylobankov): Delete this option once the Liberty release is EOL.
     cfg.BoolOpt('dvr_extra_resources',
                 default=True,
@@ -797,11 +815,6 @@
     cfg.BoolOpt('api_v3',
                 default=False,
                 help="Is the v3 volume API enabled"),
-    cfg.BoolOpt('bootable',
-                default=True,
-                help='Update bootable status of a volume '
-                     'Not implemented on icehouse ',
-                deprecated_for_removal=True),
     # TODO(ynesenenko): Remove volume_services once liberty-eol happens.
     cfg.BoolOpt('volume_services',
                 default=False,
@@ -983,9 +996,6 @@
     cfg.BoolOpt('sahara',
                 default=False,
                 help="Whether or not Sahara is expected to be available"),
-    cfg.BoolOpt('ironic',
-                default=False,
-                help="Whether or not Ironic is expected to be available"),
 ]
 
 debug_group = cfg.OptGroup(name="debug",
@@ -1040,64 +1050,6 @@
                deprecated_for_removal=True),
 ]
 
-
-baremetal_group = cfg.OptGroup(name='baremetal',
-                               title='Baremetal provisioning service options',
-                               help='When enabling baremetal tests, Nova '
-                                    'must be configured to use the Ironic '
-                                    'driver. The following parameters for the '
-                                    '[compute] section must be disabled: '
-                                    'console_output, interface_attach, '
-                                    'live_migration, pause, rescue, resize '
-                                    'shelve, snapshot, and suspend')
-
-
-# NOTE(deva): Ironic tests have been ported to tempest.lib. New config options
-#             should be added to ironic/ironic_tempest_plugin/config.py.
-#             However, these options need to remain here for testing stable
-#             branches until Liberty release reaches EOL.
-BaremetalGroup = [
-    cfg.StrOpt('catalog_type',
-               default='baremetal',
-               help="Catalog type of the baremetal provisioning service"),
-    cfg.BoolOpt('driver_enabled',
-                default=False,
-                help="Whether the Ironic nova-compute driver is enabled"),
-    cfg.StrOpt('driver',
-               default='fake',
-               help="Driver name which Ironic uses"),
-    cfg.StrOpt('endpoint_type',
-               default='publicURL',
-               choices=['public', 'admin', 'internal',
-                        'publicURL', 'adminURL', 'internalURL'],
-               help="The endpoint type to use for the baremetal provisioning "
-                    "service"),
-    cfg.IntOpt('active_timeout',
-               default=300,
-               help="Timeout for Ironic node to completely provision"),
-    cfg.IntOpt('association_timeout',
-               default=30,
-               help="Timeout for association of Nova instance and Ironic "
-                    "node"),
-    cfg.IntOpt('power_timeout',
-               default=60,
-               help="Timeout for Ironic power transitions."),
-    cfg.IntOpt('unprovision_timeout',
-               default=300,
-               help="Timeout for unprovisioning an Ironic node. "
-                    "Takes longer since Kilo as Ironic performs an extra "
-                    "step in Node cleaning.")
-]
-
-negative_group = cfg.OptGroup(name='negative', title="Negative Test Options")
-
-NegativeGroup = [
-    cfg.StrOpt('test_generator',
-               default='tempest.common.' +
-               'generator.negative_generator.NegativeTestGenerator',
-               help="Test generator class for all negative tests"),
-]
-
 DefaultGroup = [
     cfg.StrOpt('resources_prefix',
                default='tempest',
@@ -1127,9 +1079,7 @@
     (scenario_group, ScenarioGroup),
     (service_available_group, ServiceAvailableGroup),
     (debug_group, DebugGroup),
-    (baremetal_group, BaremetalGroup),
     (input_scenario_group, InputScenarioGroup),
-    (negative_group, NegativeGroup),
     (None, DefaultGroup)
 ]
 
@@ -1191,9 +1141,7 @@
         self.scenario = _CONF.scenario
         self.service_available = _CONF.service_available
         self.debug = _CONF.debug
-        self.baremetal = _CONF.baremetal
         self.input_scenario = _CONF['input-scenario']
-        self.negative = _CONF.negative
         logging.tempest_set_log_file('tempest.log')
 
     def __init__(self, parse_conf=True, config_path=None):
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 727d54e..43f919a 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -21,10 +21,6 @@
     message = "Invalid service tag"
 
 
-class TimeoutException(exceptions.TempestException):
-    message = "Request timed out"
-
-
 class BuildErrorException(exceptions.TempestException):
     message = "Server %(server_id)s failed to build and is in ERROR status"
 
diff --git a/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py b/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
index 07cc890..3cc5ca4 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/parameter_types.py
@@ -94,3 +94,14 @@
         'format': 'data-time'
     }
 }
+
+power_state = {
+    'type': 'integer',
+    # 0: NOSTATE
+    # 1: RUNNING
+    # 3: PAUSED
+    # 4: SHUTDOWN
+    # 6: CRASHED
+    # 7: SUSPENDED
+    'enum': [0, 1, 3, 4, 6, 7]
+}
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index 44497db..63e8467 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -170,7 +170,7 @@
     # attributes.
     'OS-EXT-STS:task_state': {'type': ['string', 'null']},
     'OS-EXT-STS:vm_state': {'type': 'string'},
-    'OS-EXT-STS:power_state': {'type': 'integer'},
+    'OS-EXT-STS:power_state': parameter_types.power_state,
     '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']},
diff --git a/tempest/lib/api_schema/response/compute/v2_16/servers.py b/tempest/lib/api_schema/response/compute/v2_16/servers.py
index 6868110..3eb658f 100644
--- a/tempest/lib/api_schema/response/compute/v2_16/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_16/servers.py
@@ -77,7 +77,7 @@
         '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-STS:power_state': parameter_types.power_state,
         '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']},
diff --git a/tempest/lib/api_schema/response/compute/v2_3/servers.py b/tempest/lib/api_schema/response/compute/v2_3/servers.py
index ee16333..f24103e 100644
--- a/tempest/lib/api_schema/response/compute/v2_3/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_3/servers.py
@@ -85,7 +85,7 @@
         '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-STS:power_state': parameter_types.power_state,
         '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']},
diff --git a/tempest/lib/cli/base.py b/tempest/lib/cli/base.py
index a43d002..72a15b5 100644
--- a/tempest/lib/cli/base.py
+++ b/tempest/lib/cli/base.py
@@ -29,7 +29,7 @@
 
 
 def execute(cmd, action, flags='', params='', fail_ok=False,
-            merge_stderr=False, cli_dir='/usr/bin'):
+            merge_stderr=False, cli_dir='/usr/bin', prefix=''):
     """Executes specified command for the given action.
 
     :param cmd: command to be executed
@@ -48,9 +48,12 @@
     :type merge_stderr: boolean
     :param cli_dir: The path where the cmd can be executed
     :type cli_dir: string
+    :param prefix: prefix to insert before command
+    :type prefix: string
     """
-    cmd = ' '.join([os.path.join(cli_dir, cmd),
+    cmd = ' '.join([prefix, os.path.join(cli_dir, cmd),
                     flags, action, params])
+    cmd = cmd.strip()
     LOG.info("running: '%s'" % cmd)
     if six.PY2:
         cmd = cmd.encode('utf-8')
@@ -88,10 +91,12 @@
     :type cli_dir: string
     :param insecure: if True, --insecure is passed to python client binaries.
     :type insecure: boolean
+    :param prefix: prefix to insert before commands
+    :type prefix: string
     """
 
     def __init__(self, username='', password='', tenant_name='', uri='',
-                 cli_dir='', insecure=False, *args, **kwargs):
+                 cli_dir='', insecure=False, prefix='', *args, **kwargs):
         """Initialize a new CLIClient object."""
         super(CLIClient, self).__init__()
         self.cli_dir = cli_dir if cli_dir else '/usr/bin'
@@ -100,6 +105,7 @@
         self.password = password
         self.uri = uri
         self.insecure = insecure
+        self.prefix = prefix
 
     def nova(self, action, flags='', params='', fail_ok=False,
              endpoint_type='publicURL', merge_stderr=False):
@@ -365,7 +371,7 @@
         else:
             flags = creds + ' ' + flags
         return execute(cmd, action, flags, params, fail_ok, merge_stderr,
-                       self.cli_dir)
+                       self.cli_dir, prefix=self.prefix)
 
 
 class ClientTestBase(base.BaseTestCase):
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index 1239ac5..88ce775 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -23,6 +23,7 @@
 import unittest
 import uuid
 
+from oslo_utils import uuidutils
 import six.moves.urllib.parse as urlparse
 
 DECORATOR_MODULE = 'test'
@@ -61,7 +62,7 @@
         if filename not in self.source_files:
             with open(filename) as f:
                 self.source_files[filename] = self._quote(f.read())
-        patch_id = str(uuid.uuid4())
+        patch_id = uuidutils.generate_uuid()
         if not patch.endswith('\n'):
             patch += '\n'
         self.patches[patch_id] = self._quote(patch)
diff --git a/tempest/common/cred_client.py b/tempest/lib/common/cred_client.py
similarity index 98%
rename from tempest/common/cred_client.py
rename to tempest/lib/common/cred_client.py
index ad968f1..3f10dee 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/lib/common/cred_client.py
@@ -140,7 +140,7 @@
             # Domain names must be unique, in any case a list is returned,
             # selecting the first (and only) element
             self.creds_domain = self.domains_client.list_domains(
-                params={'name': domain_name})['domains'][0]
+                name=domain_name)['domains'][0]
         except lib_exc.NotFound:
             # TODO(andrea) we could probably create the domain on the fly
             msg = "Requested domain %s could not be found" % domain_name
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index 4095c77..75c2e51 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -21,6 +21,7 @@
 
 from debtcollector import removals
 from oslo_utils import netutils
+from oslo_utils import uuidutils
 import six.moves
 
 
@@ -30,7 +31,7 @@
     :return: a random UUID (e.g. '1dc12c7d-60eb-4b61-a7a2-17cf210155b6')
     :rtype: string
     """
-    return str(uuid.uuid4())
+    return uuidutils.generate_uuid()
 
 
 def rand_uuid_hex():
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index a6c01bb..108ba70 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -71,54 +71,70 @@
     message = "The success code is different than the expected one"
 
 
-class NotFound(ClientRestClientException):
-    message = "Object not found"
+class BadRequest(ClientRestClientException):
+    status_code = 400
+    message = "Bad request"
 
 
 class Unauthorized(ClientRestClientException):
+    status_code = 401
     message = 'Unauthorized'
 
 
 class Forbidden(ClientRestClientException):
+    status_code = 403
     message = "Forbidden"
 
 
-class TimeoutException(OtherRestClientException):
-    message = "Request timed out"
-
-
-class BadRequest(ClientRestClientException):
-    message = "Bad request"
-
-
-class UnprocessableEntity(ClientRestClientException):
-    message = "Unprocessable entity"
-
-
-class RateLimitExceeded(ClientRestClientException):
-    message = "Rate limit exceeded"
-
-
-class OverLimit(ClientRestClientException):
-    message = "Request entity is too large"
-
-
-class ServerFault(ServerRestClientException):
-    message = "Got server fault"
-
-
-class NotImplemented(ServerRestClientException):
-    message = "Got NotImplemented error"
+class NotFound(ClientRestClientException):
+    status_code = 404
+    message = "Object not found"
 
 
 class Conflict(ClientRestClientException):
+    status_code = 409
     message = "An object with that identifier already exists"
 
 
 class Gone(ClientRestClientException):
+    status_code = 410
     message = "The requested resource is no longer available"
 
 
+class RateLimitExceeded(ClientRestClientException):
+    status_code = 413
+    message = "Rate limit exceeded"
+
+
+class OverLimit(ClientRestClientException):
+    status_code = 413
+    message = "Request entity is too large"
+
+
+class InvalidContentType(ClientRestClientException):
+    status_code = 415
+    message = "Invalid content type provided"
+
+
+class UnprocessableEntity(ClientRestClientException):
+    status_code = 422
+    message = "Unprocessable entity"
+
+
+class ServerFault(ServerRestClientException):
+    status_code = 500
+    message = "Got server fault"
+
+
+class NotImplemented(ServerRestClientException):
+    status_code = 501
+    message = "Got NotImplemented error"
+
+
+class TimeoutException(OtherRestClientException):
+    message = "Request timed out"
+
+
 class ResponseWithNonEmptyBody(OtherRestClientException):
     message = ("RFC Violation! Response with %(status)d HTTP Status Code "
                "MUST NOT have a body")
@@ -137,10 +153,6 @@
     message = "HTTP response header is invalid"
 
 
-class InvalidContentType(ClientRestClientException):
-    message = "Invalid content type provided"
-
-
 class UnexpectedContentType(OtherRestClientException):
     message = "Unexpected content type provided"
 
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index adf666b..0e8e3c6 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -23,8 +23,10 @@
 from tempest.lib.common.utils import misc
 from tempest.lib import exceptions
 from tempest.lib.services import compute
+from tempest.lib.services import identity
 from tempest.lib.services import image
 from tempest.lib.services import network
+from tempest.lib.services import volume
 
 
 LOG = logging.getLogger(__name__)
@@ -38,9 +40,13 @@
     """
     return {
         'compute': compute,
+        'identity.v2': identity.v2,
         'image.v1': image.v1,
         'image.v2': image.v2,
-        'network': network
+        'network': network,
+        'volume.v1': volume.v1,
+        'volume.v2': volume.v2,
+        'volume.v3': volume.v3
     }
 
 
@@ -49,8 +55,7 @@
     # 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'])
+    return set(['identity.v3', 'object-storage'])
 
 
 def available_modules():
diff --git a/tempest/lib/services/compute/agents_client.py b/tempest/lib/services/compute/agents_client.py
index 3f05d3b..169d978 100644
--- a/tempest/lib/services/compute/agents_client.py
+++ b/tempest/lib/services/compute/agents_client.py
@@ -26,8 +26,9 @@
     def list_agents(self, **params):
         """List all agent builds.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listbuilds
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listbuilds
         """
         url = 'os-agents'
         if params:
@@ -40,8 +41,9 @@
     def create_agent(self, **kwargs):
         """Create an agent build.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#agentbuild
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#agentbuild
         """
         post_body = json.dumps({'agent': kwargs})
         resp, body = self.post('os-agents', post_body)
@@ -52,8 +54,9 @@
     def delete_agent(self, agent_id):
         """Delete an existing agent build.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteBuild
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -62,8 +65,9 @@
     def update_agent(self, agent_id, **kwargs):
         """Update an agent build.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#updatebuild
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#updatebuild
         """
         put_body = json.dumps({'para': kwargs})
         resp, body = self.put('os-agents/%s' % agent_id, put_body)
diff --git a/tempest/lib/services/compute/aggregates_client.py b/tempest/lib/services/compute/aggregates_client.py
index 7ad14bc..c1a6c8c 100644
--- a/tempest/lib/services/compute/aggregates_client.py
+++ b/tempest/lib/services/compute/aggregates_client.py
@@ -40,8 +40,9 @@
     def create_aggregate(self, **kwargs):
         """Create a new aggregate.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createAggregate
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createAggregate
         """
         post_body = json.dumps({'aggregate': kwargs})
         resp, body = self.post('os-aggregates', post_body)
@@ -53,8 +54,9 @@
     def update_aggregate(self, aggregate_id, **kwargs):
         """Update an aggregate.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#updateAggregate
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#updateAggregate
         """
         put_body = json.dumps({'aggregate': kwargs})
         resp, body = self.put('os-aggregates/%s' % aggregate_id, put_body)
@@ -84,8 +86,9 @@
     def add_host(self, aggregate_id, **kwargs):
         """Add a host to the given aggregate.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#addHost
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#addHost
         """
         post_body = json.dumps({'add_host': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
@@ -97,8 +100,9 @@
     def remove_host(self, aggregate_id, **kwargs):
         """Remove a host from the given aggregate.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#removeAggregateHost
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#removeAggregateHost
         """
         post_body = json.dumps({'remove_host': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
@@ -110,8 +114,9 @@
     def set_metadata(self, aggregate_id, **kwargs):
         """Replace the aggregate's existing metadata with new metadata.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#addAggregateMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#addAggregateMetadata
         """
         post_body = json.dumps({'set_metadata': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
diff --git a/tempest/lib/services/compute/fixed_ips_client.py b/tempest/lib/services/compute/fixed_ips_client.py
index c25ac2c..682ee86 100644
--- a/tempest/lib/services/compute/fixed_ips_client.py
+++ b/tempest/lib/services/compute/fixed_ips_client.py
@@ -32,8 +32,9 @@
     def reserve_fixed_ip(self, fixed_ip, **kwargs):
         """Reserve/Unreserve a fixed IP.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#reserveIP
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#reserveIP
         """
         url = "os-fixed-ips/%s/action" % fixed_ip
         resp, body = self.post(url, json.dumps(kwargs))
diff --git a/tempest/lib/services/compute/flavors_client.py b/tempest/lib/services/compute/flavors_client.py
index ae1700c..a83c68b 100644
--- a/tempest/lib/services/compute/flavors_client.py
+++ b/tempest/lib/services/compute/flavors_client.py
@@ -30,8 +30,9 @@
     def list_flavors(self, detail=False, **params):
         """Lists flavors.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listFlavors
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listFlavors
         """
         url = 'flavors'
         _schema = schema.list_flavors
@@ -50,8 +51,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showFlavor
         """
         resp, body = self.get("flavors/%s" % flavor_id)
         body = json.loads(body)
@@ -61,12 +63,13 @@
     def create_flavor(self, **kwargs):
         """Create a new flavor or instance type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createFlavor
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createFlavor
         """
-        if kwargs.get('ephemeral'):
+        if 'ephemeral' in kwargs:
             kwargs['OS-FLV-EXT-DATA:ephemeral'] = kwargs.pop('ephemeral')
-        if kwargs.get('is_public'):
+        if 'is_public' in kwargs:
             kwargs['os-flavor-access:is_public'] = kwargs.pop('is_public')
 
         post_body = json.dumps({'flavor': kwargs})
@@ -79,8 +82,9 @@
     def delete_flavor(self, flavor_id):
         """Delete the given flavor.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteFlavor
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -104,8 +108,9 @@
     def set_flavor_extra_spec(self, flavor_id, **kwargs):
         """Set extra Specs to the mentioned flavor.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createFlavorExtraSpec
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createFlavorExtraSpec
         """
         post_body = json.dumps({'extra_specs': kwargs})
         resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
@@ -118,8 +123,9 @@
     def list_flavor_extra_specs(self, flavor_id):
         """Get extra Specs details of the mentioned flavor.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listFlavorExtraSpecs
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -130,8 +136,9 @@
     def show_flavor_extra_spec(self, flavor_id, 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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showFlavorExtraSpec
         """
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (flavor_id,
                               key))
@@ -144,8 +151,9 @@
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
         """Update specified extra Specs of the mentioned flavor and key.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#updateFlavorExtraSpec
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#updateFlavorExtraSpec
         """
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key), json.dumps(kwargs))
@@ -160,8 +168,9 @@
         #       to keep backwards compatibility.
         """Unset extra Specs from the mentioned flavor.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteFlavorExtraSpec
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteFlavorExtraSpec
         """
         resp, body = self.delete('flavors/%s/os-extra_specs/%s' %
                                  (flavor_id, key))
@@ -171,8 +180,9 @@
     def list_flavor_access(self, flavor_id):
         """Get flavor access information given the flavor id.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listFlavorAccess
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -183,8 +193,9 @@
     def add_flavor_access(self, flavor_id, tenant_id):
         """Add flavor access for the specified tenant.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#addFlavorAccess
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#addFlavorAccess
         """
         post_body = {
             'addTenantAccess': {
@@ -201,8 +212,9 @@
     def remove_flavor_access(self, flavor_id, tenant_id):
         """Remove flavor access from the specified tenant.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#removeFlavorAccess
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#removeFlavorAccess
         """
         post_body = {
             'removeTenantAccess': {
diff --git a/tempest/lib/services/compute/floating_ips_client.py b/tempest/lib/services/compute/floating_ips_client.py
index 6922c48..744e14c 100644
--- a/tempest/lib/services/compute/floating_ips_client.py
+++ b/tempest/lib/services/compute/floating_ips_client.py
@@ -27,8 +27,9 @@
     def list_floating_ips(self, **params):
         """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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listfloatingipsObject
         """
         url = 'os-floating-ips'
         if params:
@@ -42,8 +43,9 @@
     def show_floating_ip(self, floating_ip_id):
         """Get the details of a floating IP.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#showFloatingIP
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showFloatingIP
         """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.get(url)
@@ -54,8 +56,9 @@
     def create_floating_ip(self, **kwargs):
         """Allocate a floating IP to the project.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createFloatingIP
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createFloatingIP
         """
         url = 'os-floating-ips'
         post_body = json.dumps(kwargs)
@@ -67,8 +70,9 @@
     def delete_floating_ip(self, floating_ip_id):
         """Deletes the provided floating IP from the project.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteFloatingIP
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteFloatingIP
         """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.delete(url)
diff --git a/tempest/lib/services/compute/security_group_default_rules_client.py b/tempest/lib/services/compute/security_group_default_rules_client.py
index d57c8e0..e2d3c98 100644
--- a/tempest/lib/services/compute/security_group_default_rules_client.py
+++ b/tempest/lib/services/compute/security_group_default_rules_client.py
@@ -26,9 +26,9 @@
     def create_security_default_group_rule(self, **kwargs):
         """Create security group default rule.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html
-                              #createSecGroupDefaultRule
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createSecGroupDefaultRule
         """
         post_body = json.dumps({'security_group_default_rule': kwargs})
         url = 'os-security-group-default-rules'
diff --git a/tempest/lib/services/compute/security_group_rules_client.py b/tempest/lib/services/compute/security_group_rules_client.py
index c969b81..3121e24 100644
--- a/tempest/lib/services/compute/security_group_rules_client.py
+++ b/tempest/lib/services/compute/security_group_rules_client.py
@@ -26,8 +26,9 @@
     def create_security_group_rule(self, **kwargs):
         """Create a new security group rule.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createSecGroupRule
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createSecGroupRule
         """
         post_body = json.dumps({'security_group_rule': kwargs})
         url = 'os-security-group-rules'
diff --git a/tempest/lib/services/compute/security_groups_client.py b/tempest/lib/services/compute/security_groups_client.py
index 386c214..a247346 100644
--- a/tempest/lib/services/compute/security_groups_client.py
+++ b/tempest/lib/services/compute/security_groups_client.py
@@ -28,8 +28,9 @@
     def list_security_groups(self, **params):
         """List all security groups for a user.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listSecGroups
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listSecGroups
         """
 
         url = 'os-security-groups'
@@ -44,8 +45,9 @@
     def show_security_group(self, security_group_id):
         """Get the details of a Security Group.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#showSecGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showSecGroup
         """
         url = "os-security-groups/%s" % security_group_id
         resp, body = self.get(url)
@@ -56,8 +58,9 @@
     def create_security_group(self, **kwargs):
         """Create a new security group.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createSecGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createSecGroup
         """
         post_body = json.dumps({'security_group': kwargs})
         resp, body = self.post('os-security-groups', post_body)
@@ -68,8 +71,9 @@
     def update_security_group(self, security_group_id, **kwargs):
         """Update a security group.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#updateSecGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#updateSecGroup
         """
         post_body = json.dumps({'security_group': kwargs})
         resp, body = self.put('os-security-groups/%s' % security_group_id,
@@ -81,8 +85,9 @@
     def delete_security_group(self, security_group_id):
         """Delete the provided Security Group.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteSecGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteSecGroup
         """
         resp, body = self.delete(
             'os-security-groups/%s' % security_group_id)
diff --git a/tempest/lib/services/compute/server_groups_client.py b/tempest/lib/services/compute/server_groups_client.py
index e370457..9ba8d38 100644
--- a/tempest/lib/services/compute/server_groups_client.py
+++ b/tempest/lib/services/compute/server_groups_client.py
@@ -26,8 +26,9 @@
     def create_server_group(self, **kwargs):
         """Create the server group.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createServerGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createServerGroup
         """
         post_body = json.dumps({'server_group': kwargs})
         resp, body = self.post('os-server-groups', post_body)
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index d5902e1..24557d8 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -92,8 +92,9 @@
     def update_server(self, server_id, **kwargs):
         """Update server.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#updateServer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#updateServer
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -112,8 +113,9 @@
     def show_server(self, server_id):
         """Get server details.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#showServer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showServer
         """
         resp, body = self.get("servers/%s" % server_id)
         body = json.loads(body)
@@ -124,8 +126,9 @@
     def delete_server(self, server_id):
         """Delete server.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteServer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -134,10 +137,10 @@
     def list_servers(self, detail=False, **params):
         """List servers.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listServers
-                          and http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listDetailServers
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listServers
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listDetailServers
         """
 
         url = 'servers'
@@ -158,8 +161,9 @@
     def list_addresses(self, server_id):
         """Lists all addresses for a server.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#list-ips
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -188,16 +192,18 @@
     def create_backup(self, server_id, **kwargs):
         """Backup a server instance.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createBackup
         """
         return self.action(server_id, "createBackup", **kwargs)
 
     def change_password(self, server_id, **kwargs):
         """Change the root password for the server.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#changePassword
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#changePassword
         """
         return self.action(server_id, 'changePassword', **kwargs)
 
@@ -223,16 +229,18 @@
     def reboot_server(self, server_id, **kwargs):
         """Reboot a server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#reboot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#reboot
         """
         return self.action(server_id, 'reboot', **kwargs)
 
     def rebuild_server(self, server_id, image_ref, **kwargs):
         """Rebuild a server with a new image.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#rebuild
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#rebuild
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -252,8 +260,9 @@
     def resize_server(self, server_id, flavor_ref, **kwargs):
         """Change the flavor of a server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#resize
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#resize
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -267,8 +276,9 @@
     def confirm_resize_server(self, server_id, **kwargs):
         """Confirm the flavor change for a server.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#confirmResize
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#confirmResize
         """
         return self.action(server_id, 'confirmResize',
                            schema.server_actions_confirm_resize,
@@ -277,16 +287,18 @@
     def revert_resize_server(self, server_id, **kwargs):
         """Revert a server back to its original flavor.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#revertResize
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#revertResize
         """
         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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listServerMetadata
         """
         resp, body = self.get("servers/%s/metadata" % server_id)
         body = json.loads(body)
@@ -296,8 +308,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createServerMetadata
         """
         if no_metadata_field:
             post_body = ""
@@ -312,8 +325,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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,
@@ -326,8 +340,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
@@ -338,8 +353,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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),
@@ -352,8 +368,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteServerMetadataItem
         """
         resp, body = self.delete("servers/%s/metadata/%s" %
                                  (server_id, key))
@@ -364,24 +381,27 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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):
         """Attaches a volume to a server instance.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#attachVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#attachVolume
         """
         post_body = json.dumps({'volumeAttachment': kwargs})
         resp, body = self.post('servers/%s/os-volume_attachments' % server_id,
@@ -402,8 +422,9 @@
     def detach_volume(self, server_id, volume_id):  # noqa
         """Detaches a volume from a server instance.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteVolumeAttachment
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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))
@@ -413,9 +434,9 @@
     def show_volume_attachment(self, server_id, volume_id):
         """Return details about the given volume attachment.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#
-                              getVolumeAttachmentDetails
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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))
@@ -426,8 +447,9 @@
     def list_volume_attachments(self, server_id):
         """Returns the list of volume attachments for a given instance.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listVolumeAttachments
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listVolumeAttachments
         """
         resp, body = self.get('servers/%s/os-volume_attachments' % (
             server_id))
@@ -438,8 +460,9 @@
     def add_security_group(self, server_id, **kwargs):
         """Add a security group to the server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#addSecurityGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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
@@ -450,8 +473,9 @@
     def remove_security_group(self, server_id, **kwargs):
         """Remove a security group from the server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#removeSecurityGroup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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
@@ -462,104 +486,117 @@
     def live_migrate_server(self, server_id, **kwargs):
         """This should be called with administrator privileges.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#migrateLive
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#migrateLive
         """
         return self.action(server_id, 'os-migrateLive', **kwargs)
 
     def migrate_server(self, server_id, **kwargs):
         """Migrate a server to a new host.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#migrate
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#migrate
         """
         return self.action(server_id, 'migrate', **kwargs)
 
     def lock_server(self, server_id, **kwargs):
         """Lock the given server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#lock
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#lock
         """
         return self.action(server_id, 'lock', **kwargs)
 
     def unlock_server(self, server_id, **kwargs):
         """UNlock the given server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#unlock
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#unlock
         """
         return self.action(server_id, 'unlock', **kwargs)
 
     def suspend_server(self, server_id, **kwargs):
         """Suspend the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#suspend
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#suspend
         """
         return self.action(server_id, 'suspend', **kwargs)
 
     def resume_server(self, server_id, **kwargs):
         """Un-suspend the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#resume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#resume
         """
         return self.action(server_id, 'resume', **kwargs)
 
     def pause_server(self, server_id, **kwargs):
         """Pause the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#pause
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#pause
         """
         return self.action(server_id, 'pause', **kwargs)
 
     def unpause_server(self, server_id, **kwargs):
         """Un-pause the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#unpause
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#unpause
         """
         return self.action(server_id, 'unpause', **kwargs)
 
     def reset_state(self, server_id, **kwargs):
         """Reset the state of a server to active/error.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#resetState
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#resetState
         """
         return self.action(server_id, 'os-resetState', **kwargs)
 
     def shelve_server(self, server_id, **kwargs):
         """Shelve the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#shelve
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#shelve
         """
         return self.action(server_id, 'shelve', **kwargs)
 
     def unshelve_server(self, server_id, **kwargs):
         """Un-shelve the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#unshelve
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#unshelve
         """
         return self.action(server_id, 'unshelve', **kwargs)
 
     def shelve_offload_server(self, server_id, **kwargs):
         """Shelve-offload the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#shelveOffload
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#shelveOffload
         """
         return self.action(server_id, 'shelveOffload', **kwargs)
 
     def get_console_output(self, server_id, **kwargs):
         """Get console output.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#getConsoleOutput
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#getConsoleOutput
         """
         return self.action(server_id, 'os-getConsoleOutput',
                            schema.get_console_output, **kwargs)
@@ -575,16 +612,18 @@
     def rescue_server(self, server_id, **kwargs):
         """Rescue the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#rescue
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#rescue
         """
         return self.action(server_id, 'rescue', schema.rescue_server, **kwargs)
 
     def unrescue_server(self, server_id):
         """Unrescue the provided server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#unrescue
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#unrescue
         """
         return self.action(server_id, 'unrescue')
 
@@ -612,40 +651,45 @@
     def force_delete_server(self, server_id, **kwargs):
         """Force delete a server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#forceDelete
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#forceDelete
         """
         return self.action(server_id, 'forceDelete', **kwargs)
 
     def restore_soft_deleted_server(self, server_id, **kwargs):
         """Restore a soft-deleted server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#restore
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#restore
         """
         return self.action(server_id, 'restore', **kwargs)
 
     def reset_network(self, server_id, **kwargs):
         """Reset the Network of a server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#resetNetwork
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#resetNetwork
         """
         return self.action(server_id, 'resetNetwork', **kwargs)
 
     def inject_network_info(self, server_id, **kwargs):
         """Inject the Network Info into server.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#injectNetworkInfo
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#injectNetworkInfo
         """
         return self.action(server_id, 'injectNetworkInfo', **kwargs)
 
     def get_vnc_console(self, server_id, **kwargs):
         """Get URL of VNC console.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#getVNCConsole
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#getVNCConsole
         """
         return self.action(server_id, "os-getVNCConsole",
                            schema.get_vnc_console, **kwargs)
@@ -653,15 +697,17 @@
     def add_fixed_ip(self, server_id, **kwargs):
         """Add a fixed IP to server instance.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#addFixedIp
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#addFixedIp
         """
         return self.action(server_id, 'addFixedIp', **kwargs)
 
     def remove_fixed_ip(self, server_id, **kwargs):
         """Remove input fixed IP from input server instance.
 
-        Available params: http://developer.openstack.org/
-                          api-ref-compute-v2.1.html#removeFixedIp
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#removeFixedIp
         """
         return self.action(server_id, 'removeFixedIp', **kwargs)
diff --git a/tempest/lib/services/compute/services_client.py b/tempest/lib/services/compute/services_client.py
index b6dbe28..0dbd1b2 100644
--- a/tempest/lib/services/compute/services_client.py
+++ b/tempest/lib/services/compute/services_client.py
@@ -27,8 +27,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listServices
         """
         url = 'os-services'
         if params:
@@ -42,8 +43,9 @@
     def enable_service(self, **kwargs):
         """Enable service on a host.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#enableScheduling
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#enableScheduling
         """
         post_body = json.dumps(kwargs)
         resp, body = self.put('os-services/enable', post_body)
@@ -54,8 +56,9 @@
     def disable_service(self, **kwargs):
         """Disable service on a host.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#disableScheduling
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#disableScheduling
         """
         post_body = json.dumps(kwargs)
         resp, body = self.put('os-services/disable', post_body)
diff --git a/tempest/lib/services/compute/snapshots_client.py b/tempest/lib/services/compute/snapshots_client.py
index be41957..fde5288 100644
--- a/tempest/lib/services/compute/snapshots_client.py
+++ b/tempest/lib/services/compute/snapshots_client.py
@@ -27,8 +27,9 @@
     def create_snapshot(self, volume_id, **kwargs):
         """Create a snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createSnapshot
         """
         post_body = {
             'volume_id': volume_id
diff --git a/tempest/lib/services/compute/tenant_usages_client.py b/tempest/lib/services/compute/tenant_usages_client.py
index 5a748c7..d0eb1c9 100644
--- a/tempest/lib/services/compute/tenant_usages_client.py
+++ b/tempest/lib/services/compute/tenant_usages_client.py
@@ -24,6 +24,12 @@
 class TenantUsagesClient(base_compute_client.BaseComputeClient):
 
     def list_tenant_usages(self, **params):
+        """List Tenant Usage For All Tenants.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/compute/#list-tenant-usage-for-all-tenants
+        """
         url = 'os-simple-tenant-usage'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -34,6 +40,12 @@
         return rest_client.ResponseBody(resp, body)
 
     def show_tenant_usage(self, tenant_id, **params):
+        """Show Usage Details For Tenant.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/compute/#show-usage-details-for-tenant
+        """
         url = 'os-simple-tenant-usage/%s' % tenant_id
         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
index 2787779..b75f22e 100644
--- a/tempest/lib/services/compute/volumes_client.py
+++ b/tempest/lib/services/compute/volumes_client.py
@@ -27,8 +27,9 @@
     def list_volumes(self, detail=False, **params):
         """List all the volumes created.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#listVolumes
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#listVolumes
         """
         url = 'os-volumes'
 
@@ -45,8 +46,9 @@
     def show_volume(self, volume_id):
         """Return the details of a single volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#showVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#showVolume
         """
         url = "os-volumes/%s" % volume_id
         resp, body = self.get(url)
@@ -57,8 +59,9 @@
     def create_volume(self, **kwargs):
         """Create a new Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#createVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html#createVolume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('os-volumes', post_body)
@@ -69,8 +72,9 @@
     def delete_volume(self, volume_id):
         """Delete the Specified Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-compute-v2.1.html#deleteVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        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)
diff --git a/tempest/lib/services/identity/v3/role_assignments_client.py b/tempest/lib/services/identity/v3/role_assignments_client.py
new file mode 100644
index 0000000..10de03f
--- /dev/null
+++ b/tempest/lib/services/identity/v3/role_assignments_client.py
@@ -0,0 +1,48 @@
+# 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 oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class RoleAssignmentsClient(rest_client.RestClient):
+    api_version = "v3"
+
+    def list_role_assignments(self, effective=False, **kwargs):
+        """List role assignments.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/?expanded=list-effective-role-assignments-detail
+
+        :param effective: If True, returns the effective assignments, including
+                          any assignments gained by virtue of group membership
+                          or inherited roles.
+        """
+        url = 'role_assignments'
+        if kwargs:
+            # NOTE(rodrigods): "effective" is a key-only query parameter and
+            # is treated below.
+            if 'effective' in kwargs:
+                del kwargs['effective']
+            url += '?%s' % urllib.urlencode(kwargs)
+        if effective:
+            url += '&effective'
+
+        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/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index 32bad8b..d359d4b 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -15,10 +15,12 @@
 from tempest.lib.services.image.v2.image_members_client import \
     ImageMembersClient
 from tempest.lib.services.image.v2.images_client import ImagesClient
+from tempest.lib.services.image.v2.namespace_properties_client import \
+    NamespacePropertiesClient
 from tempest.lib.services.image.v2.namespaces_client import NamespacesClient
 from tempest.lib.services.image.v2.resource_types_client import \
     ResourceTypesClient
 from tempest.lib.services.image.v2.schemas_client import SchemasClient
 
-__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespacesClient',
-           'ResourceTypesClient', 'SchemasClient']
+__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespacePropertiesClient',
+           'NamespacesClient', 'ResourceTypesClient', 'SchemasClient']
diff --git a/tempest/lib/services/image/v2/namespace_properties_client.py b/tempest/lib/services/image/v2/namespace_properties_client.py
new file mode 100644
index 0000000..1236b2b
--- /dev/null
+++ b/tempest/lib/services/image/v2/namespace_properties_client.py
@@ -0,0 +1,91 @@
+# Copyright 2016 EasyStack.
+# 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 oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class NamespacePropertiesClient(rest_client.RestClient):
+    api_version = "v2"
+
+    def list_namespace_properties(self, namespace):
+        """Lists property definitions in a namespace.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#list-properties
+        """
+        url = 'metadefs/namespaces/%s/properties' % namespace
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def create_namespace_property(self, namespace, **kwargs):
+        """Creates a property definition in a namespace.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-property
+        """
+        url = 'metadefs/namespaces/%s/properties' % namespace
+        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 show_namespace_properties(self, namespace, property_name):
+        """Shows the definition for a property.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#show-property-definition
+        """
+        url = 'metadefs/namespaces/%s/properties/%s' % (namespace,
+                                                        property_name)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_namespace_properties(self, namespace, property_name, **kwargs):
+        """Updates a property definition.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#update-property-definition
+        """
+        url = 'metadefs/namespaces/%s/properties/%s' % (namespace,
+                                                        property_name)
+        data = json.dumps(kwargs)
+        resp, body = self.put(url, data)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_namespace_property(self, namespace, property_name):
+        """Removes a property definition from a namespace.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#remove-property-definition
+        """
+        url = 'metadefs/namespaces/%s/properties/%s' % (namespace,
+                                                        property_name)
+        resp, _ = self.delete(url)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/network/__init__.py b/tempest/lib/services/network/__init__.py
index c466f07..19e5463 100644
--- a/tempest/lib/services/network/__init__.py
+++ b/tempest/lib/services/network/__init__.py
@@ -27,6 +27,8 @@
     SecurityGroupRulesClient
 from tempest.lib.services.network.security_groups_client import \
     SecurityGroupsClient
+from tempest.lib.services.network.service_providers_client import \
+    ServiceProvidersClient
 from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
 from tempest.lib.services.network.subnets_client import SubnetsClient
 from tempest.lib.services.network.versions_client import NetworkVersionsClient
@@ -35,4 +37,5 @@
            'MeteringLabelRulesClient', 'MeteringLabelsClient',
            'NetworksClient', 'PortsClient', 'QuotasClient', 'RoutersClient',
            'SecurityGroupRulesClient', 'SecurityGroupsClient',
-           'SubnetpoolsClient', 'SubnetsClient', 'NetworkVersionsClient']
+           'ServiceProvidersClient', 'SubnetpoolsClient', 'SubnetsClient',
+           'NetworkVersionsClient']
diff --git a/tempest/lib/services/network/service_providers_client.py b/tempest/lib/services/network/service_providers_client.py
new file mode 100644
index 0000000..0ee9bc3
--- /dev/null
+++ b/tempest/lib/services/network/service_providers_client.py
@@ -0,0 +1,21 @@
+#    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.network import base
+
+
+class ServiceProvidersClient(base.BaseNetworkClient):
+
+    def list_service_providers(self, **filters):
+        """Lists service providers."""
+        uri = '/service-providers'
+        return self.list_resources(uri, **filters)
diff --git a/tempest/lib/services/volume/__init__.py b/tempest/lib/services/volume/__init__.py
index e69de29..6855d8e 100644
--- a/tempest/lib/services/volume/__init__.py
+++ b/tempest/lib/services/volume/__init__.py
@@ -0,0 +1,19 @@
+# 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.
+
+from tempest.lib.services.volume import v1
+from tempest.lib.services.volume import v2
+from tempest.lib.services.volume import v3
+
+__all__ = ['v1', 'v2', 'v3']
diff --git a/tempest/lib/services/volume/v1/__init__.py b/tempest/lib/services/volume/v1/__init__.py
index e69de29..7b5991f 100644
--- a/tempest/lib/services/volume/v1/__init__.py
+++ b/tempest/lib/services/volume/v1/__init__.py
@@ -0,0 +1,33 @@
+# 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.
+
+from tempest.lib.services.volume.v1.availability_zone_client \
+    import AvailabilityZoneClient
+from tempest.lib.services.volume.v1.backups_client import BackupsClient
+from tempest.lib.services.volume.v1.encryption_types_client import \
+    EncryptionTypesClient
+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.limits_client import LimitsClient
+from tempest.lib.services.volume.v1.qos_client import QosSpecsClient
+from tempest.lib.services.volume.v1.quotas_client import QuotasClient
+from tempest.lib.services.volume.v1.services_client import ServicesClient
+from tempest.lib.services.volume.v1.snapshots_client import SnapshotsClient
+from tempest.lib.services.volume.v1.types_client import TypesClient
+from tempest.lib.services.volume.v1.volumes_client import VolumesClient
+
+__all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
+           'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
+           'ServicesClient', 'SnapshotsClient', 'TypesClient', 'VolumesClient',
+           'LimitsClient']
diff --git a/tempest/lib/services/volume/v1/backups_client.py b/tempest/lib/services/volume/v1/backups_client.py
index 2728c67..8677913 100644
--- a/tempest/lib/services/volume/v1/backups_client.py
+++ b/tempest/lib/services/volume/v1/backups_client.py
@@ -26,8 +26,9 @@
     def create_backup(self, **kwargs):
         """Creates a backup of volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-backup
         """
         post_body = json.dumps({'backup': kwargs})
         resp, body = self.post('backups', post_body)
@@ -38,8 +39,9 @@
     def restore_backup(self, backup_id, **kwargs):
         """Restore volume from backup.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#restoreBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#restore-backup
         """
         post_body = json.dumps({'restore': kwargs})
         resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
diff --git a/tempest/lib/services/volume/v1/limits_client.py b/tempest/lib/services/volume/v1/limits_client.py
new file mode 100644
index 0000000..e14b2dc
--- /dev/null
+++ b/tempest/lib/services/volume/v1/limits_client.py
@@ -0,0 +1,32 @@
+# Copyright 2016 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class LimitsClient(rest_client.RestClient):
+    """Volume V1 limits client."""
+
+    api_version = "v1"
+
+    def show_limits(self):
+        """Returns the details of a volume absolute limits."""
+        url = "limits"
+        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/lib/services/volume/v1/qos_client.py b/tempest/lib/services/volume/v1/qos_client.py
index 65ae274..e247b7b 100644
--- a/tempest/lib/services/volume/v1/qos_client.py
+++ b/tempest/lib/services/volume/v1/qos_client.py
@@ -41,8 +41,9 @@
     def create_qos(self, **kwargs):
         """Create a QoS Specification.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createQoSSpec
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-qos-specification
         """
         post_body = json.dumps({'qos_specs': kwargs})
         resp, body = self.post('qos-specs', post_body)
@@ -76,8 +77,9 @@
     def set_qos_key(self, qos_id, **kwargs):
         """Set the specified keys/values of QoS specification.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#setQoSKey
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#set-keys-in-qos-specification
         """
         put_body = json.dumps({"qos_specs": kwargs})
         resp, body = self.put('qos-specs/%s' % qos_id, put_body)
diff --git a/tempest/lib/services/volume/v1/snapshots_client.py b/tempest/lib/services/volume/v1/snapshots_client.py
index 1881078..3433e68 100644
--- a/tempest/lib/services/volume/v1/snapshots_client.py
+++ b/tempest/lib/services/volume/v1/snapshots_client.py
@@ -25,8 +25,9 @@
     def list_snapshots(self, detail=False, **params):
         """List all the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#listSnapshots
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#list-snapshots-with-details-v1
         """
         url = 'snapshots'
         if detail:
@@ -42,8 +43,9 @@
     def show_snapshot(self, snapshot_id):
         """Returns the details of a single snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#showSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#show-snapshot-details-v1
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -54,8 +56,9 @@
     def create_snapshot(self, **kwargs):
         """Creates a new snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#createSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#create-snapshot-v1
         """
         post_body = json.dumps({'snapshot': kwargs})
         resp, body = self.post('snapshots', post_body)
@@ -66,8 +69,9 @@
     def delete_snapshot(self, snapshot_id):
         """Delete Snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#deleteSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#delete-snapshot-v1
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -117,9 +121,9 @@
     def update_snapshot(self, snapshot_id, **kwargs):
         """Updates a snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#update-snapshot-v1
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -130,9 +134,9 @@
     def show_snapshot_metadata(self, snapshot_id):
         """Get metadata of the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              showSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#show-snapshot-metadata-v1
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -143,9 +147,9 @@
     def update_snapshot_metadata(self, snapshot_id, **kwargs):
         """Update metadata for the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#update-snapshot-metadata-v1
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v1/types_client.py b/tempest/lib/services/volume/v1/types_client.py
index dce728d..4ae9935 100644
--- a/tempest/lib/services/volume/v1/types_client.py
+++ b/tempest/lib/services/volume/v1/types_client.py
@@ -38,8 +38,9 @@
     def list_volume_types(self, **params):
         """List all the volume_types created.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#listVolumeTypes
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#list-volume-types-v1
         """
         url = 'types'
         if params:
@@ -53,8 +54,9 @@
     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-v1.html#showVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#show-volume-type-v1
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -65,8 +67,9 @@
     def create_volume_type(self, **kwargs):
         """Create volume type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#createVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#create-volume-type-v1
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -77,8 +80,9 @@
     def delete_volume_type(self, volume_type_id):
         """Deletes the Specified Volume_type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#deleteVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#delete-volume-type-v1
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -131,8 +135,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#update-volume-type-v1
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -148,9 +153,9 @@
         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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#update-extra-specs-for-a-volume-type-v1
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
diff --git a/tempest/lib/services/volume/v1/volumes_client.py b/tempest/lib/services/volume/v1/volumes_client.py
index 3df8da4..7a25697 100644
--- a/tempest/lib/services/volume/v1/volumes_client.py
+++ b/tempest/lib/services/volume/v1/volumes_client.py
@@ -22,7 +22,7 @@
 
 
 class VolumesClient(rest_client.RestClient):
-    """Base client class to send CRUD Volume API requests"""
+    """Client class to send CRUD Volume V1 API requests"""
 
     def _prepare_params(self, params):
         """Prepares params for use in get or _ext_get methods.
@@ -61,8 +61,9 @@
     def create_volume(self, **kwargs):
         """Creates a new Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#create-volume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -73,8 +74,9 @@
     def update_volume(self, volume_id, **kwargs):
         """Updates the Specified Volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#updateVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#update-volume
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -100,8 +102,9 @@
     def attach_volume(self, volume_id, **kwargs):
         """Attaches a volume to a given instance on a given mountpoint.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#attachVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#attach-volume
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -156,8 +159,9 @@
     def extend_volume(self, volume_id, **kwargs):
         """Extend a volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#extendVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#extend-volume
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -168,8 +172,9 @@
     def reset_volume_status(self, volume_id, **kwargs):
         """Reset the Specified Volume's Status.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#resetVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#reset-volume-status
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -179,8 +184,9 @@
     def create_volume_transfer(self, **kwargs):
         """Create a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#createVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#create-volume-transfer
         """
         post_body = json.dumps({'transfer': kwargs})
         resp, body = self.post('os-volume-transfer', post_body)
@@ -199,8 +205,9 @@
     def list_volume_transfers(self, **params):
         """List all the volume transfers created.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#listVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#list-volume-transfers
         """
         url = 'os-volume-transfer'
         if params:
@@ -219,8 +226,9 @@
     def accept_volume_transfer(self, transfer_id, **kwargs):
         """Accept a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#acceptVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v1/#accept-volume-transfer
         """
         url = 'os-volume-transfer/%s/accept' % transfer_id
         post_body = json.dumps({'accept': kwargs})
diff --git a/tempest/lib/services/volume/v2/__init__.py b/tempest/lib/services/volume/v2/__init__.py
index e69de29..837b4f6 100644
--- a/tempest/lib/services/volume/v2/__init__.py
+++ b/tempest/lib/services/volume/v2/__init__.py
@@ -0,0 +1,37 @@
+# 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.
+
+from tempest.lib.services.volume.v2.availability_zone_client \
+    import AvailabilityZoneClient
+from tempest.lib.services.volume.v2.backups_client import BackupsClient
+from tempest.lib.services.volume.v2.capabilities_client import \
+    CapabilitiesClient
+from tempest.lib.services.volume.v2.encryption_types_client import \
+    EncryptionTypesClient
+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.limits_client import LimitsClient
+from tempest.lib.services.volume.v2.qos_client import QosSpecsClient
+from tempest.lib.services.volume.v2.quotas_client import QuotasClient
+from tempest.lib.services.volume.v2.scheduler_stats_client import \
+    SchedulerStatsClient
+from tempest.lib.services.volume.v2.services_client import ServicesClient
+from tempest.lib.services.volume.v2.snapshots_client import SnapshotsClient
+from tempest.lib.services.volume.v2.types_client import TypesClient
+from tempest.lib.services.volume.v2.volumes_client import VolumesClient
+
+__all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
+           'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
+           'ServicesClient', 'SnapshotsClient', 'TypesClient', 'VolumesClient',
+           'LimitsClient', 'CapabilitiesClient', 'SchedulerStatsClient']
diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py
index 61f865d..ab5eefd 100644
--- a/tempest/lib/services/volume/v2/backups_client.py
+++ b/tempest/lib/services/volume/v2/backups_client.py
@@ -26,8 +26,9 @@
     def create_backup(self, **kwargs):
         """Creates a backup of volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createBackup
         """
         post_body = json.dumps({'backup': kwargs})
         resp, body = self.post('backups', post_body)
@@ -38,8 +39,9 @@
     def restore_backup(self, backup_id, **kwargs):
         """Restore volume from backup.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#restoreBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#restoreBackup
         """
         post_body = json.dumps({'restore': kwargs})
         resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
diff --git a/tempest/lib/services/volume/v2/capabilities_client.py b/tempest/lib/services/volume/v2/capabilities_client.py
new file mode 100644
index 0000000..b6de5b9
--- /dev/null
+++ b/tempest/lib/services/volume/v2/capabilities_client.py
@@ -0,0 +1,34 @@
+# Copyright 2016 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class CapabilitiesClient(rest_client.RestClient):
+
+    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)
diff --git a/tempest/lib/services/volume/v2/limits_client.py b/tempest/lib/services/volume/v2/limits_client.py
new file mode 100644
index 0000000..ce9fba9
--- /dev/null
+++ b/tempest/lib/services/volume/v2/limits_client.py
@@ -0,0 +1,32 @@
+# Copyright 2016 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class LimitsClient(rest_client.RestClient):
+    """Volume V2 limits client."""
+
+    api_version = "v2"
+
+    def show_limits(self):
+        """Returns the details of a volume absolute limits."""
+        url = "limits"
+        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/lib/services/volume/v2/scheduler_stats_client.py b/tempest/lib/services/volume/v2/scheduler_stats_client.py
new file mode 100644
index 0000000..637254b
--- /dev/null
+++ b/tempest/lib/services/volume/v2/scheduler_stats_client.py
@@ -0,0 +1,35 @@
+# Copyright 2016 Red Hat, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class SchedulerStatsClient(rest_client.RestClient):
+
+    def list_pools(self, detail=False):
+        """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'
+        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/lib/services/volume/v2/snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
index c84e557..6f51b51 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -25,8 +25,9 @@
     def list_snapshots(self, detail=False, **params):
         """List all the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#listSnapshots
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-v2
         """
         url = 'snapshots'
         if detail:
@@ -42,8 +43,9 @@
     def show_snapshot(self, snapshot_id):
         """Returns the details of a single snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#showSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-v2
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -54,8 +56,9 @@
     def create_snapshot(self, **kwargs):
         """Creates a new snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-snapshot
         """
         post_body = json.dumps({'snapshot': kwargs})
         resp, body = self.post('snapshots', post_body)
@@ -66,8 +69,9 @@
     def update_snapshot(self, snapshot_id, **kwargs):
         """Updates a snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#updateSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-v2
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -78,8 +82,9 @@
     def delete_snapshot(self, snapshot_id):
         """Delete Snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#deleteSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot-v2
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -129,9 +134,9 @@
     def show_snapshot_metadata(self, snapshot_id):
         """Get metadata of the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              showSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata-v2
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -142,9 +147,9 @@
     def update_snapshot_metadata(self, snapshot_id, **kwargs):
         """Update metadata for the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata-v2
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v2/types_client.py b/tempest/lib/services/volume/v2/types_client.py
index d399e99..31597d7 100644
--- a/tempest/lib/services/volume/v2/types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -39,8 +39,9 @@
     def list_volume_types(self, **params):
         """List all the volume_types created.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#showVolumeTypes
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types-v2
         """
         url = 'types'
         if params:
@@ -54,8 +55,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-v2
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -66,8 +68,9 @@
     def create_volume_type(self, **kwargs):
         """Create volume type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type-v2
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -78,8 +81,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type-v2
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -132,8 +136,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-v2
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -149,9 +154,9 @@
         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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-extra-specs-v2
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
@@ -163,9 +168,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#add-type-access-v2
         """
         post_body = json.dumps({'addProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -176,9 +181,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#remove-type-access-v2
         """
         post_body = json.dumps({'removeProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -189,9 +194,9 @@
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-type-access-v2
         """
         url = 'types/%s/os-volume-type-access' % volume_type_id
         resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index b1930e1..8b8e249 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from debtcollector import removals
 from oslo_serialization import jsonutils as json
 import six
 from six.moves.urllib import parse as urllib
@@ -62,8 +63,9 @@
     def create_volume(self, **kwargs):
         """Creates a new Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-v2
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -74,8 +76,9 @@
     def update_volume(self, volume_id, **kwargs):
         """Updates the Specified Volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#updateVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-v2
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -101,8 +104,9 @@
     def attach_volume(self, volume_id, **kwargs):
         """Attaches a volume to a given instance on a given mountpoint.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#attachVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-v2
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -157,8 +161,9 @@
     def extend_volume(self, volume_id, **kwargs):
         """Extend a volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#extendVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-v2
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -169,8 +174,9 @@
     def reset_volume_status(self, volume_id, **kwargs):
         """Reset the Specified Volume's Status.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#resetVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-status-v2
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -180,8 +186,9 @@
     def create_volume_transfer(self, **kwargs):
         """Create a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#createVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer-v2
         """
         post_body = json.dumps({'transfer': kwargs})
         resp, body = self.post('os-volume-transfer', post_body)
@@ -200,8 +207,9 @@
     def list_volume_transfers(self, **params):
         """List all the volume transfers created.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#listVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers-v2
         """
         url = 'os-volume-transfer'
         if params:
@@ -220,8 +228,9 @@
     def accept_volume_transfer(self, transfer_id, **kwargs):
         """Accept a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#acceptVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer-v2
         """
         url = 'os-volume-transfer/%s/accept' % transfer_id
         post_body = json.dumps({'accept': kwargs})
@@ -296,9 +305,9 @@
     def update_volume_image_metadata(self, volume_id, **kwargs):
         """Update image metadata for the volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #setVolumeimagemetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-image-metadata-v2
         """
         post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
         url = "volumes/%s/action" % (volume_id)
@@ -315,6 +324,8 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
+    @removals.remove(message="use show_pools from tempest.lib.services."
+                             "volume.v2.scheduler_stats_client")
     def show_pools(self, detail=False):
         # List all the volumes pools (hosts)
         url = 'scheduler-stats/get_pools'
@@ -326,12 +337,14 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
+    @removals.remove(message="use show_backend_capabilities from tempest.lib."
+                             "services.volume.v2.capabilities_client")
     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
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#show_backend_capabilities-v2
         """
         url = 'capabilities/%s' % host
         resp, body = self.get(url)
diff --git a/tempest/services/volume/v3/__init__.py b/tempest/lib/services/volume/v3/__init__.py
similarity index 77%
rename from tempest/services/volume/v3/__init__.py
rename to tempest/lib/services/volume/v3/__init__.py
index d50098c..a4600a8 100644
--- a/tempest/services/volume/v3/__init__.py
+++ b/tempest/lib/services/volume/v3/__init__.py
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-from tempest.services.volume.v3.json.messages_client import MessagesClient
+from tempest.lib.services.volume.v3.base_client import BaseClient
+from tempest.lib.services.volume.v3.messages_client import MessagesClient
 
-__all__ = ['MessagesClient']
+__all__ = ['MessagesClient', 'BaseClient']
diff --git a/tempest/services/volume/base/base_v3_client.py b/tempest/lib/services/volume/v3/base_client.py
similarity index 90%
rename from tempest/services/volume/base/base_v3_client.py
rename to tempest/lib/services/volume/v3/base_client.py
index ad6f760..958212a 100644
--- a/tempest/services/volume/base/base_v3_client.py
+++ b/tempest/lib/services/volume/v3/base_client.py
@@ -19,13 +19,13 @@
 VOLUME_MICROVERSION = None
 
 
-class BaseV3Client(rest_client.RestClient):
+class BaseClient(rest_client.RestClient):
     """Base class to handle Cinder v3 client microversion support."""
     api_version = 'v3'
     api_microversion_header_name = 'Openstack-Api-Version'
 
     def get_headers(self, accept_type=None, send_type=None):
-        headers = super(BaseV3Client, self).get_headers(
+        headers = super(BaseClient, self).get_headers(
             accept_type=accept_type, send_type=send_type)
         if VOLUME_MICROVERSION:
             headers[self.api_microversion_header_name] = ('volume %s' %
@@ -35,7 +35,7 @@
     def request(self, method, url, extra_headers=False, headers=None,
                 body=None, chunked=False):
 
-        resp, resp_body = super(BaseV3Client, self).request(
+        resp, resp_body = super(BaseClient, self).request(
             method, url, extra_headers, headers, body, chunked)
         if (VOLUME_MICROVERSION and
             VOLUME_MICROVERSION != api_version_utils.LATEST_MICROVERSION):
diff --git a/tempest/services/volume/v3/json/messages_client.py b/tempest/lib/services/volume/v3/messages_client.py
similarity index 94%
rename from tempest/services/volume/v3/json/messages_client.py
rename to tempest/lib/services/volume/v3/messages_client.py
index 6be6d59..8a01864 100644
--- a/tempest/services/volume/v3/json/messages_client.py
+++ b/tempest/lib/services/volume/v3/messages_client.py
@@ -17,10 +17,10 @@
 
 from tempest.lib.common import rest_client
 from tempest.lib import exceptions as lib_exc
-from tempest.services.volume.base import base_v3_client
+from tempest.lib.services.volume.v3 import base_client
 
 
-class MessagesClient(base_v3_client.BaseV3Client):
+class MessagesClient(base_client.BaseClient):
     """Client class to send user messages API requests."""
 
     def show_message(self, message_id):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index ab388c2..376dd19 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -26,6 +26,7 @@
 from tempest.common import image as common_image
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
+from tempest.common.utils import net_utils
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
@@ -140,6 +141,9 @@
         if clients is None:
             clients = self.manager
 
+        if name is None:
+            name = data_utils.rand_name(self.__class__.__name__ + "-server")
+
         vnic_type = CONF.network.port_vnic_type
 
         # If vnic_type is configured create port for
@@ -153,7 +157,7 @@
                 # Convert security group names to security group ids
                 # to pass to create_port
                 if 'security_groups' in kwargs:
-                    security_groups =\
+                    security_groups = \
                         clients.security_groups_client.list_security_groups(
                         ).get('security_groups')
                     sec_dict = dict([(s['name'], s['id'])
@@ -215,6 +219,10 @@
                       imageRef=None, volume_type=None):
         if size is None:
             size = CONF.volume.volume_size
+        if imageRef:
+            image = self.compute_images_client.show_image(imageRef)['image']
+            min_disk = image.get('minDisk')
+            size = max(size, min_disk)
         if name is None:
             name = data_utils.rand_name(self.__class__.__name__ + "-volume")
         kwargs = {'display_name': name,
@@ -401,10 +409,14 @@
             servers = self.servers_client.list_servers()
             servers = servers['servers']
         for server in servers:
-            console_output = self.servers_client.get_console_output(
-                server['id'])['output']
-            LOG.debug('Console output for %s\nbody=\n%s',
-                      server['id'], console_output)
+            try:
+                console_output = self.servers_client.get_console_output(
+                    server['id'])['output']
+                LOG.debug('Console output for %s\nbody=\n%s',
+                          server['id'], console_output)
+            except lib_exc.NotFound:
+                LOG.debug("Server %s disappeared(deleted) while looking "
+                          "for the console log", server['id'])
 
     def _log_net_info(self, exc):
         # network debug is called as part of ssh init
@@ -495,9 +507,18 @@
                                            server_id, 'ACTIVE')
 
     def ping_ip_address(self, ip_address, should_succeed=True,
-                        ping_timeout=None):
+                        ping_timeout=None, mtu=None):
         timeout = ping_timeout or CONF.validation.ping_timeout
-        cmd = ['ping', '-c1', '-w1', ip_address]
+        cmd = ['ping', '-c1', '-w1']
+
+        if mtu:
+            cmd += [
+                # don't fragment
+                '-M', 'do',
+                # ping receives just the size of ICMP payload
+                '-s', str(net_utils.get_ping_payload_size(mtu, 4))
+            ]
+        cmd.append(ip_address)
 
         def ping():
             proc = subprocess.Popen(cmd,
@@ -525,7 +546,8 @@
     def check_vm_connectivity(self, ip_address,
                               username=None,
                               private_key=None,
-                              should_connect=True):
+                              should_connect=True,
+                              mtu=None):
         """Check server connectivity
 
         :param ip_address: server to test against
@@ -534,6 +556,7 @@
         :param should_connect: True/False indicates positive/negative test
             positive - attempt ping and ssh
             negative - attempt ping and fail if succeed
+        :param mtu: network MTU to use for connectivity validation
 
         :raises: AssertError if the result of the connectivity check does
             not match the value of the should_connect param
@@ -543,7 +566,8 @@
         else:
             msg = "ip address %s is reachable" % ip_address
         self.assertTrue(self.ping_ip_address(ip_address,
-                                             should_succeed=should_connect),
+                                             should_succeed=should_connect,
+                                             mtu=mtu),
                         msg=msg)
         if should_connect:
             # no need to check ssh for negative connectivity
@@ -551,7 +575,7 @@
 
     def check_public_network_connectivity(self, ip_address, username,
                                           private_key, should_connect=True,
-                                          msg=None, servers=None):
+                                          msg=None, servers=None, mtu=None):
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         LOG.debug('checking network connections to IP %s with user: %s' %
@@ -560,7 +584,8 @@
             self.check_vm_connectivity(ip_address,
                                        username,
                                        private_key,
-                                       should_connect=should_connect)
+                                       should_connect=should_connect,
+                                       mtu=mtu)
         except Exception:
             ex_msg = 'Public network connectivity check failed'
             if msg:
@@ -662,11 +687,6 @@
         if not CONF.service_available.neutron:
             raise cls.skipException('Neutron not available')
 
-    @classmethod
-    def resource_setup(cls):
-        super(NetworkScenarioTest, cls).resource_setup()
-        cls.tenant_id = cls.manager.identity_client.tenant_id
-
     def _create_network(self, networks_client=None,
                         routers_client=None, tenant_id=None,
                         namestart='network-smoke-',
@@ -789,7 +809,7 @@
 
     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.
+        # A port can have more than one IP address in some cases.
         # If the network is dual-stack (IPv4 + IPv6), this port is associated
         # with 2 subnets
         p_status = ['ACTIVE']
@@ -797,7 +817,7 @@
         # 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:
+        if getattr(CONF.service_available, 'ironic', False):
             p_status.append('DOWN')
         port_map = [(p["id"], fxip["ip_address"])
                     for p in ports
@@ -1005,7 +1025,7 @@
             if sg['tenant_id'] == tenant_id and sg['name'] == 'default'
         ]
         msg = "No default security group for tenant %s." % (tenant_id)
-        self.assertTrue(len(sgs) > 0, msg)
+        self.assertGreater(len(sgs), 0, msg)
         return sgs[0]
 
     def _create_security_group_rule(self, secgroup=None,
@@ -1169,7 +1189,7 @@
         :param dns_nameservers: list of dns servers to send to subnet.
         :returns: network, subnet, router
         """
-        if CONF.baremetal.driver_enabled:
+        if CONF.network.shared_physical_network:
             # NOTE(Shrews): This exception is for environments where tenant
             # credential isolation is available, but network separation is
             # not (the current baremetal case). Likely can be removed when
@@ -1210,151 +1230,6 @@
         return network, subnet, router
 
 
-# power/provision states as of icehouse
-class BaremetalPowerStates(object):
-    """Possible power states of an Ironic node."""
-    POWER_ON = 'power on'
-    POWER_OFF = 'power off'
-    REBOOT = 'rebooting'
-    SUSPEND = 'suspended'
-
-
-class BaremetalProvisionStates(object):
-    """Possible provision states of an Ironic node."""
-    NOSTATE = None
-    INIT = 'initializing'
-    ACTIVE = 'active'
-    BUILDING = 'building'
-    DEPLOYWAIT = 'wait call-back'
-    DEPLOYING = 'deploying'
-    DEPLOYFAIL = 'deploy failed'
-    DEPLOYDONE = 'deploy complete'
-    DELETING = 'deleting'
-    DELETED = 'deleted'
-    ERROR = 'error'
-
-
-class BaremetalScenarioTest(ScenarioTest):
-
-    credentials = ['primary', 'admin']
-
-    @classmethod
-    def skip_checks(cls):
-        super(BaremetalScenarioTest, cls).skip_checks()
-        if (not CONF.service_available.ironic or
-           not CONF.baremetal.driver_enabled):
-            msg = 'Ironic not available or Ironic compute driver not enabled'
-            raise cls.skipException(msg)
-
-    @classmethod
-    def setup_clients(cls):
-        super(BaremetalScenarioTest, cls).setup_clients()
-
-        cls.baremetal_client = cls.admin_manager.baremetal_client
-
-    @classmethod
-    def resource_setup(cls):
-        super(BaremetalScenarioTest, cls).resource_setup()
-        # allow any issues obtaining the node list to raise early
-        cls.baremetal_client.list_nodes()
-
-    def _node_state_timeout(self, node_id, state_attr,
-                            target_states, timeout=10, interval=1):
-        if not isinstance(target_states, list):
-            target_states = [target_states]
-
-        def check_state():
-            node = self.get_node(node_id=node_id)
-            if node.get(state_attr) in target_states:
-                return True
-            return False
-
-        if not test_utils.call_until_true(
-            check_state, timeout, interval):
-            msg = ("Timed out waiting for node %s to reach %s state(s) %s" %
-                   (node_id, state_attr, target_states))
-            raise exceptions.TimeoutException(msg)
-
-    def wait_provisioning_state(self, node_id, state, timeout):
-        self._node_state_timeout(
-            node_id=node_id, state_attr='provision_state',
-            target_states=state, timeout=timeout)
-
-    def wait_power_state(self, node_id, state):
-        self._node_state_timeout(
-            node_id=node_id, state_attr='power_state',
-            target_states=state, timeout=CONF.baremetal.power_timeout)
-
-    def wait_node(self, instance_id):
-        """Waits for a node to be associated with instance_id."""
-
-        def _get_node():
-            node = test_utils.call_and_ignore_notfound_exc(
-                self.get_node, instance_id=instance_id)
-            return node is not None
-
-        if not test_utils.call_until_true(
-            _get_node, CONF.baremetal.association_timeout, 1):
-            msg = ('Timed out waiting to get Ironic node by instance id %s'
-                   % instance_id)
-            raise exceptions.TimeoutException(msg)
-
-    def get_node(self, node_id=None, instance_id=None):
-        if node_id:
-            _, body = self.baremetal_client.show_node(node_id)
-            return body
-        elif instance_id:
-            _, body = self.baremetal_client.show_node_by_instance_uuid(
-                instance_id)
-            if body['nodes']:
-                return body['nodes'][0]
-
-    def get_ports(self, node_uuid):
-        ports = []
-        _, body = self.baremetal_client.list_node_ports(node_uuid)
-        for port in body['ports']:
-            _, p = self.baremetal_client.show_port(port['uuid'])
-            ports.append(p)
-        return ports
-
-    def add_keypair(self):
-        self.keypair = self.create_keypair()
-
-    def boot_instance(self):
-        self.instance = self.create_server(
-            key_name=self.keypair['name'])
-
-        self.wait_node(self.instance['id'])
-        self.node = self.get_node(instance_id=self.instance['id'])
-
-        self.wait_power_state(self.node['uuid'], BaremetalPowerStates.POWER_ON)
-
-        self.wait_provisioning_state(
-            self.node['uuid'],
-            [BaremetalProvisionStates.DEPLOYWAIT,
-             BaremetalProvisionStates.ACTIVE],
-            timeout=15)
-
-        self.wait_provisioning_state(self.node['uuid'],
-                                     BaremetalProvisionStates.ACTIVE,
-                                     timeout=CONF.baremetal.active_timeout)
-
-        waiters.wait_for_server_status(self.servers_client,
-                                       self.instance['id'], 'ACTIVE')
-        self.node = self.get_node(instance_id=self.instance['id'])
-        self.instance = (self.servers_client.show_server(self.instance['id'])
-                         ['server'])
-
-    def terminate_instance(self):
-        self.servers_client.delete_server(self.instance['id'])
-        self.wait_power_state(self.node['uuid'],
-                              BaremetalPowerStates.POWER_OFF)
-        self.wait_provisioning_state(
-            self.node['uuid'],
-            BaremetalProvisionStates.NOSTATE,
-            timeout=CONF.baremetal.unprovision_timeout)
-
-
 class EncryptionScenarioTest(ScenarioTest):
     """Base class for encryption scenario tests"""
 
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 43adfb1..8de3561 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -52,7 +52,7 @@
 
     def _get_host_name(self):
         hosts = self.hosts_client.list_hosts()['hosts']
-        self.assertTrue(len(hosts) >= 1)
+        self.assertGreaterEqual(len(hosts), 1)
         computes = [x for x in hosts if x['service'] == 'compute']
         return computes[0]['host_name']
 
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
deleted file mode 100644
index 45c38f6..0000000
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Copyright 2014 Hewlett-Packard Development Company, L.P.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_log import log as logging
-
-from tempest.scenario import manager
-from tempest import test
-
-LOG = logging.getLogger(__name__)
-
-
-class BaremetalBasicOps(manager.BaremetalScenarioTest):
-    """This test tests the pxe_ssh Ironic driver.
-
-    It follows this basic set of operations:
-        * Creates a keypair
-        * Boots an instance using the keypair
-        * Monitors the associated Ironic node for power and
-          expected state transitions
-        * Validates Ironic node's port data has been properly updated
-        * Verifies SSH connectivity using created keypair via fixed IP
-        * Associates a floating ip
-        * Verifies SSH connectivity using created keypair via floating IP
-        * Deletes instance
-        * Monitors the associated Ironic node for power and
-          expected state transitions
-    """
-    def verify_partition(self, client, label, mount, gib_size):
-        """Verify a labeled partition's mount point and size."""
-        LOG.info("Looking for partition %s mounted on %s" % (label, mount))
-
-        # Validate we have a device with the given partition label
-        cmd = "/sbin/blkid | grep '%s' | cut -d':' -f1" % label
-        device = client.exec_command(cmd).rstrip('\n')
-        LOG.debug("Partition device is %s" % device)
-        self.assertNotEqual('', device)
-
-        # Validate the mount point for the device
-        cmd = "mount | grep '%s' | cut -d' ' -f3" % device
-        actual_mount = client.exec_command(cmd).rstrip('\n')
-        LOG.debug("Partition mount point is %s" % actual_mount)
-        self.assertEqual(actual_mount, mount)
-
-        # Validate the partition size matches what we expect
-        numbers = '0123456789'
-        devnum = device.replace('/dev/', '')
-        cmd = "cat /sys/block/%s/%s/size" % (devnum.rstrip(numbers), devnum)
-        num_bytes = client.exec_command(cmd).rstrip('\n')
-        num_bytes = int(num_bytes) * 512
-        actual_gib_size = num_bytes / (1024 * 1024 * 1024)
-        LOG.debug("Partition size is %d GiB" % actual_gib_size)
-        self.assertEqual(actual_gib_size, gib_size)
-
-    def get_flavor_ephemeral_size(self):
-        """Returns size of the ephemeral partition in GiB."""
-        f_id = self.instance['flavor']['id']
-        flavor = self.flavors_client.show_flavor(f_id)['flavor']
-        ephemeral = flavor.get('OS-FLV-EXT-DATA:ephemeral')
-        if not ephemeral or ephemeral == 'N/A':
-            return None
-        return int(ephemeral)
-
-    def validate_ports(self):
-        for port in self.get_ports(self.node['uuid']):
-            n_port_id = port['extra']['vif_port_id']
-            body = self.ports_client.show_port(n_port_id)
-            n_port = body['port']
-            self.assertEqual(n_port['device_id'], self.instance['id'])
-            self.assertEqual(n_port['mac_address'], port['address'])
-
-    @test.idempotent_id('549173a5-38ec-42bb-b0e2-c8b9f4a08943')
-    @test.services('baremetal', 'compute', 'image', 'network')
-    def test_baremetal_server_ops(self):
-        self.add_keypair()
-        self.boot_instance()
-        self.validate_ports()
-        ip_address = self.get_server_ip(self.instance)
-        self.get_remote_client(ip_address).validate_authentication()
-        vm_client = self.get_remote_client(ip_address)
-
-        # We expect the ephemeral partition to be mounted on /mnt and to have
-        # the same size as our flavor definition.
-        eph_size = self.get_flavor_ephemeral_size()
-        if eph_size:
-            self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
-            # Create the test file
-            self.create_timestamp(
-                ip_address, private_key=self.keypair['private_key'])
-
-        self.terminate_instance()
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 3ac6759..c454ae2 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -16,8 +16,8 @@
 from tempest.common import custom_matchers
 from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions
 from tempest.scenario import manager
 from tempest import test
 
@@ -66,10 +66,10 @@
         waiters.wait_for_server_status(self.servers_client,
                                        server['id'], 'ACTIVE')
 
-    def check_partitions(self):
+    def check_disks(self):
         # NOTE(andreaf) The device name may be different on different guest OS
-        partitions = self.linux_client.get_partitions()
-        self.assertEqual(1, partitions.count(CONF.compute.volume_device_name))
+        disks = self.linux_client.get_disks()
+        self.assertEqual(1, disks.count(CONF.compute.volume_device_name))
 
     def create_and_add_security_group_to_server(self, server):
         secgroup = self._create_security_group()
@@ -145,7 +145,7 @@
         self.linux_client = self.get_remote_client(
             floating_ip['ip'], private_key=keypair['private_key'])
 
-        self.check_partitions()
+        self.check_disks()
 
         # delete the floating IP, this should refresh the server addresses
         self.compute_floating_ips_client.delete_floating_ip(floating_ip['id'])
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 60b030d..0605902 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -35,6 +35,12 @@
     """
 
     @classmethod
+    def setup_clients(cls):
+        super(TestNetworkAdvancedServerOps, cls).setup_clients()
+        cls.admin_servers_client = cls.os_adm.servers_client
+        cls.admin_hosts_client = cls.os_adm.hosts_client
+
+    @classmethod
     def skip_checks(cls):
         super(TestNetworkAdvancedServerOps, cls).skip_checks()
         if not (CONF.network.project_networks_reachable
@@ -94,6 +100,10 @@
                                        'ACTIVE')
         self._check_network_connectivity(server, keypair, floating_ip)
 
+    def _get_host_for_server(self, server_id):
+        body = self.admin_servers_client.show_server(server_id)['server']
+        return body['OS-EXT-SRV-ATTR:host']
+
     @test.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
@@ -184,3 +194,29 @@
         self.servers_client.confirm_resize_server(server['id'])
         self._wait_server_status_and_check_network_connectivity(
             server, keypair, floating_ip)
+
+    @test.idempotent_id('a4858f6c-401e-4155-9a49-d5cd053d1a2f')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration is not available.')
+    @test.services('compute', 'network')
+    def test_server_connectivity_cold_migration(self):
+        if CONF.compute.min_compute_nodes < 2:
+            msg = "Less than 2 compute nodes, skipping multinode tests."
+            raise self.skipException(msg)
+
+        keypair = self.create_keypair()
+        server = self._setup_server(keypair)
+        floating_ip = self._setup_network(server, keypair)
+        src_host = self._get_host_for_server(server['id'])
+        self._wait_server_status_and_check_network_connectivity(
+            server, keypair, floating_ip)
+
+        self.admin_servers_client.migrate_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client, server['id'],
+                                       'VERIFY_RESIZE')
+        self.servers_client.confirm_resize_server(server['id'])
+        self._wait_server_status_and_check_network_connectivity(
+            server, keypair, floating_ip)
+        dst_host = self._get_host_for_server(server['id'])
+
+        self.assertNotEqual(src_host, dst_host)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index a295b6a..4bbe4eb 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -19,12 +19,11 @@
 from oslo_log import log as logging
 import testtools
 
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
+from tempest.lib import exceptions
 from tempest.scenario import manager
 from tempest import test
 
@@ -105,8 +104,7 @@
 
     def _setup_network_and_servers(self, **kwargs):
         boot_with_port = kwargs.pop('boot_with_port', False)
-        self.security_group = \
-            self._create_security_group(tenant_id=self.tenant_id)
+        self.security_group = self._create_security_group()
         self.network, self.subnet, self.router = self.create_networks(**kwargs)
         self.check_networks()
 
@@ -117,8 +115,7 @@
             self.port_id = self._create_port(self.network['id'])['id']
             self.ports.append({'port': self.port_id})
 
-        name = data_utils.rand_name('server-smoke')
-        server = self._create_server(name, self.network, self.port_id)
+        server = self._create_server(self.network, self.port_id)
         self._check_tenant_network_connectivity()
 
         floating_ip = self.create_floating_ip(server)
@@ -152,7 +149,7 @@
             self.assertIn(self.router['id'],
                           seen_router_ids)
 
-    def _create_server(self, name, network, port_id=None):
+    def _create_server(self, network, port_id=None):
         keypair = self.create_keypair()
         self.keypairs[keypair['name']] = keypair
         security_groups = [{'name': self.security_group['name']}]
@@ -161,7 +158,6 @@
             network['port'] = port_id
 
         server = self.create_server(
-            name=name,
             networks=[network],
             key_name=keypair['name'],
             security_groups=security_groups,
@@ -183,7 +179,7 @@
 
     def check_public_network_connectivity(
             self, should_connect=True, msg=None,
-            should_check_floating_ip_status=True):
+            should_check_floating_ip_status=True, mtu=None):
         """Verifies connectivty to a VM via public network and floating IP
 
         and verifies floating IP has resource status is correct.
@@ -195,6 +191,7 @@
         to indicate the context of the failure
         :param should_check_floating_ip_status: bool. should status of
         floating_ip be checked or not
+        :param mtu: int. MTU network to use for connectivity validation
         """
         ssh_login = CONF.validation.image_ssh_user
         floating_ip, server = self.floating_ip_tuple
@@ -210,7 +207,7 @@
         # call the common method in the parent class
         super(TestNetworkBasicOps, self).check_public_network_connectivity(
             ip_address, ssh_login, private_key, should_connect, msg,
-            self.servers)
+            self.servers, mtu=mtu)
 
     def _disassociate_floating_ips(self):
         floating_ip, server = self.floating_ip_tuple
@@ -220,15 +217,14 @@
 
     def _reassociate_floating_ips(self):
         floating_ip, server = self.floating_ip_tuple
-        name = data_utils.rand_name('new_server-smoke')
         # create a new server for the floating ip
-        server = self._create_server(name, self.network)
+        server = self._create_server(self.network)
         self._associate_floating_ip(floating_ip, server)
         self.floating_ip_tuple = Floating_IP_tuple(
             floating_ip, server)
 
     def _create_new_network(self, create_gateway=False):
-        self.new_net = self._create_network(tenant_id=self.tenant_id)
+        self.new_net = self._create_network()
         if create_gateway:
             self.new_subnet = self._create_subnet(
                 network=self.new_net)
@@ -410,9 +406,20 @@
                                                msg="after re-associate "
                                                    "floating ip")
 
+    @test.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
+    @testtools.skipUnless(test.is_extension_enabled('net-mtu', 'network'),
+                          'No way to calculate MTU for networks')
+    @test.services('compute', 'network')
+    def test_mtu_sized_frames(self):
+        """Validate that network MTU sized frames fit through."""
+        self._setup_network_and_servers()
+        self.check_public_network_connectivity(
+            should_connect=True, mtu=self.network['mtu'])
+
     @test.idempotent_id('1546850e-fbaa-42f5-8b5f-03d8a6a95f15')
-    @testtools.skipIf(CONF.baremetal.driver_enabled,
-                      'Baremetal relies on a shared physical network.')
+    @testtools.skipIf(CONF.network.shared_physical_network,
+                      'Connectivity can only be tested when in a '
+                      'multitenant network environment')
     @decorators.skip_because(bug="1610994")
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
@@ -449,8 +456,7 @@
         self._check_network_internal_connectivity(network=self.network)
         self._check_network_external_connectivity()
         self._create_new_network(create_gateway=True)
-        name = data_utils.rand_name('server-smoke')
-        self._create_server(name, self.new_net)
+        self._create_server(self.new_net)
         self._check_network_internal_connectivity(network=self.new_net,
                                                   should_connect=False)
         router_id = self.router['id']
@@ -487,9 +493,9 @@
         self._check_network_internal_connectivity(network=self.new_net)
 
     @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
-    @testtools.skipIf(CONF.baremetal.driver_enabled,
-                      'Router state cannot be altered on a shared baremetal '
-                      'network')
+    @testtools.skipIf(CONF.network.shared_physical_network,
+                      'Router state can be altered only with multitenant '
+                      'networks capabilities')
     @test.services('compute', 'network')
     def test_update_router_admin_state(self):
         """Test to update admin state up of router
@@ -519,8 +525,8 @@
             "admin_state_up of router to True")
 
     @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
-    @testtools.skipIf(CONF.baremetal.driver_enabled,
-                      'network isolation not available for baremetal nodes')
+    @testtools.skipIf(CONF.network.shared_physical_network,
+                      'network isolation not available')
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
     @test.services('compute', 'network')
@@ -602,9 +608,6 @@
                             "new DNS nameservers")
 
     @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
-    @testtools.skipIf(CONF.baremetal.driver_enabled,
-                      'admin_state of instance ports cannot be altered '
-                      'for baremetal nodes')
     @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
                           "Changing a port's admin state is not supported "
                           "by the test environment")
@@ -678,8 +681,7 @@
 
         # 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'])
+        server = self._create_server(self.network, port['id'])
         port_list = self._list_ports(device_id=server['id'],
                                      network_id=self.network['id'])
         self.assertEqual(1, len(port_list),
@@ -744,7 +746,6 @@
         self.check_public_network_connectivity(
             should_connect=False,
             msg='after router unscheduling',
-            should_check_floating_ip_status=False
         )
 
         # schedule resource to new agent
@@ -803,8 +804,7 @@
         ssh_client = self.get_remote_client(fip['floating_ip_address'],
                                             private_key=private_key)
         spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
-        name = data_utils.rand_name('peer')
-        peer = self._create_server(name, self.new_net)
+        peer = self._create_server(self.new_net)
         peer_address = peer['addresses'][self.new_net['name']][0]['addr']
         self._check_remote_connectivity(ssh_client, dest=peer_address,
                                         nic=spoof_nic, should_succeed=True)
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index dd86d90..40b3317 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -18,7 +18,6 @@
 
 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
 
@@ -51,8 +50,8 @@
             msg = ('Either project_networks_reachable must be "true", or '
                    'public_network_id must be defined.')
             raise cls.skipException(msg)
-        if CONF.baremetal.driver_enabled:
-            msg = ('Baremetal does not currently support network isolation')
+        if CONF.network.shared_physical_network:
+            msg = 'Deployment uses a shared physical network'
             raise cls.skipException(msg)
 
     @classmethod
@@ -64,7 +63,7 @@
     def setUp(self):
         super(TestGettingAddress, self).setUp()
         self.keypair = self.create_keypair()
-        self.sec_grp = self._create_security_group(tenant_id=self.tenant_id)
+        self.sec_grp = self._create_security_group()
 
     def prepare_network(self, address6_mode, n_subnets6=1, dualnet=False):
         """Prepare network
@@ -75,15 +74,15 @@
         if dualnet - create IPv6 subnets on a different network
         :return: list of created networks
         """
-        self.network = self._create_network(tenant_id=self.tenant_id)
+        self.network = self._create_network()
         if dualnet:
-            self.network_v6 = self._create_network(tenant_id=self.tenant_id)
+            self.network_v6 = self._create_network()
 
         sub4 = self._create_subnet(network=self.network,
                                    namestart='sub4',
                                    ip_version=4)
 
-        router = self._get_router(tenant_id=self.tenant_id)
+        router = self._get_router()
         self.routers_client.add_router_interface(router['id'],
                                                  subnet_id=sub4['id'])
 
@@ -255,7 +254,6 @@
         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 9ac1e30..1d2b2b6 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -18,23 +18,21 @@
 
 
 class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
-    """Test swift basic ops.
-
-     * get swift stat.
-     * create container.
-     * upload a file to the created container.
-     * list container's objects and assure that the uploaded file is present.
-     * download the object and check the content
-     * delete object from container.
-     * list container's objects and assure that the deleted file is gone.
-     * delete a container.
-     * list containers and assure that the deleted container is gone.
-     * change ACL of the container and make sure it works successfully
-    """
-
     @test.idempotent_id('b920faf1-7b8a-4657-b9fe-9c4512bfb381')
     @test.services('object_storage')
     def test_swift_basic_ops(self):
+        """Test swift basic ops.
+
+         * get swift stat.
+         * create container.
+         * upload a file to the created container.
+         * list container's objects and assure that the uploaded file is
+         present.
+         * download the object and check the content
+         * delete object from container.
+         * list container's objects and assure that the deleted file is gone.
+         * delete a container.
+        """
         self.get_swift_stat()
         container_name = self.create_container()
         obj_name, obj_data = self.upload_object_to_container(container_name)
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 32f5d9f..f8c5c0a 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -15,7 +15,6 @@
 from oslo_log import log
 import testtools
 
-from tempest import clients
 from tempest.common.utils import data_utils
 from tempest.common.utils import net_info
 from tempest import config
@@ -113,9 +112,9 @@
             access point
         """
 
-        def __init__(self, credentials):
-            self.manager = clients.Manager(credentials)
+        def __init__(self, clients):
             # Credentials from manager are filled with both names and IDs
+            self.manager = clients
             self.creds = self.manager.credentials
             self.network = None
             self.subnet = None
@@ -131,9 +130,6 @@
     @classmethod
     def skip_checks(cls):
         super(TestSecurityGroupsBasicOps, cls).skip_checks()
-        if CONF.baremetal.driver_enabled:
-            msg = ('Not currently supported by baremetal.')
-            raise cls.skipException(msg)
         if CONF.network.port_vnic_type in ['direct', 'macvtap']:
             msg = ('Not currently supported when using vnic_type'
                    ' direct or macvtap')
@@ -146,17 +142,16 @@
         if not test.is_extension_enabled('security-group', 'network'):
             msg = "security-group extension not enabled."
             raise cls.skipException(msg)
+        if CONF.network.shared_physical_network:
+            msg = ('Deployment uses a shared physical network, security '
+                   'groups not supported')
+            raise cls.skipException(msg)
 
     @classmethod
     def setup_credentials(cls):
         # Create no network resources for these tests.
         cls.set_network_resources()
         super(TestSecurityGroupsBasicOps, cls).setup_credentials()
-        # TODO(mnewby) Consider looking up entities as needed instead
-        # of storing them as collections on the class.
-
-        # Credentials from the manager are filled with both IDs and Names
-        cls.alt_creds = cls.alt_manager.credentials
 
     @classmethod
     def resource_setup(cls):
@@ -171,9 +166,8 @@
 
         cls.floating_ips = {}
         cls.tenants = {}
-        creds = cls.manager.credentials
-        cls.primary_tenant = cls.TenantProperties(creds)
-        cls.alt_tenant = cls.TenantProperties(cls.alt_creds)
+        cls.primary_tenant = cls.TenantProperties(cls.os)
+        cls.alt_tenant = cls.TenantProperties(cls.os_alt)
         for tenant in [cls.primary_tenant, cls.alt_tenant]:
             cls.tenants[tenant.creds.tenant_id] = tenant
 
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index e031ff7..2d2f7df 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -16,9 +16,10 @@
 import json
 import re
 
+from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions
 from tempest.scenario import manager
 from tempest import test
 
@@ -119,14 +120,13 @@
     @test.services('compute', 'network')
     def test_server_basic_ops(self):
         keypair = self.create_keypair()
-        self.security_group = self._create_security_group()
-        security_groups = [{'name': self.security_group['name']}]
+        security_group = self._create_security_group()
         self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
         self.instance = self.create_server(
             image_id=self.image_ref,
             flavor=self.flavor_ref,
             key_name=keypair['name'],
-            security_groups=security_groups,
+            security_groups=[{'name': security_group['name']}],
             config_drive=CONF.compute_feature_enabled.config_drive,
             metadata=self.md,
             wait_until='ACTIVE')
@@ -135,3 +135,5 @@
         self.verify_metadata_on_config_drive()
         self.verify_networkdata_on_config_drive()
         self.servers_client.delete_server(self.instance['id'])
+        waiters.wait_for_server_termination(
+            self.servers_client, self.instance['id'], ignore_error=False)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 5fd934c..dff00e7 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -21,7 +21,6 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -86,14 +85,14 @@
         ssh = self.get_remote_client(ip_address, private_key=private_key)
 
         def _func():
-            part = ssh.get_partitions()
-            LOG.debug("Partitions:%s" % part)
-            return CONF.compute.volume_device_name in part
+            disks = ssh.get_disks()
+            LOG.debug("Disks: %s" % disks)
+            return CONF.compute.volume_device_name in disks
 
         if not test_utils.call_until_true(_func,
                                           CONF.compute.build_timeout,
                                           CONF.compute.build_interval):
-            raise exceptions.TimeoutException
+            raise lib_exc.TimeoutException
 
     @decorators.skip_because(bug="1205344")
     @test.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index db5e009..46aebfe 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -148,10 +148,13 @@
 
         # create a 3rd instance from snapshot
         LOG.info("Creating third instance from snapshot: %s" % snapshot['id'])
-        volume = self.create_volume(snapshot_id=snapshot['id'])
+        volume = self.create_volume(snapshot_id=snapshot['id'],
+                                    size=snapshot['size'])
+        LOG.info("Booting third instance from snapshot")
         server_from_snapshot = (
             self._boot_instance_from_volume(volume['id'],
                                             keypair, security_group))
+        LOG.info("Booted third instance %s", server_from_snapshot)
 
         # check the content of written file
         LOG.info("Logging into third instance to get timestamp: %s" %
diff --git a/tempest/services/baremetal/__init__.py b/tempest/services/baremetal/__init__.py
deleted file mode 100644
index 390f40a..0000000
--- a/tempest/services/baremetal/__init__.py
+++ /dev/null
@@ -1,18 +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.
-
-from tempest.services.baremetal.v1.json.baremetal_client import \
-    BaremetalClient
-
-__all__ = ['BaremetalClient']
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
deleted file mode 100644
index 2bdd092..0000000
--- a/tempest/services/baremetal/base.py
+++ /dev/null
@@ -1,205 +0,0 @@
-#    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 functools
-
-from oslo_serialization import jsonutils as json
-import six
-from six.moves.urllib import parse as urllib
-
-from tempest.lib.common import rest_client
-
-
-def handle_errors(f):
-    """A decorator that allows to ignore certain types of errors."""
-
-    @functools.wraps(f)
-    def wrapper(*args, **kwargs):
-        param_name = 'ignore_errors'
-        ignored_errors = kwargs.get(param_name, tuple())
-
-        if param_name in kwargs:
-            del kwargs[param_name]
-
-        try:
-            return f(*args, **kwargs)
-        except ignored_errors:
-            # Silently ignore errors
-            pass
-
-    return wrapper
-
-
-class BaremetalClient(rest_client.RestClient):
-    """Base Tempest REST client for Ironic API."""
-
-    uri_prefix = ''
-
-    def serialize(self, object_dict):
-        """Serialize an Ironic object."""
-
-        return json.dumps(object_dict)
-
-    def deserialize(self, object_str):
-        """Deserialize an Ironic object."""
-
-        return json.loads(object_str)
-
-    def _get_uri(self, resource_name, uuid=None, permanent=False):
-        """Get URI for a specific resource or object.
-
-        :param resource_name: The name of the REST resource, e.g., 'nodes'.
-        :param uuid: The unique identifier of an object in UUID format.
-        :returns: Relative URI for the resource or object.
-
-        """
-        prefix = self.uri_prefix if not permanent else ''
-
-        return '{pref}/{res}{uuid}'.format(pref=prefix,
-                                           res=resource_name,
-                                           uuid='/%s' % uuid if uuid else '')
-
-    def _make_patch(self, allowed_attributes, **kwargs):
-        """Create a JSON patch according to RFC 6902.
-
-        :param allowed_attributes: An iterable object that contains a set of
-            allowed attributes for an object.
-        :param **kwargs: Attributes and new values for them.
-        :returns: A JSON path that sets values of the specified attributes to
-            the new ones.
-
-        """
-        def get_change(kwargs, path='/'):
-            for name, value in six.iteritems(kwargs):
-                if isinstance(value, dict):
-                    for ch in get_change(value, path + '%s/' % name):
-                        yield ch
-                else:
-                    if value is None:
-                        yield {'path': path + name,
-                               'op': 'remove'}
-                    else:
-                        yield {'path': path + name,
-                               'value': value,
-                               'op': 'replace'}
-
-        patch = [ch for ch in get_change(kwargs)
-                 if ch['path'].lstrip('/') in allowed_attributes]
-
-        return patch
-
-    def _list_request(self, resource, permanent=False, **kwargs):
-        """Get the list of objects of the specified type.
-
-        :param resource: The name of the REST resource, e.g., 'nodes'.
-        :param **kwargs: Parameters for the request.
-        :returns: A tuple with the server response and deserialized JSON list
-                 of objects
-
-        """
-        uri = self._get_uri(resource, permanent=permanent)
-        if kwargs:
-            uri += "?%s" % urllib.urlencode(kwargs)
-
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-
-        return resp, self.deserialize(body)
-
-    def _show_request(self, resource, uuid, permanent=False, **kwargs):
-        """Gets a specific object of the specified type.
-
-        :param uuid: Unique identifier of the object in UUID format.
-        :returns: Serialized object as a dictionary.
-
-        """
-        if 'uri' in kwargs:
-            uri = kwargs['uri']
-        else:
-            uri = self._get_uri(resource, uuid=uuid, permanent=permanent)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-
-        return resp, self.deserialize(body)
-
-    def _create_request(self, resource, object_dict):
-        """Create an object of the specified type.
-
-        :param resource: The name of the REST resource, e.g., 'nodes'.
-        :param object_dict: A Python dict that represents an object of the
-                            specified type.
-        :returns: A tuple with the server response and the deserialized created
-                 object.
-
-        """
-        body = self.serialize(object_dict)
-        uri = self._get_uri(resource)
-
-        resp, body = self.post(uri, body=body)
-        self.expected_success(201, resp.status)
-
-        return resp, self.deserialize(body)
-
-    def _delete_request(self, resource, uuid):
-        """Delete specified object.
-
-        :param resource: The name of the REST resource, e.g., 'nodes'.
-        :param uuid: The unique identifier of an object in UUID format.
-        :returns: A tuple with the server response and the response body.
-
-        """
-        uri = self._get_uri(resource, uuid)
-
-        resp, body = self.delete(uri)
-        self.expected_success(204, resp.status)
-        return resp, body
-
-    def _patch_request(self, resource, uuid, patch_object):
-        """Update specified object with JSON-patch.
-
-        :param resource: The name of the REST resource, e.g., 'nodes'.
-        :param uuid: The unique identifier of an object in UUID format.
-        :returns: A tuple with the server response and the serialized patched
-                 object.
-
-        """
-        uri = self._get_uri(resource, uuid)
-        patch_body = json.dumps(patch_object)
-
-        resp, body = self.patch(uri, body=patch_body)
-        self.expected_success(200, resp.status)
-        return resp, self.deserialize(body)
-
-    @handle_errors
-    def get_api_description(self):
-        """Retrieves all versions of the Ironic API."""
-
-        return self._list_request('', permanent=True)
-
-    @handle_errors
-    def get_version_description(self, version='v1'):
-        """Retrieves the desctription of the API.
-
-        :param version: The version of the API. Default: 'v1'.
-        :returns: Serialized description of API resources.
-
-        """
-        return self._list_request(version, permanent=True)
-
-    def _put_request(self, resource, put_object):
-        """Update specified object with JSON-patch."""
-        uri = self._get_uri(resource)
-        put_body = json.dumps(put_object)
-
-        resp, body = self.put(uri, body=put_body)
-        self.expected_success([202, 204], resp.status)
-        return resp, body
diff --git a/tempest/services/baremetal/v1/__init__.py b/tempest/services/baremetal/v1/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/baremetal/v1/__init__.py
+++ /dev/null
diff --git a/tempest/services/baremetal/v1/json/__init__.py b/tempest/services/baremetal/v1/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/baremetal/v1/json/__init__.py
+++ /dev/null
diff --git a/tempest/services/baremetal/v1/json/baremetal_client.py b/tempest/services/baremetal/v1/json/baremetal_client.py
deleted file mode 100644
index 7405871..0000000
--- a/tempest/services/baremetal/v1/json/baremetal_client.py
+++ /dev/null
@@ -1,362 +0,0 @@
-#    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.baremetal import base
-
-
-class BaremetalClient(base.BaremetalClient):
-    """Base Tempest REST client for Ironic API v1."""
-    version = '1'
-    uri_prefix = 'v1'
-
-    @base.handle_errors
-    def list_nodes(self, **kwargs):
-        """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
-    def list_chassis(self):
-        """List all existing chassis."""
-        return self._list_request('chassis')
-
-    @base.handle_errors
-    def list_chassis_nodes(self, chassis_uuid):
-        """List all nodes associated with a chassis."""
-        return self._list_request('/chassis/%s/nodes' % chassis_uuid)
-
-    @base.handle_errors
-    def list_ports(self, **kwargs):
-        """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
-    def list_node_ports(self, uuid):
-        """List all ports associated with the node."""
-        return self._list_request('/nodes/%s/ports' % uuid)
-
-    @base.handle_errors
-    def list_nodestates(self, uuid):
-        """List all existing states."""
-        return self._list_request('/nodes/%s/states' % uuid)
-
-    @base.handle_errors
-    def list_ports_detail(self, **kwargs):
-        """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
-    def list_drivers(self):
-        """List all existing drivers."""
-        return self._list_request('drivers')
-
-    @base.handle_errors
-    def show_node(self, uuid):
-        """Gets a specific node.
-
-        :param uuid: Unique identifier of the node in UUID format.
-        :return: Serialized node as a dictionary.
-
-        """
-        return self._show_request('nodes', uuid)
-
-    @base.handle_errors
-    def show_node_by_instance_uuid(self, instance_uuid):
-        """Gets a node associated with given instance uuid.
-
-        :param instance_uuid: Unique identifier of the instance in UUID format.
-        :return: Serialized node as a dictionary.
-
-        """
-        uri = '/nodes/detail?instance_uuid=%s' % instance_uuid
-
-        return self._show_request('nodes',
-                                  uuid=None,
-                                  uri=uri)
-
-    @base.handle_errors
-    def show_chassis(self, uuid):
-        """Gets a specific chassis.
-
-        :param uuid: Unique identifier of the chassis in UUID format.
-        :return: Serialized chassis as a dictionary.
-
-        """
-        return self._show_request('chassis', uuid)
-
-    @base.handle_errors
-    def show_port(self, uuid):
-        """Gets a specific port.
-
-        :param uuid: Unique identifier of the port in UUID format.
-        :return: Serialized port as a dictionary.
-
-        """
-        return self._show_request('ports', uuid)
-
-    @base.handle_errors
-    def show_port_by_address(self, address):
-        """Gets a specific port by address.
-
-        :param address: MAC address of the port.
-        :return: Serialized port as a dictionary.
-
-        """
-        uri = '/ports/detail?address=%s' % address
-
-        return self._show_request('ports', uuid=None, uri=uri)
-
-    def show_driver(self, driver_name):
-        """Gets a specific driver.
-
-        :param driver_name: Name of driver.
-        :return: Serialized driver as a dictionary.
-        """
-        return self._show_request('drivers', driver_name)
-
-    @base.handle_errors
-    def create_node(self, chassis_id=None, **kwargs):
-        """Create a baremetal node with the specified parameters.
-
-        :param chassis_id: The unique identifier of the chassis.
-        :param cpu_arch: CPU architecture of the node. Default: x86_64.
-        :param cpus: Number of CPUs. Default: 8.
-        :param local_gb: Disk size. Default: 1024.
-        :param memory_mb: Available RAM. Default: 4096.
-        :param driver: Driver name. Default: "fake"
-        :return: A tuple with the server response and the created node.
-
-        """
-        node = {'chassis_uuid': chassis_id,
-                'properties': {'cpu_arch': kwargs.get('cpu_arch', 'x86_64'),
-                               'cpus': kwargs.get('cpus', 8),
-                               'local_gb': kwargs.get('local_gb', 1024),
-                               'memory_mb': kwargs.get('memory_mb', 4096)},
-                'driver': kwargs.get('driver', 'fake')}
-
-        return self._create_request('nodes', node)
-
-    @base.handle_errors
-    def create_chassis(self, **kwargs):
-        """Create a chassis with the specified parameters.
-
-        :param description: The description of the chassis.
-            Default: test-chassis
-        :return: A tuple with the server response and the created chassis.
-
-        """
-        chassis = {'description': kwargs.get('description', 'test-chassis')}
-
-        return self._create_request('chassis', chassis)
-
-    @base.handle_errors
-    def create_port(self, node_id, **kwargs):
-        """Create a port with the specified parameters.
-
-        :param node_id: The ID of the node which owns the port.
-        :param address: MAC address of the port.
-        :param extra: Meta data of the port. Default: {'foo': 'bar'}.
-        :param uuid: UUID of the port.
-        :return: A tuple with the server response and the created port.
-
-        """
-        port = {'extra': kwargs.get('extra', {'foo': 'bar'}),
-                'uuid': kwargs['uuid']}
-
-        if node_id is not None:
-            port['node_uuid'] = node_id
-
-        if kwargs['address'] is not None:
-            port['address'] = kwargs['address']
-
-        return self._create_request('ports', port)
-
-    @base.handle_errors
-    def delete_node(self, uuid):
-        """Deletes a node having the specified UUID.
-
-        :param uuid: The unique identifier of the node.
-        :return: A tuple with the server response and the response body.
-
-        """
-        return self._delete_request('nodes', uuid)
-
-    @base.handle_errors
-    def delete_chassis(self, uuid):
-        """Deletes a chassis having the specified UUID.
-
-        :param uuid: The unique identifier of the chassis.
-        :return: A tuple with the server response and the response body.
-
-        """
-        return self._delete_request('chassis', uuid)
-
-    @base.handle_errors
-    def delete_port(self, uuid):
-        """Deletes a port having the specified UUID.
-
-        :param uuid: The unique identifier of the port.
-        :return: A tuple with the server response and the response body.
-
-        """
-        return self._delete_request('ports', uuid)
-
-    @base.handle_errors
-    def update_node(self, uuid, **kwargs):
-        """Update the specified node.
-
-        :param uuid: The unique identifier of the node.
-        :return: A tuple with the server response and the updated node.
-
-        """
-        node_attributes = ('properties/cpu_arch',
-                           'properties/cpus',
-                           'properties/local_gb',
-                           'properties/memory_mb',
-                           'driver',
-                           'instance_uuid')
-
-        patch = self._make_patch(node_attributes, **kwargs)
-
-        return self._patch_request('nodes', uuid, patch)
-
-    @base.handle_errors
-    def update_chassis(self, uuid, **kwargs):
-        """Update the specified chassis.
-
-        :param uuid: The unique identifier of the chassis.
-        :return: A tuple with the server response and the updated chassis.
-
-        """
-        chassis_attributes = ('description',)
-        patch = self._make_patch(chassis_attributes, **kwargs)
-
-        return self._patch_request('chassis', uuid, patch)
-
-    @base.handle_errors
-    def update_port(self, uuid, patch):
-        """Update the specified port.
-
-        :param uuid: The unique identifier of the port.
-        :param patch: List of dicts representing json patches.
-        :return: A tuple with the server response and the updated port.
-
-        """
-
-        return self._patch_request('ports', uuid, patch)
-
-    @base.handle_errors
-    def set_node_power_state(self, node_uuid, state):
-        """Set power state of the specified node.
-
-        :param node_uuid: The unique identifier of the node.
-        :param state: desired state to set (on/off/reboot).
-
-        """
-        target = {'target': state}
-        return self._put_request('nodes/%s/states/power' % node_uuid,
-                                 target)
-
-    @base.handle_errors
-    def validate_driver_interface(self, node_uuid):
-        """Get all driver interfaces of a specific node.
-
-        :param node_uuid: Unique identifier of the node in UUID format.
-
-        """
-
-        uri = '{pref}/{res}/{uuid}/{postf}'.format(pref=self.uri_prefix,
-                                                   res='nodes',
-                                                   uuid=node_uuid,
-                                                   postf='validate')
-
-        return self._show_request('nodes', node_uuid, uri=uri)
-
-    @base.handle_errors
-    def set_node_boot_device(self, node_uuid, boot_device, persistent=False):
-        """Set the boot device of the specified node.
-
-        :param node_uuid: The unique identifier of the node.
-        :param boot_device: The boot device name.
-        :param persistent: Boolean value. True if the boot device will
-                           persist to all future boots, False if not.
-                           Default: False.
-
-        """
-        request = {'boot_device': boot_device, 'persistent': persistent}
-        resp, body = self._put_request('nodes/%s/management/boot_device' %
-                                       node_uuid, request)
-        self.expected_success(204, resp.status)
-        return body
-
-    @base.handle_errors
-    def get_node_boot_device(self, node_uuid):
-        """Get the current boot device of the specified node.
-
-        :param node_uuid: The unique identifier of the node.
-
-        """
-        path = 'nodes/%s/management/boot_device' % node_uuid
-        resp, body = self._list_request(path)
-        self.expected_success(200, resp.status)
-        return body
-
-    @base.handle_errors
-    def get_node_supported_boot_devices(self, node_uuid):
-        """Get the supported boot devices of the specified node.
-
-        :param node_uuid: The unique identifier of the node.
-
-        """
-        path = 'nodes/%s/management/boot_device/supported' % node_uuid
-        resp, body = self._list_request(path)
-        self.expected_success(200, resp.status)
-        return body
-
-    @base.handle_errors
-    def get_console(self, node_uuid):
-        """Get connection information about the console.
-
-        :param node_uuid: Unique identifier of the node in UUID format.
-
-        """
-
-        resp, body = self._show_request('nodes/states/console', node_uuid)
-        self.expected_success(200, resp.status)
-        return resp, body
-
-    @base.handle_errors
-    def set_console_mode(self, node_uuid, enabled):
-        """Start and stop the node console.
-
-        :param node_uuid: Unique identifier of the node in UUID format.
-        :param enabled: Boolean value; whether to enable or disable the
-                        console.
-
-        """
-
-        enabled = {'enabled': enabled}
-        resp, body = self._put_request('nodes/%s/states/console' % node_uuid,
-                                       enabled)
-        self.expected_success(202, resp.status)
-        return resp, body
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
index 9b40b77..6e64a7d 100644
--- a/tempest/services/identity/v3/__init__.py
+++ b/tempest/services/identity/v3/__init__.py
@@ -22,14 +22,14 @@
 from tempest.lib.services.identity.v3.policies_client import PoliciesClient
 from tempest.lib.services.identity.v3.projects_client import ProjectsClient
 from tempest.lib.services.identity.v3.regions_client import RegionsClient
+from tempest.lib.services.identity.v3.role_assignments_client import \
+    RoleAssignmentsClient
 from tempest.lib.services.identity.v3.roles_client import RolesClient
 from tempest.lib.services.identity.v3.services_client import ServicesClient
 from tempest.lib.services.identity.v3.token_client import V3TokenClient
 from tempest.lib.services.identity.v3.trusts_client import TrustsClient
 from tempest.lib.services.identity.v3.users_client import UsersClient
 from tempest.services.identity.v3.json.domains_client import DomainsClient
-from tempest.services.identity.v3.json.role_assignments_client import \
-    RoleAssignmentsClient
 
 __all__ = ['CredentialsClient', 'EndPointsClient', 'GroupsClient',
            'IdentityClient', 'InheritedRolesClient', 'PoliciesClient',
diff --git a/tempest/services/identity/v3/json/domains_client.py b/tempest/services/identity/v3/json/domains_client.py
index fe929a5..43cb62c 100644
--- a/tempest/services/identity/v3/json/domains_client.py
+++ b/tempest/services/identity/v3/json/domains_client.py
@@ -21,29 +21,36 @@
 class DomainsClient(rest_client.RestClient):
     api_version = "v3"
 
-    def create_domain(self, name, **kwargs):
-        """Creates a domain."""
-        description = kwargs.get('description', None)
-        en = kwargs.get('enabled', True)
-        post_body = {
-            'description': description,
-            'enabled': en,
-            'name': name
-        }
-        post_body = json.dumps({'domain': post_body})
+    def create_domain(self, **kwargs):
+        """Creates a domain.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#create-domain
+        """
+        post_body = json.dumps({'domain': kwargs})
         resp, body = self.post('domains', post_body)
         self.expected_success(201, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
     def delete_domain(self, domain_id):
-        """Deletes a domain."""
+        """Deletes a domain.
+
+        For APi details, please refer to the official API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#delete-domain
+        """
         resp, body = self.delete('domains/%s' % domain_id)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def list_domains(self, params=None):
-        """List Domains."""
+    def list_domains(self, **params):
+        """List Domains.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#list-domains
+        """
         url = 'domains'
         if params:
             url += '?%s' % urllib.urlencode(params)
@@ -53,24 +60,24 @@
         return rest_client.ResponseBody(resp, body)
 
     def update_domain(self, domain_id, **kwargs):
-        """Updates a domain."""
-        body = self.show_domain(domain_id)['domain']
-        description = kwargs.get('description', body['description'])
-        en = kwargs.get('enabled', body['enabled'])
-        name = kwargs.get('name', body['name'])
-        post_body = {
-            'description': description,
-            'enabled': en,
-            'name': name
-        }
-        post_body = json.dumps({'domain': post_body})
+        """Updates a domain.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#update-domain
+        """
+        post_body = json.dumps({'domain': kwargs})
         resp, body = self.patch('domains/%s' % domain_id, post_body)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
     def show_domain(self, domain_id):
-        """Get Domain details."""
+        """Get Domain details.
+
+        For API details, please refer to the official API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#show-domain-details
+        """
         resp, body = self.get('domains/%s' % domain_id)
         self.expected_success(200, resp.status)
         body = json.loads(body)
diff --git a/tempest/services/identity/v3/json/role_assignments_client.py b/tempest/services/identity/v3/json/role_assignments_client.py
deleted file mode 100644
index 9fd7736..0000000
--- a/tempest/services/identity/v3/json/role_assignments_client.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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 oslo_serialization import jsonutils as json
-
-from tempest.lib.common import rest_client
-
-
-class RoleAssignmentsClient(rest_client.RestClient):
-    api_version = "v3"
-
-    def list_user_project_effective_assignments(
-            self, project_id, user_id):
-        """List the effective role assignments for a user in a project."""
-        resp, body = self.get(
-            "role_assignments?scope.project.id=%s&user.id=%s&effective" %
-            (project_id, user_id))
-        self.expected_success(200, resp.status)
-        body = json.loads(body)
-        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/object_storage/__init__.py b/tempest/services/object_storage/__init__.py
index 96fe4a3..d1a61d6 100644
--- a/tempest/services/object_storage/__init__.py
+++ b/tempest/services/object_storage/__init__.py
@@ -13,7 +13,10 @@
 # the License.
 
 from tempest.services.object_storage.account_client import AccountClient
+from tempest.services.object_storage.capabilities_client import \
+    CapabilitiesClient
 from tempest.services.object_storage.container_client import ContainerClient
 from tempest.services.object_storage.object_client import ObjectClient
 
-__all__ = ['AccountClient', 'ContainerClient', 'ObjectClient']
+__all__ = ['AccountClient', 'CapabilitiesClient', 'ContainerClient',
+           'ObjectClient']
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 6012a92..9932b4a 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -144,13 +144,3 @@
             body = body.strip().splitlines()
         self.expected_success([200, 204], resp.status)
         return resp, body
-
-    def list_extensions(self):
-        self.skip_path()
-        try:
-            resp, body = self.get('info')
-        finally:
-            self.reset_path()
-        body = json.loads(body)
-        self.expected_success(200, resp.status)
-        return resp, body
diff --git a/tempest/services/object_storage/capabilities_client.py b/tempest/services/object_storage/capabilities_client.py
new file mode 100644
index 0000000..0fe437f
--- /dev/null
+++ b/tempest/services/object_storage/capabilities_client.py
@@ -0,0 +1,31 @@
+# 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 oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class CapabilitiesClient(rest_client.RestClient):
+
+    def list_capabilities(self):
+        self.skip_path()
+        try:
+            resp, body = self.get('info')
+        finally:
+            self.reset_path()
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return resp, body
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index 5a26bfc..2509156 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -96,28 +96,6 @@
         self.expected_success(204, resp.status)
         return resp, body
 
-    def list_all_container_objects(self, container, params=None):
-        """Returns complete list of all objects in the container
-
-        even if item count is beyond 10,000 item listing limit.
-        Does not require any parameters aside from container name.
-        """
-        # TODO(dwalleck): Rewrite using json format to avoid newlines at end of
-        # obj names. Set limit to API limit - 1 (max returned items = 9999)
-        limit = 9999
-        if params is not None:
-            if 'limit' in params:
-                limit = params['limit']
-
-            if 'marker' in params:
-                limit = params['marker']
-
-        resp, objlist = self.list_container_contents(
-            container,
-            params={'limit': limit, 'format': 'json'})
-        self.expected_success(200, resp.status)
-        return objlist
-
     def list_container_contents(self, container, params=None):
         """List the objects in a container, given the container name
 
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index ea5dbe5..9fec548 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -178,7 +178,7 @@
                            'within the required time (%s s).' %
                            (stack_name, status, stack_status,
                             self.build_timeout))
-                raise exceptions.TimeoutException(message)
+                raise lib_exc.TimeoutException(message)
             time.sleep(self.build_interval)
 
     def show_resource_metadata(self, stack_identifier, resource_name):
diff --git a/tempest/services/volume/__init__.py b/tempest/services/volume/__init__.py
deleted file mode 100644
index 4d29cdd..0000000
--- a/tempest/services/volume/__init__.py
+++ /dev/null
@@ -1,19 +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.
-
-from tempest.services.volume import v1
-from tempest.services.volume import v2
-from tempest.services.volume import v3
-
-__all__ = ['v1', 'v2', 'v3']
diff --git a/tempest/services/volume/base/__init__.py b/tempest/services/volume/base/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/base/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/v1/__init__.py b/tempest/services/volume/v1/__init__.py
deleted file mode 100644
index 7fb3ed3..0000000
--- a/tempest/services/volume/v1/__init__.py
+++ /dev/null
@@ -1,33 +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.
-
-from tempest.lib.services.volume.v1.availability_zone_client import \
-    AvailabilityZoneClient
-from tempest.lib.services.volume.v1.backups_client import BackupsClient
-from tempest.lib.services.volume.v1.encryption_types_client import \
-    EncryptionTypesClient
-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.qos_client import QosSpecsClient
-from tempest.lib.services.volume.v1.quotas_client import QuotasClient
-from tempest.lib.services.volume.v1.services_client import ServicesClient
-from tempest.lib.services.volume.v1.snapshots_client import SnapshotsClient
-from tempest.lib.services.volume.v1.types_client import TypesClient
-from tempest.lib.services.volume.v1.volumes_client import VolumesClient
-
-__all__ = ['AvailabilityZoneClient', 'EncryptionTypesClient',
-           'ExtensionsClient', 'HostsClient', 'QuotasClient',
-           'QosSpecsClient', 'ServicesClient',
-           'SnapshotsClient', 'TypesClient', 'BackupsClient',
-           'VolumesClient', ]
diff --git a/tempest/services/volume/v1/json/__init__.py b/tempest/services/volume/v1/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/v1/json/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/v2/__init__.py b/tempest/services/volume/v2/__init__.py
deleted file mode 100644
index 8edaf2a..0000000
--- a/tempest/services/volume/v2/__init__.py
+++ /dev/null
@@ -1,32 +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.
-
-from tempest.lib.services.volume.v2.availability_zone_client import \
-    AvailabilityZoneClient
-from tempest.lib.services.volume.v2.backups_client import BackupsClient
-from tempest.lib.services.volume.v2.encryption_types_client import \
-    EncryptionTypesClient
-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.qos_client import QosSpecsClient
-from tempest.lib.services.volume.v2.quotas_client import QuotasClient
-from tempest.lib.services.volume.v2.services_client import ServicesClient
-from tempest.lib.services.volume.v2.snapshots_client import SnapshotsClient
-from tempest.lib.services.volume.v2.types_client import TypesClient
-from tempest.lib.services.volume.v2.volumes_client import VolumesClient
-
-__all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
-           'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
-           'ServicesClient', 'SnapshotsClient', 'TypesClient',
-           'VolumesClient', ]
diff --git a/tempest/services/volume/v2/json/__init__.py b/tempest/services/volume/v2/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/v2/json/__init__.py
+++ /dev/null
diff --git a/tempest/services/volume/v3/json/__init__.py b/tempest/services/volume/v3/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/volume/v3/json/__init__.py
+++ /dev/null
diff --git a/tempest/test.py b/tempest/test.py
index cc9410f..4cc2a2b 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -25,12 +25,12 @@
 import testtools
 
 from tempest import clients
-from tempest.common import cred_client
 from tempest.common import credentials_factory as credentials
 from tempest.common import fixed_network
 import tempest.common.validation_resources as vresources
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common import cred_client
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -64,7 +64,6 @@
     service_list = {
         'compute': CONF.service_available.nova,
         'image': CONF.service_available.glance,
-        'baremetal': CONF.service_available.ironic,
         'volume': CONF.service_available.cinder,
         'network': True,
         'identity': True,
@@ -141,8 +140,38 @@
     return False
 
 
+def related_bug(bug, status_code=None):
+    """A decorator useful to know solutions from launchpad bug reports
+
+    @param bug: The launchpad bug number causing the test
+    @param status_code: The status code related to the bug report
+    """
+    def decorator(f):
+        @functools.wraps(f)
+        def wrapper(self, *func_args, **func_kwargs):
+            try:
+                return f(self, *func_args, **func_kwargs)
+            except Exception as exc:
+                exc_status_code = getattr(exc, 'status_code', None)
+                if status_code is None or status_code == exc_status_code:
+                    LOG.error('Hints: This test was made for the bug %s. '
+                              'The failure could be related to '
+                              'https://launchpad.net/bugs/%s' % (bug, bug))
+                raise exc
+        return wrapper
+    return decorator
+
+
 def is_scheduler_filter_enabled(filter_name):
-    """Check the list of enabled compute scheduler filters from config. """
+    """Check the list of enabled compute scheduler filters from config.
+
+    This function checks whether the given compute scheduler filter is
+    available and configured in the config file. If the
+    scheduler_available_filters option is set to 'all' (Default value. which
+    means default filters are configured in nova) in tempest.conf then, this
+    function returns True with assumption that requested filter 'filter_name'
+    is one of available filter in nova ("nova.scheduler.filters.all_filters").
+    """
 
     filters = CONF.compute_feature_enabled.scheduler_available_filters
     if len(filters) == 0:
@@ -504,8 +533,12 @@
             else:
                 raise lib_exc.InvalidCredentials(
                     "Invalid credentials type %s" % credential_type)
-        return cls.client_manager(credentials=creds.credentials,
-                                  service=cls._service)
+        manager = cls.client_manager(credentials=creds.credentials,
+                                     service=cls._service)
+        # NOTE(andreaf) Ensure credentials have user and project id fields.
+        # It may not be the case when using pre-provisioned credentials.
+        manager.auth_provider.set_auth()
+        return manager
 
     @classmethod
     def clear_credentials(cls):
@@ -532,18 +565,17 @@
         """
         if not CONF.validation.run_validation:
             return
+
         if keypair is None:
-            if CONF.validation.auth_method.lower() == "keypair":
-                keypair = True
-            else:
-                keypair = False
+            keypair = (CONF.validation.auth_method.lower() == "keypair")
+
         if floating_ip is None:
-            if CONF.validation.connect_method.lower() == "floating":
-                floating_ip = True
-            else:
-                floating_ip = False
+            floating_ip = (CONF.validation.connect_method.lower() ==
+                           "floating")
+
         if security_group is None:
             security_group = CONF.validation.security_group
+
         if security_group_rules is None:
             security_group_rules = CONF.validation.security_group_rules
 
@@ -610,10 +642,10 @@
             cred_provider, networks_client, CONF.compute.fixed_network_name)
 
     def assertEmpty(self, list, msg=None):
-        self.assertTrue(len(list) == 0, msg)
+        self.assertEqual(0, len(list), msg)
 
     def assertNotEmpty(self, list, msg=None):
-        self.assertTrue(len(list) > 0, msg)
+        self.assertGreater(len(list), 0, msg)
 
 
 call_until_true = debtcollector.moves.moved_function(
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index b3931d1..b08954f 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -146,7 +146,7 @@
 
     identity_version = 2
     identity_response = fake_identity._fake_v2_response
-    cred_client = 'tempest.common.cred_client.V2CredsClient'
+    cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
     dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
 
     def setUp(self):
@@ -245,7 +245,7 @@
 
     identity_version = 3
     identity_response = fake_identity._fake_v3_response
-    cred_client = 'tempest.common.cred_client.V3CredsClient'
+    cred_client = 'tempest.lib.common.cred_client.V3CredsClient'
 
     def setUp(self):
         self.mock_domains()
@@ -256,7 +256,7 @@
 
     identity_version = 2
     identity_response = fake_identity._fake_v2_response
-    cred_client = 'tempest.common.cred_client.V2CredsClient'
+    cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
     dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
     domain_is_in = False
 
@@ -338,7 +338,7 @@
 
     identity_version = 3
     identity_response = fake_identity._fake_v3_response
-    cred_client = 'tempest.common.cred_client.V3CredsClient'
+    cred_client = 'tempest.lib.common.cred_client.V3CredsClient'
     domain_is_in = True
 
     def setUp(self):
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 00b4542..1af0d95 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -401,7 +401,7 @@
                            'not_fake': 'metadata',
                            'swift': 'metadata'})
         fake_os = mock.MagicMock()
-        fake_os.account_client.list_extensions = fake_list_extensions
+        fake_os.capabilities_client.list_capabilities = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, 'get_enabled_extensions',
             return_value=(['fake1', 'fake2', 'fake3'])))
@@ -423,7 +423,7 @@
                            'not_fake': 'metadata',
                            'swift': 'metadata'})
         fake_os = mock.MagicMock()
-        fake_os.account_client.list_extensions = fake_list_extensions
+        fake_os.capabilities_client.list_capabilities = fake_list_extensions
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, 'get_enabled_extensions',
             return_value=(['all'])))
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
index 07867fc..1053d86 100644
--- a/tempest/tests/common/test_custom_matchers.py
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -25,11 +25,11 @@
         matches = self.matches_matches
         mismatches = self.matches_mismatches
         for candidate in matches:
-            self.assertEqual(None, matcher.match(candidate))
+            self.assertIsNone(matcher.match(candidate))
         for candidate in mismatches:
             mismatch = matcher.match(candidate)
-            self.assertNotEqual(None, mismatch)
-            self.assertNotEqual(None, getattr(mismatch, 'describe', None))
+            self.assertIsNotNone(mismatch)
+            self.assertIsNotNone(getattr(mismatch, 'describe', None))
 
     def test__str__(self):
         # [(expected, object to __str__)].
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index a826337..46f9526 100644
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -18,6 +18,7 @@
 
 from tempest.common import waiters
 from tempest import exceptions
+from tempest.lib import exceptions as lib_exc
 from tempest.lib.services.volume.v2 import volumes_client
 from tempest.tests import base
 import tempest.tests.utils as utils
@@ -36,14 +37,14 @@
         waiters.wait_for_image_status(self.client, 'fake_image_id', 'active')
         end_time = int(time.time())
         # Ensure waiter returns before build_timeout
-        self.assertTrue((end_time - start_time) < 10)
+        self.assertLess((end_time - start_time), 10)
 
     def test_wait_for_image_status_timeout(self):
         time_mock = self.patch('time.time')
         time_mock.side_effect = utils.generate_timeout_series(1)
 
         self.client.show_image.return_value = ({'status': 'saving'})
-        self.assertRaises(exceptions.TimeoutException,
+        self.assertRaises(lib_exc.TimeoutException,
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
 
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index e59e08f..e4f4c04 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -107,13 +107,20 @@
         self.assertEqual(self.conn.get_number_of_vcpus(), 16)
         self._assert_exec_called_with('grep -c ^processor /proc/cpuinfo')
 
-    def test_get_partitions(self):
-        proc_partitions = """major minor  #blocks  name
+    def test_get_disks(self):
+        output_lsblk = """\
+NAME       MAJ:MIN    RM          SIZE RO TYPE MOUNTPOINT
+sda          8:0       0  128035676160  0 disk
+sdb          8:16      0 1000204886016  0 disk
+sr0         11:0       1    1073741312  0 rom"""
+        result = """\
+NAME       MAJ:MIN    RM          SIZE RO TYPE MOUNTPOINT
+sda          8:0       0  128035676160  0 disk
+sdb          8:16      0 1000204886016  0 disk"""
 
-8        0  1048576 vda"""
-        self.ssh_mock.mock.exec_command.return_value = proc_partitions
-        self.assertEqual(self.conn.get_partitions(), proc_partitions)
-        self._assert_exec_called_with('cat /proc/partitions')
+        self.ssh_mock.mock.exec_command.return_value = output_lsblk
+        self.assertEqual(self.conn.get_disks(), result)
+        self._assert_exec_called_with('lsblk -lb --nodeps')
 
     def test_get_boot_time(self):
         booted_at = 10000
diff --git a/tempest/tests/common/utils/test_net_utils.py b/tempest/tests/common/utils/test_net_utils.py
new file mode 100644
index 0000000..83c6bcc
--- /dev/null
+++ b/tempest/tests/common/utils/test_net_utils.py
@@ -0,0 +1,33 @@
+#    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 tempest.common.utils import net_utils
+from tempest.lib import exceptions as lib_exc
+from tempest.tests import base
+
+
+class TestGetPingPayloadSize(base.TestCase):
+
+    def test_ipv4(self):
+        self.assertEqual(1422, net_utils.get_ping_payload_size(1450, 4))
+
+    def test_ipv6(self):
+        self.assertEqual(1406, net_utils.get_ping_payload_size(1450, 6))
+
+    def test_too_low_mtu(self):
+        self.assertRaises(
+            lib_exc.BadRequest, net_utils.get_ping_payload_size, 10, 4)
+
+    def test_None(self):
+        self.assertIsNone(net_utils.get_ping_payload_size(None, mock.Mock()))
diff --git a/tempest/tests/lib/cli/test_execute.py b/tempest/tests/lib/cli/test_execute.py
index cc9c94c..aaeb6f4 100644
--- a/tempest/tests/lib/cli/test_execute.py
+++ b/tempest/tests/lib/cli/test_execute.py
@@ -11,7 +11,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
 import mock
 import subprocess
 
@@ -74,3 +73,20 @@
         self.assertRaises(exceptions.CommandFailed, cli_base.execute,
                           "/bin/ls", action="tempest", flags="--foobar",
                           merge_stderr=True)
+
+    def test_execute_with_prefix(self):
+        result = cli_base.execute("env", action="",
+                                  prefix="env NEW_VAR=1")
+        self.assertIsInstance(result, str)
+        self.assertIn("NEW_VAR=1", result)
+
+
+class TestCLIClient(base.TestCase):
+
+    @mock.patch.object(cli_base, 'execute')
+    def test_execute_with_prefix(self, mock_execute):
+        cli = cli_base.CLIClient(prefix='env LAC_ALL=C')
+        cli.glance('action')
+        self.assertEqual(mock_execute.call_count, 1)
+        self.assertEqual(mock_execute.call_args[1],
+                         {'prefix': 'env LAC_ALL=C'})
diff --git a/tempest/tests/lib/common/test_cred_client.py b/tempest/tests/lib/common/test_cred_client.py
new file mode 100644
index 0000000..1cb3103
--- /dev/null
+++ b/tempest/tests/lib/common/test_cred_client.py
@@ -0,0 +1,78 @@
+# Copyright 2016 Hewlett Packard Enterprise Development LP
+# 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 tempest.lib.common import cred_client
+from tempest.tests import base
+
+
+class TestCredClientV2(base.TestCase):
+    def setUp(self):
+        super(TestCredClientV2, self).setUp()
+        self.identity_client = mock.MagicMock()
+        self.projects_client = mock.MagicMock()
+        self.users_client = mock.MagicMock()
+        self.roles_client = mock.MagicMock()
+        self.creds_client = cred_client.V2CredsClient(self.identity_client,
+                                                      self.projects_client,
+                                                      self.users_client,
+                                                      self.roles_client)
+
+    def test_create_project(self):
+        self.projects_client.create_tenant.return_value = {
+            'tenant': 'a_tenant'
+        }
+        res = self.creds_client.create_project('fake_name', 'desc')
+        self.assertEqual('a_tenant', res)
+        self.projects_client.create_tenant.assert_called_once_with(
+            name='fake_name', description='desc')
+
+    def test_delete_project(self):
+        self.creds_client.delete_project('fake_id')
+        self.projects_client.delete_tenant.assert_called_once_with(
+            'fake_id')
+
+
+class TestCredClientV3(base.TestCase):
+    def setUp(self):
+        super(TestCredClientV3, self).setUp()
+        self.identity_client = mock.MagicMock()
+        self.projects_client = mock.MagicMock()
+        self.users_client = mock.MagicMock()
+        self.roles_client = mock.MagicMock()
+        self.domains_client = mock.MagicMock()
+        self.domains_client.list_domains.return_value = {
+            'domains': [{'id': 'fake_domain_id'}]
+        }
+        self.creds_client = cred_client.V3CredsClient(self.identity_client,
+                                                      self.projects_client,
+                                                      self.users_client,
+                                                      self.roles_client,
+                                                      self.domains_client,
+                                                      'fake_domain')
+
+    def test_create_project(self):
+        self.projects_client.create_project.return_value = {
+            'project': 'a_tenant'
+        }
+        res = self.creds_client.create_project('fake_name', 'desc')
+        self.assertEqual('a_tenant', res)
+        self.projects_client.create_project.assert_called_once_with(
+            name='fake_name', description='desc', domain_id='fake_domain_id')
+
+    def test_delete_project(self):
+        self.creds_client.delete_project('fake_id')
+        print(self.projects_client.calls)
+        self.projects_client.delete_project.assert_called_once_with(
+            'fake_id')
diff --git a/tempest/tests/lib/fake_identity.py b/tempest/tests/lib/fake_identity.py
index 831f8b5..8bae34f 100644
--- a/tempest/tests/lib/fake_identity.py
+++ b/tempest/tests/lib/fake_identity.py
@@ -55,6 +55,7 @@
         },
         "user": {
             "id": "fake_alt_user_id",
+            "password_expires_at": None,
         },
         "serviceCatalog": CATALOG_V2,
     },
@@ -71,6 +72,7 @@
         },
         "user": {
             "id": "fake_user_id",
+            "password_expires_at": None,
         },
         "serviceCatalog": CATALOG_V2,
     },
@@ -83,18 +85,21 @@
             "id": "first_compute_fake_service",
             "interface": "public",
             "region": "NoMatchRegion",
+            "region_id": "NoMatchRegion",
             "url": "http://fake_url/v3/first_endpoint/api"
         },
         {
             "id": "second_fake_service",
             "interface": "public",
             "region": "FakeRegion",
+            "region_id": "FakeRegion",
             "url": "http://fake_url/v3/second_endpoint/api"
         },
         {
             "id": "third_fake_service",
             "interface": "admin",
             "region": "MiddleEarthRegion",
+            "region_id": "MiddleEarthRegion",
             "url": "http://fake_url/v3/third_endpoint/api"
         }
 
@@ -108,6 +113,7 @@
 
 IDENTITY_V3_RESPONSE = {
     "token": {
+        "audit_ids": ["ny5LA5YXToa_mAVO8Hnupw", "9NPTvsRDSkmsW61abP978Q"],
         "methods": [
             "token",
             "password"
@@ -127,7 +133,8 @@
                 "name": "domain_name"
             },
             "id": "fake_user_id",
-            "name": "username"
+            "name": "username",
+            "password_expires_at": None,
         },
         "issued_at": "2013-05-29T16:55:21.468960Z",
         "catalog": CATALOG_V3
@@ -136,6 +143,7 @@
 
 IDENTITY_V3_RESPONSE_DOMAIN_SCOPE = {
     "token": {
+        "audit_ids": ["ny5LA5YXToa_mAVO8Hnupw", "9NPTvsRDSkmsW61abP978Q"],
         "methods": [
             "token",
             "password"
@@ -151,7 +159,8 @@
                 "name": "domain_name"
             },
             "id": "fake_user_id",
-            "name": "username"
+            "name": "username",
+            "password_expires_at": None,
         },
         "issued_at": "2013-05-29T16:55:21.468960Z",
         "catalog": CATALOG_V3
@@ -160,6 +169,7 @@
 
 IDENTITY_V3_RESPONSE_NO_SCOPE = {
     "token": {
+        "audit_ids": ["ny5LA5YXToa_mAVO8Hnupw", "9NPTvsRDSkmsW61abP978Q"],
         "methods": [
             "token",
             "password"
@@ -171,7 +181,8 @@
                 "name": "domain_name"
             },
             "id": "fake_user_id",
-            "name": "username"
+            "name": "username",
+            "password_expires_at": None,
         },
         "issued_at": "2013-05-29T16:55:21.468960Z",
     }
diff --git a/tempest/tests/lib/services/identity/v3/test_role_assignments_client.py b/tempest/tests/lib/services/identity/v3/test_role_assignments_client.py
new file mode 100644
index 0000000..7d304c1
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_role_assignments_client.py
@@ -0,0 +1,206 @@
+# 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 role_assignments_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestRoleAssignmentsClient(base.BaseServiceTest):
+
+    FAKE_USER_ID = "313234"
+    FAKE_GROUP_ID = "101112"
+
+    FAKE_ROLE1_ID = "123456"
+    FAKE_ROLE2_ID = "123457"
+
+    FAKE_PROJECT_ID = "456789"
+    FAKE_DOMAIN_ID = "102030"
+
+    FAKE_USER_PROJECT_ASSIGNMENT = {
+        "links": {
+            "assignment": "http://example.com/identity/v3/projects/"
+                          "%s/users/%s/roles/%s" % (FAKE_PROJECT_ID,
+                                                    FAKE_USER_ID,
+                                                    FAKE_ROLE2_ID)
+        },
+        "role": {
+            "id": FAKE_ROLE2_ID
+        },
+        "scope": {
+            "project": {
+                "id": FAKE_PROJECT_ID
+            }
+        },
+        "user": {
+            "id": FAKE_USER_ID
+        }
+    }
+
+    FAKE_GROUP_PROJECT_ASSIGNMENT = {
+        "links": {
+            "assignment": "http://example.com/identity/v3/projects/"
+                          "%s/groups/%s/roles/%s" % (FAKE_PROJECT_ID,
+                                                     FAKE_GROUP_ID,
+                                                     FAKE_ROLE1_ID)
+        },
+        "role": {
+            "id": FAKE_ROLE1_ID
+        },
+        "scope": {
+            "project": {
+                "id": FAKE_PROJECT_ID
+            }
+        },
+        "group": {
+            "id": FAKE_GROUP_ID
+        }
+    }
+
+    FAKE_USER_PROJECT_EFFECTIVE_ASSIGNMENT = {
+        "links": {
+            "assignment": "http://example.com/identity/v3/projects/"
+                          "%s/groups/%s/roles/%s" % (FAKE_PROJECT_ID,
+                                                     FAKE_GROUP_ID,
+                                                     FAKE_ROLE1_ID),
+            "membership": "http://example.com/identity/v3/groups/"
+                          "%s/users/%s" % (FAKE_GROUP_ID, FAKE_USER_ID)
+        },
+        "role": {
+            "id": FAKE_ROLE1_ID
+        },
+        "scope": {
+            "project": {
+                "id": FAKE_PROJECT_ID
+            }
+        },
+        "user": {
+            "id": FAKE_USER_ID
+        }
+    }
+
+    FAKE_USER_DOMAIN_ASSIGNMENT = {
+        "links": {
+            "assignment": "http://example.com/identity/v3/domains/"
+                          "%s/users/%s/roles/%s" % (FAKE_DOMAIN_ID,
+                                                    FAKE_USER_ID,
+                                                    FAKE_ROLE1_ID)
+        },
+        "role": {
+            "id": FAKE_ROLE1_ID
+        },
+        "scope": {
+            "domain": {
+                "id": FAKE_DOMAIN_ID
+            }
+        },
+        "user": {
+            "id": FAKE_USER_ID
+        }
+    }
+
+    FAKE_GROUP_PROJECT_ASSIGNMENTS = {
+        "role_assignments": [
+            FAKE_GROUP_PROJECT_ASSIGNMENT
+        ],
+        "links": {
+            "self": "http://example.com/identity/v3/role_assignments?"
+                    "scope.project.id=%s&group.id=%s&effective" % (
+                        FAKE_PROJECT_ID, FAKE_GROUP_ID),
+            "previous": None,
+            "next": None
+        }
+    }
+
+    FAKE_USER_PROJECT_EFFECTIVE_ASSIGNMENTS = {
+        "role_assignments": [
+            FAKE_USER_PROJECT_ASSIGNMENT,
+            FAKE_USER_PROJECT_EFFECTIVE_ASSIGNMENT
+        ],
+        "links": {
+            "self": "http://example.com/identity/v3/role_assignments?"
+                    "scope.project.id=%s&user.id=%s&effective" % (
+                        FAKE_PROJECT_ID, FAKE_USER_ID),
+            "previous": None,
+            "next": None
+        }
+    }
+
+    FAKE_USER_DOMAIN_ASSIGNMENTS = {
+        "role_assignments": [
+            FAKE_USER_DOMAIN_ASSIGNMENT
+        ],
+        "links": {
+            "self": "http://example.com/identity/v3/role_assignments?"
+                    "scope.domain.id=%s&user.id=%s&effective" % (
+                        FAKE_DOMAIN_ID, FAKE_USER_ID),
+            "previous": None,
+            "next": None
+        }
+    }
+
+    def setUp(self):
+        super(TestRoleAssignmentsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = role_assignments_client.RoleAssignmentsClient(
+            fake_auth, 'identity', 'regionOne')
+
+    def _test_list_user_project_effective_assignments(self, bytes_body=False):
+        params = {'scope.project.id': self.FAKE_PROJECT_ID,
+                  'user.id': self.FAKE_USER_ID}
+        self.check_service_client_function(
+            self.client.list_role_assignments,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_USER_PROJECT_EFFECTIVE_ASSIGNMENTS,
+            bytes_body,
+            effective=True,
+            **params)
+
+    def test_list_user_project_effective_assignments_with_str_body(self):
+        self._test_list_user_project_effective_assignments()
+
+    def test_list_user_project_effective_assignments_with_bytes_body(self):
+        self._test_list_user_project_effective_assignments(bytes_body=True)
+
+    def _test_list_group_project_assignments(self, bytes_body=False):
+        params = {'scope.project.id': self.FAKE_PROJECT_ID,
+                  'group.id': self.FAKE_GROUP_ID}
+        self.check_service_client_function(
+            self.client.list_role_assignments,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_GROUP_PROJECT_ASSIGNMENTS,
+            bytes_body,
+            **params)
+
+    def test_list_group_project_assignments_with_str_body(self):
+        self._test_list_group_project_assignments()
+
+    def test_list_group_project_assignments_with_bytes_body(self):
+        self._test_list_group_project_assignments(bytes_body=True)
+
+    def _test_list_user_domain_assignments(self, bytes_body=False):
+        params = {'scope.domain.id': self.FAKE_DOMAIN_ID,
+                  'user.id': self.FAKE_USER_ID}
+        self.check_service_client_function(
+            self.client.list_role_assignments,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_GROUP_PROJECT_ASSIGNMENTS,
+            bytes_body,
+            **params)
+
+    def test_list_user_domain_assignments_with_str_body(self):
+        self._test_list_user_domain_assignments()
+
+    def test_list_user_domain_assignments_with_bytes_body(self):
+        self._test_list_user_domain_assignments(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_token_client.py b/tempest/tests/lib/services/identity/v3/test_token_client.py
index 9f4b4cc..38e8c4a 100644
--- a/tempest/tests/lib/services/identity/v3/test_token_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_token_client.py
@@ -20,7 +20,7 @@
 from tempest.lib import exceptions
 from tempest.lib.services.identity.v3 import token_client
 from tempest.tests import base
-from tempest.tests.lib import fake_http
+from tempest.tests.lib import fake_identity
 
 
 class TestTokenClientV3(base.TestCase):
@@ -31,10 +31,8 @@
 
     def test_auth(self):
         token_client_v3 = token_client.V3TokenClient('fake_url')
-        response = fake_http.fake_http_response(
-            None, status=201,
-        )
-        body = {'access': {'token': 'fake_token'}}
+        response, body_text = fake_identity._fake_v3_response(None, None)
+        body = json.loads(body_text)
 
         with mock.patch.object(token_client_v3, 'post') as post_mock:
             post_mock.return_value = response, body
@@ -60,10 +58,8 @@
 
     def test_auth_with_project_id_and_domain_id(self):
         token_client_v3 = token_client.V3TokenClient('fake_url')
-        response = fake_http.fake_http_response(
-            None, status=201,
-        )
-        body = {'access': {'token': 'fake_token'}}
+        response, body_text = fake_identity._fake_v3_response(None, None)
+        body = json.loads(body_text)
 
         with mock.patch.object(token_client_v3, 'post') as post_mock:
             post_mock.return_value = response, body
@@ -103,10 +99,8 @@
 
     def test_auth_with_tenant(self):
         token_client_v3 = token_client.V3TokenClient('fake_url')
-        response = fake_http.fake_http_response(
-            None, status=201,
-        )
-        body = {'access': {'token': 'fake_token'}}
+        response, body_text = fake_identity._fake_v3_response(None, None)
+        body = json.loads(body_text)
 
         with mock.patch.object(token_client_v3, 'post') as post_mock:
             post_mock.return_value = response, body
@@ -138,13 +132,10 @@
 
     def test_request_with_str_body(self):
         token_client_v3 = token_client.V3TokenClient('fake_url')
-        response = fake_http.fake_http_response(
-            None, status=200,
-        )
-        body = str('{"access": {"token": "fake_token"}}')
 
         with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
-            mock_raw_r.return_value = response, body
+            mock_raw_r.return_value = (
+                fake_identity._fake_v3_response(None, None))
             resp, body = token_client_v3.request('GET', 'fake_uri')
 
         self.assertIsInstance(body, dict)
@@ -152,10 +143,8 @@
     def test_request_with_bytes_body(self):
         token_client_v3 = token_client.V3TokenClient('fake_url')
 
-        response = fake_http.fake_http_response(
-            None, status=200,
-        )
-        body = b'{"access": {"token": "fake_token"}}'
+        response, body_text = fake_identity._fake_v3_response(None, None)
+        body = body_text.encode('utf-8')
 
         with mock.patch.object(token_client_v3, 'raw_request') as mock_raw_r:
             mock_raw_r.return_value = response, body
diff --git a/tempest/tests/lib/services/image/v2/test_namespace_properties_client.py b/tempest/tests/lib/services/image/v2/test_namespace_properties_client.py
new file mode 100644
index 0000000..1d56db6
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_namespace_properties_client.py
@@ -0,0 +1,191 @@
+# Copyright 2016 EasyStack.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.services.image.v2 import namespace_properties_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestNamespacePropertiesClient(base.BaseServiceTest):
+    FAKE_CREATE_SHOW_NAMESPACE_PROPERTY = {
+        "description": "property",
+        "enum": ["xen", "qemu", "kvm", "lxc", "uml", "vmware", "hyperv"],
+        "name": "OS::Glance::Image",
+        "title": "Hypervisor Type",
+        "type": "string"
+    }
+
+    FAKE_LIST_NAMESPACE_PROPERTY = {
+        "properties": {
+            "hw_disk_bus": {
+                "description": "property.",
+                "enum": ["scsi", "virtio", "uml", "xen", "ide", "usb"],
+                "title": "Disk Bus",
+                "type": "string"
+            },
+            "hw_machine_type": {
+                "description": "desc.",
+                "title": "Machine Type",
+                "type": "string"
+            },
+            "hw_qemu_guest_agent": {
+                "description": "desc.",
+                "enum": [
+                    "yes",
+                    "no"
+                ],
+                "title": "QEMU Guest Agent",
+                "type": "string"
+            },
+            "hw_rng_model": {
+                "default": "virtio",
+                "description": "desc",
+                "title": "Random Number Generator Device",
+                "type": "string"
+            },
+            "hw_scsi_model": {
+                "default": "virtio-scsi",
+                "description": "desc.",
+                "title": "SCSI Model",
+                "type": "string"
+            },
+            "hw_video_model": {
+                "description": "The video image driver used.",
+                "enum": [
+                    "vga",
+                    "cirrus",
+                    "vmvga",
+                    "xen",
+                    "qxl"
+                ],
+                "title": "Video Model",
+                "type": "string"
+            },
+            "hw_video_ram": {
+                "description": "desc.",
+                "title": "Max Video Ram",
+                "type": "integer"
+            },
+            "hw_vif_model": {
+                "description": "desc.",
+                "enum": ["e1000",
+                         "ne2k_pci",
+                         "pcnet",
+                         "rtl8139",
+                         "virtio",
+                         "e1000",
+                         "e1000e",
+                         "VirtualE1000",
+                         "VirtualE1000e",
+                         "VirtualPCNet32",
+                         "VirtualSriovEthernetCard",
+                         "VirtualVmxnet",
+                         "netfront",
+                         "ne2k_pci"
+                         ],
+                "title": "Virtual Network Interface",
+                "type": "string"
+            },
+            "os_command_line": {
+                "description": "desc.",
+                "title": "Kernel Command Line",
+                "type": "string"
+            }
+        }
+    }
+
+    FAKE_UPDATE_NAMESPACE_PROPERTY = {
+        "description": "property",
+        "enum": ["xen", "qemu", "kvm", "lxc", "uml", "vmware", "hyperv"],
+        "name": "OS::Glance::Image",
+        "title": "update Hypervisor Type",
+        "type": "string"
+    }
+
+    def setUp(self):
+        super(TestNamespacePropertiesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = namespace_properties_client.NamespacePropertiesClient(
+            fake_auth, 'image', 'regionOne')
+
+    def _test_create_namespace_property(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_namespace_property,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SHOW_NAMESPACE_PROPERTY,
+            bytes_body, status=201,
+            namespace="OS::Compute::Hypervisor",
+            title="Hypervisor Type", name="OS::Glance::Image",
+            type="string",
+            enum=["xen", "qemu", "kvm", "lxc", "uml", "vmware", "hyperv"])
+
+    def _test_list_namespace_property(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_namespace_properties,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_NAMESPACE_PROPERTY,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor")
+
+    def _test_show_namespace_property(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_namespace_properties,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CREATE_SHOW_NAMESPACE_PROPERTY,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            property_name="OS::Glance::Image")
+
+    def _test_update_namespace_property(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_namespace_properties,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_NAMESPACE_PROPERTY,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            property_name="OS::Glance::Image",
+            title="update Hypervisor Type", type="string",
+            enum=["xen", "qemu", "kvm", "lxc", "uml", "vmware", "hyperv"],
+            name="OS::Glance::Image")
+
+    def test_create_namespace_property_with_str_body(self):
+        self._test_create_namespace_property()
+
+    def test_create_namespace_property_with_bytes_body(self):
+        self._test_create_namespace_property(bytes_body=True)
+
+    def test_list_namespace_property_with_str_body(self):
+        self._test_list_namespace_property()
+
+    def test_list_namespace_property_with_bytes_body(self):
+        self._test_list_namespace_property(bytes_body=True)
+
+    def test_show_namespace_property_with_str_body(self):
+        self._test_show_namespace_property()
+
+    def test_show_namespace_property_with_bytes_body(self):
+        self._test_show_namespace_property(bytes_body=True)
+
+    def test_update_namespace_property_with_str_body(self):
+        self._test_update_namespace_property()
+
+    def test_update_namespace_property_with_bytes_body(self):
+        self._test_update_namespace_property(bytes_body=True)
+
+    def test_delete_namespace(self):
+        self.check_service_client_function(
+            self.client.delete_namespace_property,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {}, namespace="OS::Compute::Hypervisor",
+            property_name="OS::Glance::Image", status=204)
diff --git a/tempest/tests/lib/services/network/test_service_providers_client.py b/tempest/tests/lib/services/network/test_service_providers_client.py
new file mode 100644
index 0000000..ae11ef0
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_service_providers_client.py
@@ -0,0 +1,37 @@
+#    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.network import service_providers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestServiceProvidersClient(base.BaseServiceTest):
+    def setUp(self):
+        super(TestServiceProvidersClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = service_providers_client.ServiceProvidersClient(
+            fake_auth, 'network', 'regionOne')
+
+    def _test_list_service_providers(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_service_providers,
+            'tempest.lib.common.rest_client.RestClient.get',
+            {"service_providers": []},
+            bytes_body)
+
+    def test_list_service_providers_with_str_body(self):
+        self._test_list_service_providers()
+
+    def test_list_service_providers_with_bytes_body(self):
+        self._test_list_service_providers(bytes_body=True)
diff --git a/tempest/tests/lib/services/network/test_versions_client.py b/tempest/tests/lib/services/network/test_versions_client.py
index ae52c8a..026dc6d 100644
--- a/tempest/tests/lib/services/network/test_versions_client.py
+++ b/tempest/tests/lib/services/network/test_versions_client.py
@@ -35,10 +35,7 @@
                     "type": "text/html"
                 }
             ],
-            "status": "CURRENT",
-            "updated": "2013-07-23T11:33:21Z",
-            "version": "2.0",
-            "min_version": "2.0"
+            "status": "CURRENT"
             }
         }
 
diff --git a/tempest/tests/lib/services/volume/v1/test_quotas_client.py b/tempest/tests/lib/services/volume/v1/test_quotas_client.py
new file mode 100644
index 0000000..f9e76af
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v1/test_quotas_client.py
@@ -0,0 +1,96 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v1 import quotas_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestQuotasClient(base.BaseServiceTest):
+    FAKE_QUOTAS = {
+        "quota_set": {
+            "cores": 20,
+            "fixed_ips": -1,
+            "floating_ips": 10,
+            "id": "fake_tenant",
+            "injected_file_content_bytes": 10240,
+            "injected_file_path_bytes": 255,
+            "injected_files": 5,
+            "instances": 10,
+            "key_pairs": 100,
+            "metadata_items": 128,
+            "ram": 51200,
+            "security_group_rules": 20,
+            "security_groups": 10
+        }
+    }
+
+    FAKE_UPDATE_QUOTAS_REQUEST = {
+        "quota_set": {
+            "security_groups": 45
+        }
+    }
+
+    def setUp(self):
+        super(TestQuotasClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = quotas_client.QuotasClient(fake_auth,
+                                                 'volume',
+                                                 'regionOne')
+
+    def _test_show_default_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_default_quota_set,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_QUOTAS,
+            bytes_body, tenant_id="fake_tenant")
+
+    def _test_show_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_quota_set,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_QUOTAS,
+            bytes_body, tenant_id="fake_tenant")
+
+    def _test_update_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_quota_set,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_QUOTAS_REQUEST,
+            bytes_body, tenant_id="fake_tenant")
+
+    def test_show_default_quota_set_with_str_body(self):
+        self._test_show_default_quota_set()
+
+    def test_show_default_quota_set_with_bytes_body(self):
+        self._test_show_default_quota_set(bytes_body=True)
+
+    def test_show_quota_set_with_str_body(self):
+        self._test_show_quota_set()
+
+    def test_show_quota_set_with_bytes_body(self):
+        self._test_show_quota_set(bytes_body=True)
+
+    def test_update_quota_set_with_str_body(self):
+        self._test_update_quota_set()
+
+    def test_update_quota_set_with_bytes_body(self):
+        self._test_update_quota_set(bytes_body=True)
+
+    def test_delete_quota_set(self):
+        self.check_service_client_function(
+            self.client.delete_quota_set,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            tenant_id="fake_tenant")
diff --git a/tempest/tests/lib/services/volume/v1/test_snapshots_client.py b/tempest/tests/lib/services/volume/v1/test_snapshots_client.py
new file mode 100644
index 0000000..49191e3
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v1/test_snapshots_client.py
@@ -0,0 +1,200 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v1 import snapshots_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSnapshotsClient(base.BaseServiceTest):
+    FAKE_CREATE_SNAPSHOT = {
+        "snapshot": {
+            "display_name": "snap-001",
+            "display_description": "Daily backup",
+            "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            "force": True
+        }
+    }
+
+    FAKE_UPDATE_SNAPSHOT_REQUEST = {
+        "metadata": {
+            "key": "v1"
+        }
+    }
+
+    FAKE_INFO_SNAPSHOT = {
+        "snapshot": {
+            "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+            "display_name": "snap-001",
+            "display_description": "Daily backup",
+            "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            "status": "available",
+            "size": 30,
+            "created_at": "2012-02-29T03:50:07Z"
+        }
+    }
+
+    FAKE_LIST_SNAPSHOTS = {
+        "snapshots": [
+            {
+                "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+                "display_name": "snap-001",
+                "display_description": "Daily backup",
+                "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+                "status": "available",
+                "size": 30,
+                "created_at": "2012-02-29T03:50:07Z",
+                "metadata": {
+                    "contents": "junk"
+                }
+            },
+            {
+                "id": "e479997c-650b-40a4-9dfe-77655818b0d2",
+                "display_name": "snap-002",
+                "display_description": "Weekly backup",
+                "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358",
+                "status": "available",
+                "size": 25,
+                "created_at": "2012-03-19T01:52:47Z",
+                "metadata": {}
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestSnapshotsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = snapshots_client.SnapshotsClient(fake_auth,
+                                                       'volume',
+                                                       'regionOne')
+
+    def _test_create_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_snapshot,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SNAPSHOT,
+            bytes_body)
+
+    def _test_show_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_snapshot,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_list_snapshots(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_snapshots,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_SNAPSHOTS,
+            bytes_body,
+            detail=True)
+
+    def _test_create_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+            metadata={"key": "v1"})
+
+    def _test_update_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_show_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_update_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body, snapshot_id="cbc36478b0bd8e67e89")
+
+    def _test_update_snapshot_metadata_item(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot_metadata_item,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body, volume_type_id="cbc36478b0bd8e67e89")
+
+    def test_create_snapshot_with_str_body(self):
+        self._test_create_snapshot()
+
+    def test_create_snapshot_with_bytes_body(self):
+        self._test_create_snapshot(bytes_body=True)
+
+    def test_show_snapshot_with_str_body(self):
+        self._test_show_snapshot()
+
+    def test_show_snapshot_with_bytes_body(self):
+        self._test_show_snapshot(bytes_body=True)
+
+    def test_list_snapshots_with_str_body(self):
+        self._test_list_snapshots()
+
+    def test_list_snapshots_with_bytes_body(self):
+        self._test_list_snapshots(bytes_body=True)
+
+    def test_create_snapshot_metadata_with_str_body(self):
+        self._test_create_snapshot_metadata()
+
+    def test_create_snapshot_metadata_with_bytes_body(self):
+        self._test_create_snapshot_metadata(bytes_body=True)
+
+    def test_update_snapshot_with_str_body(self):
+        self._test_update_snapshot()
+
+    def test_update_snapshot_with_bytes_body(self):
+        self._test_update_snapshot(bytes_body=True)
+
+    def test_show_snapshot_metadata_with_str_body(self):
+        self._test_show_snapshot_metadata()
+
+    def test_show_snapshot_metadata_with_bytes_body(self):
+        self._test_show_snapshot_metadata(bytes_body=True)
+
+    def test_update_snapshot_metadata_with_str_body(self):
+        self._test_update_snapshot_metadata()
+
+    def test_update_snapshot_metadata_with_bytes_body(self):
+        self._test_update_snapshot_metadata(bytes_body=True)
+
+    def test_force_delete_snapshot(self):
+        self.check_service_client_function(
+            self.client.force_delete_snapshot,
+            'tempest.lib.common.rest_client.RestClient.post',
+            {},
+            snapshot_id="521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            status=202)
+
+    def test_delete_snapshot(self):
+        self.check_service_client_function(
+            self.client.delete_snapshot,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            snapshot_id="521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            status=202)
diff --git a/tempest/tests/lib/services/volume/v2/test_quotas_client.py b/tempest/tests/lib/services/volume/v2/test_quotas_client.py
new file mode 100644
index 0000000..6384350
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_quotas_client.py
@@ -0,0 +1,86 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v2 import quotas_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestQuotasClient(base.BaseServiceTest):
+    FAKE_QUOTAS = {
+        "quota_set": {
+            "gigabytes": 5,
+            "snapshots": 10,
+            "volumes": 20
+        }
+    }
+
+    FAKE_UPDATE_QUOTAS_REQUEST = {
+        "quota_set": {
+            "security_groups": 45
+        }
+    }
+
+    def setUp(self):
+        super(TestQuotasClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = quotas_client.QuotasClient(fake_auth,
+                                                 'volume',
+                                                 'regionOne')
+
+    def _test_show_default_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_default_quota_set,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_QUOTAS,
+            bytes_body, tenant_id="fake_tenant")
+
+    def _test_show_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_quota_set,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_QUOTAS,
+            bytes_body, tenant_id="fake_tenant")
+
+    def _test_update_quota_set(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_quota_set,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_QUOTAS_REQUEST,
+            bytes_body, tenant_id="fake_tenant")
+
+    def test_show_default_quota_set_with_str_body(self):
+        self._test_show_default_quota_set()
+
+    def test_show_default_quota_set_with_bytes_body(self):
+        self._test_show_default_quota_set(bytes_body=True)
+
+    def test_show_quota_set_with_str_body(self):
+        self._test_show_quota_set()
+
+    def test_show_quota_set_with_bytes_body(self):
+        self._test_show_quota_set(bytes_body=True)
+
+    def test_update_quota_set_with_str_body(self):
+        self._test_update_quota_set()
+
+    def test_update_quota_set_with_bytes_body(self):
+        self._test_update_quota_set(bytes_body=True)
+
+    def test_delete_quota_set(self):
+        self.check_service_client_function(
+            self.client.delete_quota_set,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            tenant_id="fake_tenant")
diff --git a/tempest/tests/lib/services/volume/v2/test_snapshots_client.py b/tempest/tests/lib/services/volume/v2/test_snapshots_client.py
new file mode 100644
index 0000000..7d656f1
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v2/test_snapshots_client.py
@@ -0,0 +1,201 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v2 import snapshots_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestSnapshotsClient(base.BaseServiceTest):
+    FAKE_CREATE_SNAPSHOT = {
+        "snapshot": {
+            "display_name": "snap-001",
+            "display_description": "Daily backup",
+            "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            "force": True
+        }
+    }
+
+    FAKE_UPDATE_SNAPSHOT_REQUEST = {
+        "metadata": {
+            "key": "v1"
+        }
+    }
+
+    FAKE_INFO_SNAPSHOT = {
+        "snapshot": {
+            "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+            "display_name": "snap-001",
+            "display_description": "Daily backup",
+            "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            "status": "available",
+            "size": 30,
+            "created_at": "2012-02-29T03:50:07Z"
+        }
+    }
+
+    FAKE_LIST_SNAPSHOTS = {
+        "snapshots": [
+            {
+                "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+                "display_name": "snap-001",
+                "display_description": "Daily backup",
+                "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+                "status": "available",
+                "size": 30,
+                "created_at": "2012-02-29T03:50:07Z",
+                "metadata": {
+                    "contents": "junk"
+                }
+            },
+            {
+                "id": "e479997c-650b-40a4-9dfe-77655818b0d2",
+                "display_name": "snap-002",
+                "display_description": "Weekly backup",
+                "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358",
+                "status": "available",
+                "size": 25,
+                "created_at": "2012-03-19T01:52:47Z",
+                "metadata": {}
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestSnapshotsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = snapshots_client.SnapshotsClient(fake_auth,
+                                                       'volume',
+                                                       'regionOne')
+
+    def _test_create_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_snapshot,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SNAPSHOT,
+            bytes_body,
+            status=202)
+
+    def _test_show_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_snapshot,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_list_snapshots(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_snapshots,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_SNAPSHOTS,
+            bytes_body,
+            detail=True)
+
+    def _test_create_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+            metadata={"key": "v1"})
+
+    def _test_update_snapshot(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_show_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body,
+            snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+
+    def _test_update_snapshot_metadata(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot_metadata,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+            bytes_body, snapshot_id="cbc36478b0bd8e67e89")
+
+    def _test_update_snapshot_metadata_item(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_snapshot_metadata_item,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_INFO_SNAPSHOT,
+            bytes_body, volume_type_id="cbc36478b0bd8e67e89")
+
+    def test_create_snapshot_with_str_body(self):
+        self._test_create_snapshot()
+
+    def test_create_snapshot_with_bytes_body(self):
+        self._test_create_snapshot(bytes_body=True)
+
+    def test_show_snapshot_with_str_body(self):
+        self._test_show_snapshot()
+
+    def test_show_snapshot_with_bytes_body(self):
+        self._test_show_snapshot(bytes_body=True)
+
+    def test_list_snapshots_with_str_body(self):
+        self._test_list_snapshots()
+
+    def test_list_snapshots_with_bytes_body(self):
+        self._test_list_snapshots(bytes_body=True)
+
+    def test_create_snapshot_metadata_with_str_body(self):
+        self._test_create_snapshot_metadata()
+
+    def test_create_snapshot_metadata_with_bytes_body(self):
+        self._test_create_snapshot_metadata(bytes_body=True)
+
+    def test_update_snapshot_with_str_body(self):
+        self._test_update_snapshot()
+
+    def test_update_snapshot_with_bytes_body(self):
+        self._test_update_snapshot(bytes_body=True)
+
+    def test_show_snapshot_metadata_with_str_body(self):
+        self._test_show_snapshot_metadata()
+
+    def test_show_snapshot_metadata_with_bytes_body(self):
+        self._test_show_snapshot_metadata(bytes_body=True)
+
+    def test_update_snapshot_metadata_with_str_body(self):
+        self._test_update_snapshot_metadata()
+
+    def test_update_snapshot_metadata_with_bytes_body(self):
+        self._test_update_snapshot_metadata(bytes_body=True)
+
+    def test_force_delete_snapshot(self):
+        self.check_service_client_function(
+            self.client.force_delete_snapshot,
+            'tempest.lib.common.rest_client.RestClient.post',
+            {},
+            snapshot_id="521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            status=202)
+
+    def test_delete_snapshot(self):
+        self.check_service_client_function(
+            self.client.delete_snapshot,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            snapshot_id="521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            status=202)
diff --git a/tempest/api/baremetal/__init__.py b/tempest/tests/lib/services/volume/v3/__init__.py
similarity index 100%
rename from tempest/api/baremetal/__init__.py
rename to tempest/tests/lib/services/volume/v3/__init__.py
diff --git a/tempest/tests/lib/services/volume/v3/test_user_messages_client.py b/tempest/tests/lib/services/volume/v3/test_user_messages_client.py
new file mode 100644
index 0000000..4aeed5f
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v3/test_user_messages_client.py
@@ -0,0 +1,92 @@
+# Copyright 2016 Red Hat.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v3 import messages_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestUserMessagesClient(base.BaseServiceTest):
+    USER_MESSAGE_INFO = {
+        "created_at": "2016-11-21T06:16:34.000000",
+        "guaranteed_until": "2016-12-21T06:16:34.000000",
+        "user_message": "No storage could be allocated for this volume "
+                        "request. You may be able to try another size or"
+                        " volume type.",
+        "resource_uuid": "c570b406-bf0b-4067-9398-f0bb09a7d9d7",
+        "request_id": "req-8f68681e-9b6b-4009-b94c-ac0811595451",
+        "message_level": "ERROR",
+        "id": "9a7dafbd-a156-4540-8996-50e71b5dcadf",
+        "resource_type": "VOLUME",
+        "links": [
+            {"href": "http://192.168.100.230:8776/v3/"
+                     "a678cb65f701462ea2257245cd640829/messages/"
+                     "9a7dafbd-a156-4540-8996-50e71b5dcadf",
+             "rel": "self"},
+            {"href": "http://192.168.100.230:8776/"
+                     "a678cb65f701462ea2257245cd640829/messages/"
+                     "9a7dafbd-a156-4540-8996-50e71b5dcadf",
+             "rel": "bookmark"}]
+        }
+    FAKE_SHOW_USER_MESSAGE = {
+        "message": dict(event_id="000002", **USER_MESSAGE_INFO)}
+
+    FAKE_LIST_USER_MESSAGES = {
+        "messages": [
+            dict(event_id="000003", **USER_MESSAGE_INFO),
+            dict(event_id="000004", **USER_MESSAGE_INFO)
+        ]
+    }
+
+    def setUp(self):
+        super(TestUserMessagesClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = messages_client.MessagesClient(fake_auth,
+                                                     'volume',
+                                                     'regionOne')
+
+    def _test_show_user_message(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_message,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_SHOW_USER_MESSAGE,
+            bytes_body,
+            message_id="9a7dafbd-a156-4540-8996-50e71b5dcadf")
+
+    def _test_list_user_message(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_messages,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_USER_MESSAGES,
+            bytes_body)
+
+    def test_list_user_message_with_str_body(self):
+        self._test_list_user_message()
+
+    def test_list_user_message_with_bytes_body(self):
+        self._test_list_user_message(bytes_body=True)
+
+    def test_show_user_message_with_str_body(self):
+        self._test_show_user_message()
+
+    def test_show_user_message_with_bytes_body(self):
+        self._test_show_user_message(bytes_body=True)
+
+    def test_delete_user_message(self):
+        self.check_service_client_function(
+            self.client.delete_message,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            message_id="9a7dafbd-a156-4540-8996-50e71b5dcadf",
+            status=204)
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index 6da7e41..2f975d2 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -458,6 +458,56 @@
         expected = 'http://fake_url/v2.0'
         self._test_base_url_helper(expected, filters, ('token', auth_data))
 
+    def test_base_url_with_extra_path_endpoint(self):
+        auth_data = {
+            'serviceCatalog': [
+                {
+                    'type': 'compute',
+                    'endpoints': [
+                        {
+                            'region': 'FakeRegion',
+                            'publicURL': 'http://fake_url/some_path/v2.0'
+                        }
+                    ]
+                }
+            ]
+        }
+
+        filters = {
+            'service': 'compute',
+            'endpoint_type': 'publicURL',
+            'region': 'FakeRegion',
+            'api_version': 'v2.0'
+        }
+
+        expected = 'http://fake_url/some_path/v2.0'
+        self._test_base_url_helper(expected, filters, ('token', auth_data))
+
+    def test_base_url_with_unversioned_extra_path_endpoint(self):
+        auth_data = {
+            'serviceCatalog': [
+                {
+                    'type': 'compute',
+                    'endpoints': [
+                        {
+                            'region': 'FakeRegion',
+                            'publicURL': 'http://fake_url/some_path'
+                        }
+                    ]
+                }
+            ]
+        }
+
+        filters = {
+            'service': 'compute',
+            'endpoint_type': 'publicURL',
+            'region': 'FakeRegion',
+            'api_version': 'v2.0'
+        }
+
+        expected = 'http://fake_url/some_path/v2.0'
+        self._test_base_url_helper(expected, filters, ('token', auth_data))
+
     def test_token_not_expired(self):
         expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
         self._verify_expiry(expiry_data=expiry_data, should_be_expired=False)
@@ -592,6 +642,58 @@
         expected = 'http://fake_url/v3'
         self._test_base_url_helper(expected, filters, ('token', auth_data))
 
+    def test_base_url_with_extra_path_endpoint(self):
+        auth_data = {
+            'catalog': [
+                {
+                    'type': 'compute',
+                    'endpoints': [
+                        {
+                            'region': 'FakeRegion',
+                            'url': 'http://fake_url/some_path/v2.0',
+                            'interface': 'public'
+                        }
+                    ]
+                }
+            ]
+        }
+
+        filters = {
+            'service': 'compute',
+            'endpoint_type': 'publicURL',
+            'region': 'FakeRegion',
+            'api_version': 'v2.0'
+        }
+
+        expected = 'http://fake_url/some_path/v2.0'
+        self._test_base_url_helper(expected, filters, ('token', auth_data))
+
+    def test_base_url_with_unversioned_extra_path_endpoint(self):
+        auth_data = {
+            'catalog': [
+                {
+                    'type': 'compute',
+                    'endpoints': [
+                        {
+                            'region': 'FakeRegion',
+                            'url': 'http://fake_url/some_path',
+                            'interface': 'public'
+                        }
+                    ]
+                }
+            ]
+        }
+
+        filters = {
+            'service': 'compute',
+            'endpoint_type': 'publicURL',
+            'region': 'FakeRegion',
+            'api_version': 'v2.0'
+        }
+
+        expected = 'http://fake_url/some_path/v2.0'
+        self._test_base_url_helper(expected, filters, ('token', auth_data))
+
     # Base URL test with scope only for V3
     def test_base_url_scope_project(self):
         self.auth_provider.scope = 'project'
diff --git a/tempest/tests/negative/test_negative_generators.py b/tempest/tests/negative/test_negative_generators.py
deleted file mode 100644
index 7e1ee2c..0000000
--- a/tempest/tests/negative/test_negative_generators.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2014 Deutsche Telekom AG
-# 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 jsonschema
-import mock
-import six
-
-from tempest.common.generator import base_generator
-from tempest.common.generator import negative_generator
-from tempest.common.generator import valid_generator
-from tempest.tests import base
-
-
-class TestNegativeBasicGenerator(base.TestCase):
-    valid_desc = {
-        "name": "list-flavors-with-detail",
-        "http-method": "GET",
-        "url": "flavors/detail",
-        "json-schema": {
-            "type": "object",
-            "properties": {
-                "minRam": {"type": "integer"},
-                "minDisk": {"type": "integer"}
-            }
-        },
-        "resources": ["flavor", "volume", "image"]
-    }
-
-    minimal_desc = {
-        "name": "list-flavors-with-detail",
-        "http-method": "GET",
-        "url": "flavors/detail",
-    }
-
-    add_prop_desc = {
-        "name": "list-flavors-with-detail",
-        "http-method": "GET",
-        "url": "flavors/detail",
-        "unknown_field": [12]
-    }
-
-    invalid_json_schema_desc = {
-        "name": "list-flavors-with-detail",
-        "http-method": "GET",
-        "url": "flavors/detail",
-        "json-schema": {"type": "NotExistingType"}
-    }
-
-    def setUp(self):
-        super(TestNegativeBasicGenerator, self).setUp()
-        self.generator = base_generator.BasicGeneratorSet()
-
-    def _assert_valid_jsonschema_call(self, jsonschema_mock, desc):
-        self.assertEqual(jsonschema_mock.call_count, 1)
-        jsonschema_mock.assert_called_with(desc, self.generator.schema)
-
-    @mock.patch('jsonschema.validate', wraps=jsonschema.validate)
-    def test_validate_schema_with_valid_input(self, jsonschema_mock):
-        self.generator.validate_schema(self.valid_desc)
-        self._assert_valid_jsonschema_call(jsonschema_mock, self.valid_desc)
-
-    @mock.patch('jsonschema.validate', wraps=jsonschema.validate)
-    def test_validate_schema_with_minimal_input(self, jsonschema_mock):
-        self.generator.validate_schema(self.minimal_desc)
-        self._assert_valid_jsonschema_call(jsonschema_mock, self.minimal_desc)
-
-    def test_validate_schema_with_invalid_input(self):
-        self.assertRaises(jsonschema.ValidationError,
-                          self.generator.validate_schema, self.add_prop_desc)
-        self.assertRaises(jsonschema.SchemaError,
-                          self.generator.validate_schema,
-                          self.invalid_json_schema_desc)
-
-
-class BaseNegativeGenerator(object):
-    types = ['string', 'integer', 'object']
-
-    fake_input_obj = {"type": "object",
-                      "properties": {"minRam": {"type": "integer"},
-                                     "diskName": {"type": "string"},
-                                     "maxRam": {"type": "integer", }
-                                     }
-                      }
-
-    unknown_type_schema = {
-        "type": "not_defined"
-    }
-
-    class fake_test_class(object):
-        def __init__(self, scenario):
-            for k, v in six.iteritems(scenario):
-                setattr(self, k, v)
-
-    def _validate_result(self, valid_schema, invalid_schema):
-        for k, v in six.iteritems(valid_schema):
-            self.assertIn(k, invalid_schema)
-
-    def test_generator_mandatory_functions(self):
-        for data_type in self.types:
-            self.assertIn(data_type, self.generator.types_dict)
-
-    def test_generate_with_unknown_type(self):
-        self.assertRaises(TypeError, self.generator.generate_payload,
-                          self.unknown_type_schema)
-
-
-class TestNegativeValidGenerator(base.TestCase, BaseNegativeGenerator):
-    def setUp(self):
-        super(TestNegativeValidGenerator, self).setUp()
-        self.generator = valid_generator.ValidTestGenerator()
-
-    def test_generate_valid(self):
-        result = self.generator.generate_valid(self.fake_input_obj)
-        self.assertIn("minRam", result)
-        self.assertIsInstance(result["minRam"], int)
-        self.assertIn("diskName", result)
-        self.assertIsInstance(result["diskName"], str)
-
-
-class TestNegativeNegativeGenerator(base.TestCase, BaseNegativeGenerator):
-    def setUp(self):
-        super(TestNegativeNegativeGenerator, self).setUp()
-        self.generator = negative_generator.NegativeTestGenerator()
-
-    def test_generate_obj(self):
-        schema = self.fake_input_obj
-        scenarios = self.generator.generate_scenarios(schema)
-        for scenario in scenarios:
-            test = self.fake_test_class(scenario)
-            valid_schema = \
-                valid_generator.ValidTestGenerator().generate_valid(schema)
-            schema_under_test = copy.copy(valid_schema)
-            expected_result = \
-                self.generator.generate_payload(test, schema_under_test)
-            self.assertIsNone(expected_result)
-            self._validate_result(valid_schema, schema_under_test)
diff --git a/tempest/tests/test_negative_rest_client.py b/tempest/tests/test_negative_rest_client.py
deleted file mode 100644
index 05f9f3e..0000000
--- a/tempest/tests/test_negative_rest_client.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# (c) 2015 Deutsche Telekom AG
-# Copyright 2015 Red Hat, Inc.
-# Copyright 2015 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 mock
-from oslotest import mockpatch
-
-from tempest.common import negative_rest_client
-from tempest import config
-from tempest.tests import base
-from tempest.tests import fake_config
-from tempest.tests.lib import fake_auth_provider
-
-
-class TestNegativeRestClient(base.TestCase):
-
-    url = 'fake_endpoint'
-
-    def setUp(self):
-        super(TestNegativeRestClient, self).setUp()
-        self.useFixture(fake_config.ConfigFixture())
-        self.patchobject(config, 'TempestConfigPrivate',
-                         fake_config.FakePrivate)
-        self.negative_rest_client = negative_rest_client.NegativeRestClient(
-            fake_auth_provider.FakeAuthProvider(), None)
-        self.useFixture(mockpatch.PatchObject(self.negative_rest_client,
-                                              '_log_request'))
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.post',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_post(self, mock_post):
-        __, return_dict = self.negative_rest_client.send_request('POST',
-                                                                 self.url,
-                                                                 [], {})
-        mock_post.assert_called_once_with(self.url, {})
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.get',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_get(self, mock_get):
-        __, return_dict = self.negative_rest_client.send_request('GET',
-                                                                 self.url,
-                                                                 [])
-        mock_get.assert_called_once_with(self.url)
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.delete',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_delete(self, mock_delete):
-        __, return_dict = self.negative_rest_client.send_request('DELETE',
-                                                                 self.url,
-                                                                 [])
-        mock_delete.assert_called_once_with(self.url)
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.patch',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_patch(self, mock_patch):
-        __, return_dict = self.negative_rest_client.send_request('PATCH',
-                                                                 self.url,
-                                                                 [], {})
-        mock_patch.assert_called_once_with(self.url, {})
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.put',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_put(self, mock_put):
-        __, return_dict = self.negative_rest_client.send_request('PUT',
-                                                                 self.url,
-                                                                 [], {})
-        mock_put.assert_called_once_with(self.url, {})
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.head',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_head(self, mock_head):
-        __, return_dict = self.negative_rest_client.send_request('HEAD',
-                                                                 self.url,
-                                                                 [])
-        mock_head.assert_called_once_with(self.url)
-
-    @mock.patch('tempest.lib.common.rest_client.RestClient.copy',
-                return_value=(mock.Mock(), mock.Mock()))
-    def test_copy(self, mock_copy):
-        __, return_dict = self.negative_rest_client.send_request('COPY',
-                                                                 self.url,
-                                                                 [])
-        mock_copy.assert_called_once_with(self.url)
-
-    def test_other(self):
-        self.assertRaises(AssertionError,
-                          self.negative_rest_client.send_request,
-                          'OTHER', self.url, [])
diff --git a/test-requirements.txt b/test-requirements.txt
index 53efa46..475fb16 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,11 +1,11 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-hacking<0.12,>=0.11.0 # Apache-2.0
+hacking<0.13,>=0.12.0 # Apache-2.0
 # needed for doc build
 sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
 oslosphinx>=4.7.0 # Apache-2.0
-reno>=1.8.0 # Apache2
+reno>=1.8.0 # Apache-2.0
 mock>=2.0 # BSD
-coverage>=3.6 # Apache-2.0
+coverage>=4.0 # Apache-2.0
 oslotest>=1.10.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index 82dba92..7a36e84 100644
--- a/tox.ini
+++ b/tox.ini
@@ -143,10 +143,10 @@
 # E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved.  For further detail see https://review.openstack.org/#/c/36788/
 # E123 skipped because it is ignored by default in the default pep8
 # E129 skipped because it is too limiting when combined with other rules
-# Skipped because of new hacking 0.9: H405
 ignore = E125,E123,E129
 show-source = True
 exclude = .git,.venv,.tox,dist,doc,*egg
+enable-extensions = H106,H203
 
 [testenv:releasenotes]
 commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
@@ -161,3 +161,12 @@
 commands=
     pip-extra-reqs -d --ignore-file=tempest/tests/* tempest
     pip-missing-reqs -d --ignore-file=tempest/tests/* tempest
+
+
+[testenv:bindep]
+# Do not install any requirements. We want this to be fast and work even if
+# system dependencies are missing, since it's used to tell you what system
+# dependencies are missing! This also means that bindep must be installed
+# separately, outside of the requirements files.
+deps = bindep
+commands = bindep test