Merge "Improve volume_backed logic in create_test_server"
diff --git a/.gitignore b/.gitignore
index 9292dbb..287db4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 ChangeLog
 *.pyc
 __pycache__/
+etc/accounts.yaml
 etc/tempest.conf
 etc/tempest.conf.sample
 etc/logging.conf
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 2edaddb..04ddfdf 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,5 +1,3 @@
-# -*- coding: utf-8 -*-
-#
 # Tempest documentation build configuration file, created by
 # sphinx-quickstart on Tue May 21 17:43:32 2013.
 #
diff --git a/releasenotes/notes/add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml b/releasenotes/notes/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
similarity index 100%
rename from releasenotes/notes/add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
rename to releasenotes/notes/14.0.0-add-cred-provider-abstract-class-to-lib-70ff513221f8a871.yaml
diff --git a/releasenotes/notes/add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml b/releasenotes/notes/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
similarity index 100%
rename from releasenotes/notes/add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
rename to releasenotes/notes/14.0.0-add-cred_client-to-tempest.lib-4d4af33f969c576f.yaml
diff --git a/releasenotes/notes/add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml b/releasenotes/notes/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
similarity index 100%
rename from releasenotes/notes/add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
rename to releasenotes/notes/14.0.0-add-error-code-translation-to-versions-clients-acbc78292e24b014.yaml
diff --git a/releasenotes/notes/add-image-clients-af94564fb34ddca6.yaml b/releasenotes/notes/14.0.0-add-image-clients-af94564fb34ddca6.yaml
similarity index 100%
rename from releasenotes/notes/add-image-clients-af94564fb34ddca6.yaml
rename to releasenotes/notes/14.0.0-add-image-clients-af94564fb34ddca6.yaml
diff --git a/releasenotes/notes/add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml b/releasenotes/notes/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
similarity index 100%
rename from releasenotes/notes/add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
rename to releasenotes/notes/14.0.0-add-role-assignments-client-as-a-library-d34b4fdf376984ad.yaml
diff --git a/releasenotes/notes/add-service-provider-client-cbba77d424a30dd3.yaml b/releasenotes/notes/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml
similarity index 100%
rename from releasenotes/notes/add-service-provider-client-cbba77d424a30dd3.yaml
rename to releasenotes/notes/14.0.0-add-service-provider-client-cbba77d424a30dd3.yaml
diff --git a/releasenotes/notes/add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml b/releasenotes/notes/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
similarity index 100%
rename from releasenotes/notes/add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
rename to releasenotes/notes/14.0.0-add-ssh-port-parameter-to-client-6d16c374ac4456c1.yaml
diff --git a/releasenotes/notes/deprecate-nova-api-extensions-df16b02485dae203.yaml b/releasenotes/notes/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml
similarity index 100%
rename from releasenotes/notes/deprecate-nova-api-extensions-df16b02485dae203.yaml
rename to releasenotes/notes/14.0.0-deprecate-nova-api-extensions-df16b02485dae203.yaml
diff --git a/releasenotes/notes/move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml b/releasenotes/notes/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
similarity index 100%
rename from releasenotes/notes/move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
rename to releasenotes/notes/14.0.0-move-cinder-v3-to-lib-service-be3ba0c20753b594.yaml
diff --git a/releasenotes/notes/new-volume-limit-client-517c17d9090f4df4.yaml b/releasenotes/notes/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml
similarity index 100%
rename from releasenotes/notes/new-volume-limit-client-517c17d9090f4df4.yaml
rename to releasenotes/notes/14.0.0-new-volume-limit-client-517c17d9090f4df4.yaml
diff --git a/releasenotes/notes/remo-stress-tests-81052b211ad95d2e.yaml b/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
similarity index 100%
rename from releasenotes/notes/remo-stress-tests-81052b211ad95d2e.yaml
rename to releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
diff --git a/releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml b/releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml
new file mode 100644
index 0000000..ca2635e
--- /dev/null
+++ b/releasenotes/notes/14.0.0-remove-baremetal-tests-65186d9e15d5b8fb.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - All tests for the Ironic project have been removed from Tempest. Those
+    exist as a Tempest plugin in the Ironic project.
diff --git a/releasenotes/notes/remove-bootable-option-024f8944c056a3e0.yaml b/releasenotes/notes/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml
similarity index 100%
rename from releasenotes/notes/remove-bootable-option-024f8944c056a3e0.yaml
rename to releasenotes/notes/14.0.0-remove-bootable-option-024f8944c056a3e0.yaml
diff --git a/releasenotes/notes/remove-negative-test-generator-1653f4c0f86ccf75.yaml b/releasenotes/notes/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml
similarity index 100%
rename from releasenotes/notes/remove-negative-test-generator-1653f4c0f86ccf75.yaml
rename to releasenotes/notes/14.0.0-remove-negative-test-generator-1653f4c0f86ccf75.yaml
diff --git a/releasenotes/notes/remove-sahara-tests-1532c47c7df80e3a.yaml b/releasenotes/notes/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml
similarity index 100%
rename from releasenotes/notes/remove-sahara-tests-1532c47c7df80e3a.yaml
rename to releasenotes/notes/14.0.0-remove-sahara-tests-1532c47c7df80e3a.yaml
diff --git a/releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml b/releasenotes/notes/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml
similarity index 100%
rename from releasenotes/notes/13.1.0-volume-clients-as-library-309030c7a16e62ab.yaml
rename to releasenotes/notes/14.0.0-volume-clients-as-library-309030c7a16e62ab.yaml
diff --git a/releasenotes/notes/add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml b/releasenotes/notes/add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml
new file mode 100644
index 0000000..1af1939
--- /dev/null
+++ b/releasenotes/notes/add-identity-v3-clients-as-a-library-d34b4fdf376984ad.yaml
@@ -0,0 +1,6 @@
+---
+features:
+    - Define the identity v3 service client domains_client as a library.
+      Add domains_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-image-clients-tests-49dbc0a0a4281a77.yaml b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
new file mode 100644
index 0000000..eaab1f0
--- /dev/null
+++ b/releasenotes/notes/add-image-clients-tests-49dbc0a0a4281a77.yaml
@@ -0,0 +1,10 @@
+---
+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_objects_client(v2)
+      * namespace_tags_client(v2)
+
diff --git a/releasenotes/notes/add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml b/releasenotes/notes/add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml
new file mode 100644
index 0000000..9a4e6b1
--- /dev/null
+++ b/releasenotes/notes/add-snapshot-manage-client-as-library-a76ffdba9d8d01cb.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    Define v2 snapshot_manage_client client for the volume service as
+    library interfaces, allowing other projects to use this module as
+    stable libraries without maintenance changes.
+
+    * snapshot_manage_client(v2)
diff --git a/releasenotes/notes/deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml b/releasenotes/notes/deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml
new file mode 100644
index 0000000..4acdc6d
--- /dev/null
+++ b/releasenotes/notes/deprecate-allow_port_security_disabled-option-2d3d87f6bd11d03a.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+  - The default value for the ``allow_port_security_disabled`` option in the
+    ``compute-feature-enabled`` section has been changed from ``False``
+    to ``True``.
+deprecations:
+  - The ``allow_port_security_disabled`` option in the
+   ``compute-feature-enabled`` section is now deprecated.
diff --git a/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml b/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
new file mode 100644
index 0000000..c0a06d1
--- /dev/null
+++ b/releasenotes/notes/deprecate-identity-feature-enabled.reseller-84800a8232fe217f.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+  - The default value for the ``reseller`` option in the
+    ``identity-feature-enabled`` section has been changed from ``False``
+    to ``True``.
+deprecations:
+  - The ``reseller`` option in the ``identity-feature-enabled`` section is now
+    deprecated.
diff --git a/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml b/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
new file mode 100644
index 0000000..c80f159
--- /dev/null
+++ b/releasenotes/notes/deprecate-volume_feature_enabled.volume_services-dbe024ea067d5ab2.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+  - The default value for the ``volume_services`` option in the
+    ``volume_feature_enabled`` section has been changed from ``False``
+    to ``True``.
+deprecations:
+  - The ``volume_services`` option in the ``volume_feature_enabled`` section
+    is now deprecated.
diff --git a/releasenotes/notes/jsonschema-validator-2377ba131e12d3c7.yaml b/releasenotes/notes/jsonschema-validator-2377ba131e12d3c7.yaml
new file mode 100644
index 0000000..8817ed4
--- /dev/null
+++ b/releasenotes/notes/jsonschema-validator-2377ba131e12d3c7.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - Added customized JSON schema format checker for 'date-time' format.
+    Compute response schema will be validated against customized format
+    checker.
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index 140263c..eec42cd 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -1,4 +1,3 @@
-# -*- 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
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/__init__.py b/tempest/api/baremetal/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/baremetal/__init__.py
+++ /dev/null
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 e74dd04..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.lib 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 40cb523..118ad60 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -12,13 +12,9 @@
 #    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__)
+from tempest.lib import decorators
 
 
 class AgentsAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -48,7 +44,7 @@
             kwargs[rand_key] = data_utils.rand_name(kwargs[rand_key])
         return kwargs
 
-    @test.idempotent_id('1fc6bdc8-0b6d-4cc7-9f30-9b04fabe5b90')
+    @decorators.idempotent_id('1fc6bdc8-0b6d-4cc7-9f30-9b04fabe5b90')
     def test_create_agent(self):
         # Create an agent.
         params = self._param_helper(
@@ -60,7 +56,7 @@
         for expected_item, value in params.items():
             self.assertEqual(value, body[expected_item])
 
-    @test.idempotent_id('dc9ffd51-1c50-4f0e-a820-ae6d2a568a9e')
+    @decorators.idempotent_id('dc9ffd51-1c50-4f0e-a820-ae6d2a568a9e')
     def test_update_agent(self):
         # Create and update an agent.
         body = self.client.create_agent(**self.params_agent)['agent']
@@ -73,7 +69,7 @@
         for expected_item, value in params.items():
             self.assertEqual(value, body[expected_item])
 
-    @test.idempotent_id('470e0b89-386f-407b-91fd-819737d0b335')
+    @decorators.idempotent_id('470e0b89-386f-407b-91fd-819737d0b335')
     def test_delete_agent(self):
         # Create an agent and delete it.
         body = self.client.create_agent(**self.params_agent)['agent']
@@ -84,7 +80,7 @@
         self.assertNotIn(body['agent_id'], map(lambda x: x['agent_id'],
                                                agents))
 
-    @test.idempotent_id('6a326c69-654b-438a-80a3-34bcc454e138')
+    @decorators.idempotent_id('6a326c69-654b-438a-80a3-34bcc454e138')
     def test_list_agents(self):
         # Create an agent and  list all agents.
         body = self.client.create_agent(**self.params_agent)['agent']
@@ -94,7 +90,7 @@
                            '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')
+    @decorators.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
     def test_list_agents_with_filter(self):
         # Create agents and list the agent builds by the filter.
         body = self.client.create_agent(**self.params_agent)['agent']
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 1233a2b..36ce975 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -20,7 +20,7 @@
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.lib.common.utils import test_utils
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -59,7 +59,7 @@
                 msg += " for hypervisor_type %s" % CONF.compute.hypervisor_type
             raise testtools.TestCase.failureException(msg)
 
-    @test.idempotent_id('0d148aa3-d54c-4317-aa8d-42040a475e20')
+    @decorators.idempotent_id('0d148aa3-d54c-4317-aa8d-42040a475e20')
     def test_aggregate_create_delete(self):
         # Create and delete an aggregate.
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -73,7 +73,7 @@
         self.client.delete_aggregate(aggregate['id'])
         self.client.wait_for_resource_deletion(aggregate['id'])
 
-    @test.idempotent_id('5873a6f8-671a-43ff-8838-7ce430bb6d0b')
+    @decorators.idempotent_id('5873a6f8-671a-43ff-8838-7ce430bb6d0b')
     def test_aggregate_create_delete_with_az(self):
         # Create and delete an aggregate.
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -88,7 +88,7 @@
         self.client.delete_aggregate(aggregate['id'])
         self.client.wait_for_resource_deletion(aggregate['id'])
 
-    @test.idempotent_id('68089c38-04b1-4758-bdf0-cf0daec4defd')
+    @decorators.idempotent_id('68089c38-04b1-4758-bdf0-cf0daec4defd')
     def test_aggregate_create_verify_entry_in_list(self):
         # Create an aggregate and ensure it is listed.
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -101,7 +101,7 @@
                       map(lambda x: (x['id'], x['availability_zone']),
                           aggregates))
 
-    @test.idempotent_id('36ec92ca-7a73-43bc-b920-7531809e8540')
+    @decorators.idempotent_id('36ec92ca-7a73-43bc-b920-7531809e8540')
     def test_aggregate_create_update_metadata_get_details(self):
         # Create an aggregate and ensure its details are returned.
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -124,7 +124,7 @@
         body = self.client.show_aggregate(aggregate['id'])['aggregate']
         self.assertEqual(meta, body["metadata"])
 
-    @test.idempotent_id('4d2b2004-40fa-40a1-aab2-66f4dab81beb')
+    @decorators.idempotent_id('4d2b2004-40fa-40a1-aab2-66f4dab81beb')
     def test_aggregate_create_update_with_az(self):
         # Update an aggregate and ensure properties are updated correctly
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -154,7 +154,7 @@
                           (x['id'], x['name'], x['availability_zone']),
                           aggregates))
 
-    @test.idempotent_id('c8e85064-e79b-4906-9931-c11c24294d02')
+    @decorators.idempotent_id('c8e85064-e79b-4906-9931-c11c24294d02')
     def test_aggregate_add_remove_host(self):
         # Add a host to the given aggregate and remove.
         self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -177,7 +177,7 @@
                          body['availability_zone'])
         self.assertNotIn(self.host, body['hosts'])
 
-    @test.idempotent_id('7f6a1cc5-2446-4cdb-9baa-b6ae0a919b72')
+    @decorators.idempotent_id('7f6a1cc5-2446-4cdb-9baa-b6ae0a919b72')
     def test_aggregate_add_host_list(self):
         # Add a host to the given aggregate and list.
         self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -197,7 +197,7 @@
         self.assertIsNone(agg['availability_zone'])
         self.assertIn(self.host, agg['hosts'])
 
-    @test.idempotent_id('eeef473c-7c52-494d-9f09-2ed7fc8fc036')
+    @decorators.idempotent_id('eeef473c-7c52-494d-9f09-2ed7fc8fc036')
     def test_aggregate_add_host_get_details(self):
         # Add a host to the given aggregate and get details.
         self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -214,7 +214,7 @@
         self.assertIsNone(body['availability_zone'])
         self.assertIn(self.host, body['hosts'])
 
-    @test.idempotent_id('96be03c7-570d-409c-90f8-e4db3c646996')
+    @decorators.idempotent_id('96be03c7-570d-409c-90f8-e4db3c646996')
     def test_aggregate_add_host_create_server_with_az(self):
         # Add a host to the given aggregate and create a server.
         self.useFixture(fixtures.LockFixture('availability_zone'))
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 85aa301..deded73 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -16,6 +16,7 @@
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -48,7 +49,7 @@
         return aggregate
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
+    @decorators.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
     def test_aggregate_create_as_user(self):
         # Regular user is not allowed to create an aggregate.
         aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -57,7 +58,7 @@
                           name=aggregate_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('3b8a1929-3793-4e92-bcb4-dfa572ee6c1d')
+    @decorators.idempotent_id('3b8a1929-3793-4e92-bcb4-dfa572ee6c1d')
     def test_aggregate_create_aggregate_name_length_less_than_1(self):
         # the length of aggregate name should >= 1 and <=255
         self.assertRaises(lib_exc.BadRequest,
@@ -65,7 +66,7 @@
                           name='')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('4c194563-543b-4e70-a719-557bbe947fac')
+    @decorators.idempotent_id('4c194563-543b-4e70-a719-557bbe947fac')
     def test_aggregate_create_aggregate_name_length_exceeds_255(self):
         # the length of aggregate name should >= 1 and <=255
         aggregate_name = 'a' * 256
@@ -74,7 +75,7 @@
                           name=aggregate_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9c23a291-b0b1-487b-b464-132e061151b3')
+    @decorators.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 = self._create_test_aggregate()
@@ -83,7 +84,7 @@
                           name=aggregate['name'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
+    @decorators.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
         aggregate = self._create_test_aggregate()
@@ -92,14 +93,14 @@
                           aggregate['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('b7d475a6-5dcd-4ff4-b70a-cd9de66a6672')
+    @decorators.idempotent_id('b7d475a6-5dcd-4ff4-b70a-cd9de66a6672')
     def test_aggregate_list_as_user(self):
         # Regular user is not allowed to list aggregates.
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.list_aggregates)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('557cad12-34c9-4ff4-95f0-22f0dfbaf7dc')
+    @decorators.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 = self._create_test_aggregate()
@@ -108,21 +109,21 @@
                           aggregate['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('c74f4bf1-4708-4ff2-95a0-f49eaca951bd')
+    @decorators.idempotent_id('c74f4bf1-4708-4ff2-95a0-f49eaca951bd')
     def test_aggregate_delete_with_invalid_id(self):
         # Delete an aggregate with invalid id should raise exceptions.
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_aggregate, -1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('3c916244-2c46-49a4-9b55-b20bb0ae512c')
+    @decorators.idempotent_id('3c916244-2c46-49a4-9b55-b20bb0ae512c')
     def test_aggregate_get_details_with_invalid_id(self):
         # Get aggregate details with invalid id should raise exceptions.
         self.assertRaises(lib_exc.NotFound,
                           self.client.show_aggregate, -1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
+    @decorators.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
     def test_aggregate_add_non_exist_host(self):
         # Adding a non-exist host to an aggregate should raise exceptions.
         hosts_all = self.os_adm.hosts_client.list_hosts()['hosts']
@@ -136,7 +137,7 @@
                           aggregate['id'], host=non_exist_host)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7324c334-bd13-4c93-8521-5877322c3d51')
+    @decorators.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 = self._create_test_aggregate()
@@ -145,7 +146,7 @@
                           aggregate['id'], host=self.host)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
+    @decorators.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
     def test_aggregate_add_existent_host(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
         aggregate = self._create_test_aggregate()
@@ -158,7 +159,7 @@
                           aggregate['id'], host=self.host)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7a53af20-137a-4e44-a4ae-e19260e626d9')
+    @decorators.idempotent_id('7a53af20-137a-4e44-a4ae-e19260e626d9')
     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'))
@@ -173,7 +174,7 @@
                           aggregate['id'], host=self.host)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
+    @decorators.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
     def test_aggregate_remove_nonexistent_host(self):
         aggregate = self._create_test_aggregate()
 
diff --git a/tempest/api/compute/admin/test_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
index 8e481fd..7fda732 100644
--- a/tempest/api/compute/admin/test_auto_allocate_network.py
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -17,9 +17,9 @@
 from tempest.api.compute import base
 from tempest.common import compute
 from tempest.common import credentials_factory as credentials
-from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_excs
 from tempest import test
 
@@ -146,22 +146,20 @@
             test_utils.call_and_ignore_notfound_exc(
                 cls.networks_client.delete_network, network['id'])
 
-    @test.idempotent_id('5eb7b8fa-9c23-47a2-9d7d-02ed5809dd34')
+    @decorators.idempotent_id('5eb7b8fa-9c23-47a2-9d7d-02ed5809dd34')
     def test_server_create_no_allocate(self):
         """Tests that no networking is allocated for the server."""
         # create the server with no networking
         server, _ = compute.create_test_server(
             self.os, networks='none', wait_until='ACTIVE')
-        self.addCleanup(waiters.wait_for_server_termination,
-                        self.servers_client, server['id'])
-        self.addCleanup(self.servers_client.delete_server, server['id'])
+        self.addCleanup(self.delete_server, server['id'])
         # get the server ips
         addresses = self.servers_client.list_addresses(
             server['id'])['addresses']
         # assert that there is no networking
         self.assertEqual({}, addresses)
 
-    @test.idempotent_id('2e6cf129-9e28-4e8a-aaaa-045ea826b2a6')
+    @decorators.idempotent_id('2e6cf129-9e28-4e8a-aaaa-045ea826b2a6')
     def test_server_multi_create_auto_allocate(self):
         """Tests that networking is auto-allocated for multiple servers."""
 
@@ -182,9 +180,7 @@
             min_count=3)
         server_nets = set()
         for server in servers:
-            self.addCleanup(waiters.wait_for_server_termination,
-                            self.servers_client, server['id'])
-            self.addCleanup(self.servers_client.delete_server, server['id'])
+            self.addCleanup(self.delete_server, server['id'])
             # get the server ips
             addresses = self.servers_client.list_addresses(
                 server['id'])['addresses']
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index 3470602..50dec28 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class AZAdminV2TestJSON(base.BaseV2ComputeAdminTest):
@@ -25,13 +25,13 @@
         super(AZAdminV2TestJSON, cls).setup_clients()
         cls.client = cls.availability_zone_admin_client
 
-    @test.idempotent_id('d3431479-8a09-4f76-aa2d-26dc580cb27c')
+    @decorators.idempotent_id('d3431479-8a09-4f76-aa2d-26dc580cb27c')
     def test_get_availability_zone_list(self):
         # List of availability zone
         availability_zone = self.client.list_availability_zones()
         self.assertGreater(len(availability_zone['availabilityZoneInfo']), 0)
 
-    @test.idempotent_id('ef726c58-530f-44c2-968c-c7bed22d5b8c')
+    @decorators.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)
diff --git a/tempest/api/compute/admin/test_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index c60de1e..faeb811 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -26,7 +27,7 @@
         cls.non_adm_client = cls.availability_zone_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('bf34dca2-fdc3-4073-9c02-7648d9eae0d7')
+    @decorators.idempotent_id('bf34dca2-fdc3-4073-9c02-7648d9eae0d7')
     def test_get_availability_zone_list_detail_with_non_admin_user(self):
         # List of availability zones and available services with
         # non-administrator user
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
index b764483..7726ed4 100644
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -14,6 +14,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -25,18 +26,18 @@
     @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
         cls.ironic_client = cls.os_adm.baremetal_client
 
     @test.attr(type=['baremetal'])
-    @test.idempotent_id('e475aa6e-416d-4fa4-b3af-28d5e84250fb')
+    @decorators.idempotent_id('e475aa6e-416d-4fa4-b3af-28d5e84250fb')
     def test_list_get_baremetal_nodes(self):
         # Create some test nodes in Ironic directly
         test_nodes = []
-        for i in range(0, 3):
+        for _ in range(0, 3):
             _, node = self.ironic_client.create_node()
             test_nodes.append(node)
             self.addCleanup(self.ironic_client.delete_node, node['uuid'])
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index 9cda0cd..10ed519 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -47,18 +48,18 @@
             if cls.ip:
                 break
 
-    @test.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
+    @decorators.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
     @test.services('network')
     def test_list_fixed_ip_details(self):
         fixed_ip = self.client.show_fixed_ip(self.ip)
         self.assertEqual(fixed_ip['fixed_ip']['address'], self.ip)
 
-    @test.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
+    @decorators.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
     @test.services('network')
     def test_set_reserve(self):
         self.client.reserve_fixed_ip(self.ip, reserve="None")
 
-    @test.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
+    @decorators.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
     @test.services('network')
     def test_set_unreserve(self):
         self.client.reserve_fixed_ip(self.ip, unreserve="None")
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index 05bba21..073f152 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -14,6 +14,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -49,14 +50,14 @@
                 break
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
+    @decorators.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
     @test.services('network')
     def test_list_fixed_ip_details_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_fixed_ip, self.ip)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
+    @decorators.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
     @test.services('network')
     def test_set_reserve_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -64,7 +65,7 @@
                           self.ip, reserve="None")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
+    @decorators.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
     @test.services('network')
     def test_set_unreserve_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -72,7 +73,7 @@
                           self.ip, unreserve="None")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
+    @decorators.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
     @test.services('network')
     def test_set_reserve_with_invalid_ip(self):
         # NOTE(maurosr): since this exercises the same code snippet, we do it
@@ -85,7 +86,7 @@
                           "my.invalid.ip", reserve="None")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
+    @decorators.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
     @test.services('network')
     def test_fixed_ip_with_invalid_action(self):
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index fde5622..3fd1612 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -17,6 +17,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -83,19 +84,19 @@
 
         return flavor['id']
 
-    @test.idempotent_id('8b4330e1-12c4-4554-9390-e6639971f086')
+    @decorators.idempotent_id('8b4330e1-12c4-4554-9390-e6639971f086')
     def test_create_flavor_with_int_id(self):
         flavor_id = data_utils.rand_int_id(start=1000)
         new_flavor_id = self._create_flavor(flavor_id)
         self.assertEqual(new_flavor_id, str(flavor_id))
 
-    @test.idempotent_id('94c9bb4e-2c2a-4f3c-bb1f-5f0daf918e6d')
+    @decorators.idempotent_id('94c9bb4e-2c2a-4f3c-bb1f-5f0daf918e6d')
     def test_create_flavor_with_uuid_id(self):
         flavor_id = data_utils.rand_uuid()
         new_flavor_id = self._create_flavor(flavor_id)
         self.assertEqual(new_flavor_id, flavor_id)
 
-    @test.idempotent_id('f83fe669-6758-448a-a85e-32d351f36fe0')
+    @decorators.idempotent_id('f83fe669-6758-448a-a85e-32d351f36fe0')
     def test_create_flavor_with_none_id(self):
         # If nova receives a request with None as flavor_id,
         # nova generates flavor_id of uuid.
@@ -103,7 +104,7 @@
         new_flavor_id = self._create_flavor(flavor_id)
         self.assertEqual(new_flavor_id, str(uuid.UUID(new_flavor_id)))
 
-    @test.idempotent_id('8261d7b0-be58-43ec-a2e5-300573c3f6c5')
+    @decorators.idempotent_id('8261d7b0-be58-43ec-a2e5-300573c3f6c5')
     def test_create_flavor_verify_entry_in_list_details(self):
         # Create a flavor and ensure it's details are listed
         # This operation requires the user to have 'admin' role
@@ -127,7 +128,7 @@
                 flag = True
         self.assertTrue(flag)
 
-    @test.idempotent_id('63dc64e6-2e79-4fdf-868f-85500d308d66')
+    @decorators.idempotent_id('63dc64e6-2e79-4fdf-868f-85500d308d66')
     def test_create_list_flavor_without_extra_data(self):
         # Create a flavor and ensure it is listed
         # This operation requires the user to have 'admin' role
@@ -169,7 +170,7 @@
                 flag = True
         self.assertTrue(flag)
 
-    @test.idempotent_id('be6cc18c-7c5d-48c0-ac16-17eaf03c54eb')
+    @decorators.idempotent_id('be6cc18c-7c5d-48c0-ac16-17eaf03c54eb')
     def test_list_non_public_flavor(self):
         # Create a flavor with os-flavor-access:is_public false.
         # The flavor should not be present in list_details as the
@@ -201,7 +202,7 @@
                 flag = True
         self.assertFalse(flag)
 
-    @test.idempotent_id('bcc418ef-799b-47cc-baa1-ce01368b8987')
+    @decorators.idempotent_id('bcc418ef-799b-47cc-baa1-ce01368b8987')
     def test_create_server_with_non_public_flavor(self):
         # Create a flavor with os-flavor-access:is_public false
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -221,7 +222,7 @@
                           name='test', imageRef=self.image_ref,
                           flavorRef=flavor['id'])
 
-    @test.idempotent_id('b345b196-bfbd-4231-8ac1-6d7fe15ff3a3')
+    @decorators.idempotent_id('b345b196-bfbd-4231-8ac1-6d7fe15ff3a3')
     def test_list_public_flavor_with_other_user(self):
         # Create a Flavor with public access.
         # Try to List/Get flavor with another user
@@ -244,7 +245,7 @@
                 flag = True
         self.assertTrue(flag)
 
-    @test.idempotent_id('fb9cbde6-3a0e-41f2-a983-bdb0a823c44e')
+    @decorators.idempotent_id('fb9cbde6-3a0e-41f2-a983-bdb0a823c44e')
     def test_is_public_string_variations(self):
         flavor_id_not_public = data_utils.rand_int_id(start=1000)
         flavor_name_not_public = data_utils.rand_name(self.flavor_name_prefix)
@@ -287,7 +288,7 @@
         _test_string_variations(['t', 'true', 'yes', '1'],
                                 flavor_name_public)
 
-    @test.idempotent_id('3b541a2e-2ac2-4b42-8b8d-ba6e22fcd4da')
+    @decorators.idempotent_id('3b541a2e-2ac2-4b42-8b8d-ba6e22fcd4da')
     def test_create_flavor_using_string_ram(self):
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 2063267..38ff4c0 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -47,7 +48,7 @@
         cls.vcpus = 1
         cls.disk = 10
 
-    @test.idempotent_id('ea2c2211-29fa-4db9-97c3-906d36fad3e0')
+    @decorators.idempotent_id('ea2c2211-29fa-4db9-97c3-906d36fad3e0')
     def test_flavor_access_list_with_private_flavor(self):
         # Test to make sure that list flavor access on a newly created
         # private flavor will return an empty access list
@@ -63,7 +64,7 @@
                          ['flavor_access'])
         self.assertEqual(len(flavor_access), 0, str(flavor_access))
 
-    @test.idempotent_id('59e622f6-bdf6-45e3-8ba8-fedad905a6b4')
+    @decorators.idempotent_id('59e622f6-bdf6-45e3-8ba8-fedad905a6b4')
     def test_flavor_access_add_remove(self):
         # Test to add and remove flavor access to a given tenant.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 1b7eb12..2719cc4 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -48,7 +49,7 @@
         cls.disk = 10
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0621c53e-d45d-40e7-951d-43e5e257b272')
+    @decorators.idempotent_id('0621c53e-d45d-40e7-951d-43e5e257b272')
     def test_flavor_access_list_with_public_flavor(self):
         # Test to list flavor access with exceptions by querying public flavor
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -64,7 +65,7 @@
                           new_flavor_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('41eaaade-6d37-4f28-9c74-f21b46ca67bd')
+    @decorators.idempotent_id('41eaaade-6d37-4f28-9c74-f21b46ca67bd')
     def test_flavor_non_admin_add(self):
         # Test to add flavor access as a user without admin privileges.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -81,7 +82,7 @@
                           self.tenant_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('073e79a6-c311-4525-82dc-6083d919cb3a')
+    @decorators.idempotent_id('073e79a6-c311-4525-82dc-6083d919cb3a')
     def test_flavor_non_admin_remove(self):
         # Test to remove flavor access as a user without admin privileges.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -102,7 +103,7 @@
                           self.tenant_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
+    @decorators.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
     def test_add_flavor_access_duplicate(self):
         # Create a new flavor.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -127,7 +128,7 @@
                           self.tenant_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
+    @decorators.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
     def test_remove_flavor_access_not_found(self):
         # Create a new flavor.
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 661cd18..70e662c 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -63,7 +64,7 @@
         cls.client.wait_for_resource_deletion(cls.flavor['id'])
         super(FlavorsExtraSpecsTestJSON, cls).resource_cleanup()
 
-    @test.idempotent_id('0b2f9d4b-1ca2-4b99-bb40-165d4bb94208')
+    @decorators.idempotent_id('0b2f9d4b-1ca2-4b99-bb40-165d4bb94208')
     def test_flavor_set_get_update_show_unset_keys(self):
         # Test to SET, GET, UPDATE, SHOW, UNSET flavor extra
         # spec as a user with admin privileges.
@@ -95,7 +96,7 @@
         self.client.unset_flavor_extra_spec(self.flavor['id'], "key1")
         self.client.unset_flavor_extra_spec(self.flavor['id'], "key2")
 
-    @test.idempotent_id('a99dad88-ae1c-4fba-aeb4-32f898218bd0')
+    @decorators.idempotent_id('a99dad88-ae1c-4fba-aeb4-32f898218bd0')
     def test_flavor_non_admin_get_all_keys(self):
         specs = {"key1": "value1", "key2": "value2"}
         self.client.set_flavor_extra_spec(self.flavor['id'], **specs)
@@ -105,7 +106,7 @@
         for key in specs:
             self.assertEqual(body[key], specs[key])
 
-    @test.idempotent_id('12805a7f-39a3-4042-b989-701d5cad9c90')
+    @decorators.idempotent_id('12805a7f-39a3-4042-b989-701d5cad9c90')
     def test_flavor_non_admin_get_specific_key(self):
         body = self.client.set_flavor_extra_spec(self.flavor['id'],
                                                  key1="value1",
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 7eb4bbf..767a1ca 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -16,6 +16,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -66,7 +67,7 @@
         super(FlavorsExtraSpecsNegativeTestJSON, cls).resource_cleanup()
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a00a3b81-5641-45a8-ab2b-4a8ec41e1d7d')
+    @decorators.idempotent_id('a00a3b81-5641-45a8-ab2b-4a8ec41e1d7d')
     def test_flavor_non_admin_set_keys(self):
         # Test to SET flavor extra spec as a user without admin privileges.
         self.assertRaises(lib_exc.Forbidden,
@@ -75,7 +76,7 @@
                           key1="value1", key2="value2")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1ebf4ef8-759e-48fe-a801-d451d80476fb')
+    @decorators.idempotent_id('1ebf4ef8-759e-48fe-a801-d451d80476fb')
     def test_flavor_non_admin_update_specific_key(self):
         # non admin user is not allowed to update flavor extra spec
         body = self.client.set_flavor_extra_spec(
@@ -89,7 +90,7 @@
                           key1='value1_new')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
+    @decorators.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
     def test_flavor_non_admin_unset_keys(self):
         self.client.set_flavor_extra_spec(self.flavor['id'],
                                           key1="value1", key2="value2")
@@ -100,7 +101,7 @@
                           'key1')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
+    @decorators.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
     def test_flavor_unset_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.unset_flavor_extra_spec,
@@ -108,7 +109,7 @@
                           'nonexistent_key')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
+    @decorators.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
     def test_flavor_get_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
                           self.flavors_client.show_flavor_extra_spec,
@@ -116,7 +117,7 @@
                           "nonexistent_key")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('25b822b8-9f49-44f6-80de-d99f0482e5cb')
+    @decorators.idempotent_id('25b822b8-9f49-44f6-80de-d99f0482e5cb')
     def test_flavor_update_mismatch_key(self):
         # the key will be updated should be match the key in the body
         self.assertRaises(lib_exc.BadRequest,
@@ -126,7 +127,7 @@
                           key1="value")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f5889590-bf66-41cc-b4b1-6e6370cfd93f')
+    @decorators.idempotent_id('f5889590-bf66-41cc-b4b1-6e6370cfd93f')
     def test_flavor_update_more_key(self):
         # there should be just one item in the request body
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index a4695b0..f38af56 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -18,6 +18,7 @@
 from tempest.api.compute import base
 from tempest import config
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
 
@@ -55,7 +56,7 @@
                 raise exceptions.InvalidConfiguration(msg)
         return
 
-    @test.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
+    @decorators.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
     @test.services('network')
     def test_create_list_delete_floating_ips_bulk(self):
         # Create, List  and delete the Floating IPs Bulk
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index 3797b29..b664955 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -14,7 +14,7 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
-from tempest import test
+from tempest.lib import decorators
 
 
 class HostsAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -25,12 +25,12 @@
         super(HostsAdminTestJSON, cls).setup_clients()
         cls.client = cls.os_adm.hosts_client
 
-    @test.idempotent_id('9bfaf98d-e2cb-44b0-a07e-2558b2821e4f')
+    @decorators.idempotent_id('9bfaf98d-e2cb-44b0-a07e-2558b2821e4f')
     def test_list_hosts(self):
         hosts = self.client.list_hosts()['hosts']
         self.assertGreaterEqual(len(hosts), 2, str(hosts))
 
-    @test.idempotent_id('5dc06f5b-d887-47a2-bb2a-67762ef3c6de')
+    @decorators.idempotent_id('5dc06f5b-d887-47a2-bb2a-67762ef3c6de')
     def test_list_hosts_with_zone(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
         hosts = self.client.list_hosts()['hosts']
@@ -39,21 +39,21 @@
         self.assertGreaterEqual(len(hosts), 1)
         self.assertIn(host, hosts)
 
-    @test.idempotent_id('9af3c171-fbf4-4150-a624-22109733c2a6')
+    @decorators.idempotent_id('9af3c171-fbf4-4150-a624-22109733c2a6')
     def test_list_hosts_with_a_blank_zone(self):
         # If send the request with a blank zone, the request will be successful
         # and it will return all the hosts list
         hosts = self.client.list_hosts(zone='')['hosts']
         self.assertNotEqual(0, len(hosts))
 
-    @test.idempotent_id('c6ddbadb-c94e-4500-b12f-8ffc43843ff8')
+    @decorators.idempotent_id('c6ddbadb-c94e-4500-b12f-8ffc43843ff8')
     def test_list_hosts_with_nonexistent_zone(self):
         # If send the request with a nonexistent zone, the request will be
         # successful and no hosts will be returned
         hosts = self.client.list_hosts(zone='xxx')['hosts']
         self.assertEqual(0, len(hosts))
 
-    @test.idempotent_id('38adbb12-aee2-4498-8aec-329c72423aa4')
+    @decorators.idempotent_id('38adbb12-aee2-4498-8aec-329c72423aa4')
     def test_show_host_detail(self):
         hosts = self.client.list_hosts()['hosts']
 
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 3821b22..07ab8c5 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -35,26 +36,26 @@
         cls.hostname = hosts[0]['host_name']
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
+    @decorators.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
     def test_list_hosts_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.list_hosts)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
+    @decorators.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
     def test_show_host_detail_with_nonexistent_hostname(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.show_host, 'nonexistent_hostname')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
+    @decorators.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
     def test_show_host_detail_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_host,
                           self.hostname)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
+    @decorators.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
     def test_update_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.update_host,
@@ -63,7 +64,7 @@
                           maintenance_mode='enable')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
+    @decorators.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
         self.assertRaises(lib_exc.BadRequest,
@@ -73,7 +74,7 @@
                           maintenance_mode='enable')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
+    @decorators.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
     def test_update_host_with_invalid_maintenance_mode(self):
         # 'maintenance_mode' can only be 'enable' or 'disable'
         self.assertRaises(lib_exc.BadRequest,
@@ -83,7 +84,7 @@
                           maintenance_mode='invalid')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
+    @decorators.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
         self.assertRaises(lib_exc.BadRequest,
@@ -91,7 +92,7 @@
                           self.hostname)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
+    @decorators.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
     def test_update_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.update_host,
@@ -100,42 +101,42 @@
                           maintenance_mode='enable')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
+    @decorators.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
     def test_startup_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.startup_host,
                           'nonexistent_hostname')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
+    @decorators.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
     def test_startup_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.startup_host,
                           self.hostname)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
+    @decorators.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
     def test_shutdown_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.shutdown_host,
                           'nonexistent_hostname')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
+    @decorators.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
     def test_shutdown_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.shutdown_host,
                           self.hostname)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
+    @decorators.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
     def test_reboot_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.reboot_host,
                           'nonexistent_hostname')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
+    @decorators.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
     def test_reboot_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.reboot_host,
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 1f043dc..4637024 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class HypervisorAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -33,19 +33,19 @@
     def assertHypervisors(self, hypers):
         self.assertGreater(len(hypers), 0, "No hypervisors found: %s" % hypers)
 
-    @test.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
+    @decorators.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
     def test_get_hypervisor_list(self):
         # List of hypervisor and available hypervisors hostname
         hypers = self._list_hypervisors()
         self.assertHypervisors(hypers)
 
-    @test.idempotent_id('1e7fdac2-b672-4ad1-97a4-bad0e3030118')
+    @decorators.idempotent_id('1e7fdac2-b672-4ad1-97a4-bad0e3030118')
     def test_get_hypervisor_list_details(self):
         # Display the details of the all hypervisor
         hypers = self.client.list_hypervisors(detail=True)['hypervisors']
         self.assertHypervisors(hypers)
 
-    @test.idempotent_id('94ff9eae-a183-428e-9cdb-79fde71211cc')
+    @decorators.idempotent_id('94ff9eae-a183-428e-9cdb-79fde71211cc')
     def test_get_hypervisor_show_details(self):
         # Display the details of the specified hypervisor
         hypers = self._list_hypervisors()
@@ -56,7 +56,7 @@
         self.assertEqual(details['hypervisor_hostname'],
                          hypers[0]['hypervisor_hostname'])
 
-    @test.idempotent_id('e81bba3f-6215-4e39-a286-d52d2f906862')
+    @decorators.idempotent_id('e81bba3f-6215-4e39-a286-d52d2f906862')
     def test_get_hypervisor_show_servers(self):
         # Show instances about the specific hypervisors
         hypers = self._list_hypervisors()
@@ -67,14 +67,14 @@
                        ['hypervisors'])
         self.assertGreater(len(hypervisors), 0)
 
-    @test.idempotent_id('797e4f28-b6e0-454d-a548-80cc77c00816')
+    @decorators.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.assertGreater(len(stats), 0)
 
-    @test.idempotent_id('91a50d7d-1c2b-4f24-b55a-a1fe20efca70')
+    @decorators.idempotent_id('91a50d7d-1c2b-4f24-b55a-a1fe20efca70')
     def test_get_hypervisor_uptime(self):
         # Verify that GET shows the specified hypervisor uptime
         hypers = self._list_hypervisors()
@@ -113,7 +113,7 @@
             has_valid_uptime,
             "None of the hypervisors had a valid uptime: %s" % hypers)
 
-    @test.idempotent_id('d7e1805b-3b14-4a3b-b6fd-50ec6d9f361f')
+    @decorators.idempotent_id('d7e1805b-3b14-4a3b-b6fd-50ec6d9f361f')
     def test_search_hypervisor(self):
         hypers = self._list_hypervisors()
         self.assertHypervisors(hypers)
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index 0f35e14..1a37312 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -34,7 +35,7 @@
         return hypers
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
+    @decorators.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
     def test_show_nonexistent_hypervisor(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
 
@@ -44,7 +45,7 @@
             nonexistent_hypervisor_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
+    @decorators.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
     def test_show_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
         self.assertGreater(len(hypers), 0)
@@ -55,7 +56,7 @@
             hypers[0]['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
+    @decorators.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
     def test_show_servers_with_non_admin_user(self):
         hypers = self._list_hypervisors()
         self.assertGreater(len(hypers), 0)
@@ -66,7 +67,7 @@
             hypers[0]['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('02463d69-0ace-4d33-a4a8-93d7883a2bba')
+    @decorators.idempotent_id('02463d69-0ace-4d33-a4a8-93d7883a2bba')
     def test_show_servers_with_nonexistent_hypervisor(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
 
@@ -76,14 +77,14 @@
             nonexistent_hypervisor_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e2b061bb-13f9-40d8-9d6e-d5bf17595849')
+    @decorators.idempotent_id('e2b061bb-13f9-40d8-9d6e-d5bf17595849')
     def test_get_hypervisor_stats_with_non_admin_user(self):
         self.assertRaises(
             lib_exc.Forbidden,
             self.non_adm_client.show_hypervisor_statistics)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
+    @decorators.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
     def test_get_nonexistent_hypervisor_uptime(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
 
@@ -93,7 +94,7 @@
             nonexistent_hypervisor_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
+    @decorators.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
     def test_get_hypervisor_uptime_with_non_admin_user(self):
         hypers = self._list_hypervisors()
         self.assertGreater(len(hypers), 0)
@@ -104,7 +105,7 @@
             hypers[0]['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('51b3d536-9b14-409c-9bce-c6f7c794994e')
+    @decorators.idempotent_id('51b3d536-9b14-409c-9bce-c6f7c794994e')
     def test_get_hypervisor_list_with_non_admin_user(self):
         # List of hypervisor and available services with non admin user
         self.assertRaises(
@@ -112,7 +113,7 @@
             self.non_adm_client.list_hypervisors)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('dc02db05-e801-4c5f-bc8e-d915290ab345')
+    @decorators.idempotent_id('dc02db05-e801-4c5f-bc8e-d915290ab345')
     def test_get_hypervisor_list_details_with_non_admin_user(self):
         # List of hypervisor details and available services with non admin user
         self.assertRaises(
@@ -120,7 +121,7 @@
             self.non_adm_client.list_hypervisors, detail=True)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
+    @decorators.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
     def test_search_nonexistent_hypervisor(self):
         self.assertRaises(
             lib_exc.NotFound,
@@ -128,7 +129,7 @@
             'nonexistent_hypervisor_name')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
+    @decorators.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
     def test_search_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
         self.assertGreater(len(hypers), 0)
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index 6976783..b613a26 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -18,7 +18,7 @@
 from six.moves.urllib import parse as urllib
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
@@ -28,7 +28,7 @@
         super(InstanceUsageAuditLogTestJSON, cls).setup_clients()
         cls.adm_client = cls.os_adm.instance_usages_audit_log_client
 
-    @test.idempotent_id('25319919-33d9-424f-9f99-2c203ee48b9d')
+    @decorators.idempotent_id('25319919-33d9-424f-9f99-2c203ee48b9d')
     def test_list_instance_usage_audit_logs(self):
         # list instance usage audit logs
         body = (self.adm_client.list_instance_usage_audit_logs()
@@ -41,7 +41,7 @@
         for item in expected_items:
             self.assertIn(item, body)
 
-    @test.idempotent_id('6e40459d-7c5f-400b-9e83-449fbc8e7feb')
+    @decorators.idempotent_id('6e40459d-7c5f-400b-9e83-449fbc8e7feb')
     def test_get_instance_usage_audit_log(self):
         # Get instance usage audit log before specified time
         now = datetime.datetime.now()
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index b908502..16c39c4 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -18,6 +18,7 @@
 from six.moves.urllib import parse as urllib
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -30,7 +31,7 @@
         cls.adm_client = cls.os_adm.instance_usages_audit_log_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a9d33178-d2c9-4131-ad3b-f4ca8d0308a2')
+    @decorators.idempotent_id('a9d33178-d2c9-4131-ad3b-f4ca8d0308a2')
     def test_instance_usage_audit_logs_with_nonadmin_user(self):
         # the instance_usage_audit_logs API just can be accessed by admin user
         self.assertRaises(lib_exc.Forbidden,
@@ -43,7 +44,7 @@
                           urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8')
+    @decorators.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8')
     def test_get_instance_usage_audit_logs_with_invalid_time(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.adm_client.show_instance_usage_audit_log,
diff --git a/tempest/api/compute/admin/test_keypairs_v210.py b/tempest/api/compute/admin/test_keypairs_v210.py
index dfa7c39..82d3bae 100644
--- a/tempest/api/compute/admin/test_keypairs_v210.py
+++ b/tempest/api/compute/admin/test_keypairs_v210.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute.keypairs import base
 from tempest.common.utils import data_utils
-from tempest import test
+from tempest.lib import decorators
 
 
 class KeyPairsV210TestJSON(base.BaseKeypairTest):
@@ -30,11 +30,11 @@
 
     def _create_and_check_keypairs(self, user_id):
         key_list = list()
-        for i in range(2):
+        for _ in range(2):
             k_name = data_utils.rand_name('keypair')
-            keypair = self._create_keypair(k_name,
-                                           keypair_type='ssh',
-                                           user_id=user_id)
+            keypair = self.create_keypair(k_name,
+                                          keypair_type='ssh',
+                                          user_id=user_id)
             self.assertEqual(k_name, keypair['name'],
                              "The created keypair name is not equal "
                              "to the requested name!")
@@ -45,7 +45,7 @@
             key_list.append(keypair)
         return key_list
 
-    @test.idempotent_id('3c8484af-cfb3-48f6-b8ba-d5d58bbf3eac')
+    @decorators.idempotent_id('3c8484af-cfb3-48f6-b8ba-d5d58bbf3eac')
     def test_admin_manage_keypairs_for_other_users(self):
         user_id = self.non_admin_client.user_id
         key_list = self._create_and_check_keypairs(user_id)
@@ -56,8 +56,7 @@
         self.assertEqual(user_id, keypair_detail['user_id'],
                          "The fetched keypair is not for requested user!")
         # Create a admin keypair
-        admin_k_name = data_utils.rand_name('keypair')
-        admin_keypair = self._create_keypair(admin_k_name, keypair_type='ssh')
+        admin_keypair = self.create_keypair(keypair_type='ssh')
         admin_keypair.pop('private_key', None)
         admin_keypair.pop('user_id')
 
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 72d5b18..39797f7 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -72,10 +72,9 @@
             block_migration = (CONF.compute_feature_enabled.
                                block_migration_for_live_migration and
                                not volume_backed)
-        body = self.admin_servers_client.live_migrate_server(
+        self.admin_servers_client.live_migrate_server(
             server_id, host=dest_host, block_migration=block_migration,
             **kwargs)
-        return body
 
     def _get_host_other_than(self, host):
         for target_host in self._get_compute_hostnames():
@@ -118,23 +117,23 @@
         self.assertEqual(target_host, self._get_host_for_server(server_id),
                          msg)
 
-    @test.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
+    @decorators.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
     def test_live_block_migration(self):
         self._test_live_migration()
 
-    @test.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
+    @decorators.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     def test_live_block_migration_paused(self):
         self._test_live_migration(state='PAUSED')
 
     @decorators.skip_because(bug="1524898")
-    @test.idempotent_id('5071cf17-3004-4257-ae61-73a84e28badd')
+    @decorators.idempotent_id('5071cf17-3004-4257-ae61-73a84e28badd')
     @test.services('volume')
     def test_volume_backed_live_migration(self):
         self._test_live_migration(volume_backed=True)
 
-    @test.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
+    @decorators.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
     @testtools.skipIf(not CONF.compute_feature_enabled.
                       block_migration_for_live_migration,
                       'Block Live migration not available')
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index c9ba730..21f5c68 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -18,8 +18,8 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -31,15 +31,14 @@
         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')
+    @decorators.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
     def test_list_migrations(self):
         # Admin can get the migrations list
         self.client.list_migrations()
 
-    @test.idempotent_id('1b512062-8093-438e-b47a-37d2f597cd64')
+    @decorators.idempotent_id('1b512062-8093-438e-b47a-37d2f597cd64')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_list_migrations_in_flavor_resize_situation(self):
@@ -61,7 +60,7 @@
         except exceptions.NotFound:
             pass
 
-    @test.idempotent_id('33f1fec3-ba18-4470-8e4e-1d888e7c3593')
+    @decorators.idempotent_id('33f1fec3-ba18-4470-8e4e-1d888e7c3593')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_revert_deleted_flavor(self):
@@ -128,13 +127,13 @@
             server['id'])['server']['OS-EXT-SRV-ATTR:host']
         assert_func(src_host, dst_host)
 
-    @test.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
+    @decorators.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration not available.')
     def test_cold_migration(self):
         self._test_cold_migrate_server(revert=False)
 
-    @test.idempotent_id('caa1aa8b-f4ef-4374-be0d-95f001c2ac2d')
+    @decorators.idempotent_id('caa1aa8b-f4ef-4374-be0d-95f001c2ac2d')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration not available.')
     def test_revert_cold_migration(self):
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index 8504840..12ae864 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -32,7 +32,7 @@
         super(NetworksTest, cls).setup_clients()
         cls.client = cls.os_adm.compute_networks_client
 
-    @test.idempotent_id('d206d211-8912-486f-86e2-a9d090d1f416')
+    @decorators.idempotent_id('d206d211-8912-486f-86e2-a9d090d1f416')
     def test_get_network(self):
         networks = self.client.list_networks()['networks']
         if CONF.compute.fixed_network_name:
@@ -53,7 +53,7 @@
                    ['network'])
         self.assertEqual(configured_network['label'], network['label'])
 
-    @test.idempotent_id('df3d1046-6fa5-4b2c-ad0c-cfa46a351cb9')
+    @decorators.idempotent_id('df3d1046-6fa5-4b2c-ad0c-cfa46a351cb9')
     def test_list_all_networks(self):
         networks = self.client.list_networks()['networks']
         # Check the configured network is in the list
@@ -61,5 +61,5 @@
             configured_network = CONF.compute.fixed_network_name
             self.assertIn(configured_network, [x['label'] for x in networks])
         else:
-            network_name = map(lambda x: x['label'], networks)
-            self.assertGreaterEqual(len(network_name), 1)
+            network_labels = [x['label'] for x in networks]
+            self.assertGreaterEqual(len(network_labels), 1)
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index ce0adb4..3e9dc79 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -14,13 +14,12 @@
 #    under the License.
 
 from oslo_log import log as logging
-import six
 from testtools import matchers
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
 from tempest.common.utils import data_utils
-from tempest import test
+from tempest.lib import decorators
 
 LOG = logging.getLogger(__name__)
 
@@ -54,7 +53,7 @@
                                      'instances', 'security_group_rules',
                                      'cores', 'security_groups'))
 
-    @test.idempotent_id('3b0a7c8f-cf58-46b8-a60c-715a32a8ba7d')
+    @decorators.idempotent_id('3b0a7c8f-cf58-46b8-a60c-715a32a8ba7d')
     def test_get_default_quotas(self):
         # Admin can get the default resource quota set for a tenant
         expected_quota_set = self.default_quota_set | set(['id'])
@@ -64,7 +63,7 @@
         for quota in expected_quota_set:
             self.assertIn(quota, quota_set.keys())
 
-    @test.idempotent_id('55fbe2bf-21a9-435b-bbd2-4162b0ed799a')
+    @decorators.idempotent_id('55fbe2bf-21a9-435b-bbd2-4162b0ed799a')
     def test_update_all_quota_resources_for_tenant(self):
         # Admin can update all the resource quota limits for a tenant
         default_quota_set = self.adm_client.show_default_quota_set(
@@ -89,7 +88,7 @@
             self.assertIn(quota, quota_set.keys())
 
     # TODO(afazekas): merge these test cases
-    @test.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
+    @decorators.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
     def test_get_updated_quotas(self):
         # Verify that GET shows the updated quota set of project
         project_name = data_utils.rand_name('cpu_quota_project')
@@ -121,7 +120,7 @@
             project_id, user_id=user_id)['quota_set']
         self.assertEqual(2048, quota_set['ram'])
 
-    @test.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
+    @decorators.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
     def test_delete_quota(self):
         # Admin can delete the resource quota set for a project
         project_name = data_utils.rand_name('ram_quota_project')
@@ -165,7 +164,7 @@
     # global state, and possibly needs to be part of a set of
     # tests that get run all by themselves at the end under a
     # 'danger' flag.
-    @test.idempotent_id('7932ab0f-5136-4075-b201-c0e2338df51a')
+    @decorators.idempotent_id('7932ab0f-5136-4075-b201-c0e2338df51a')
     def test_update_default_quotas(self):
         LOG.debug("get the current 'default' quota class values")
         body = (self.adm_client.show_quota_class_set('default')
@@ -175,7 +174,7 @@
         # restore the defaults when the test is done
         self.addCleanup(self._restore_default_quotas, body.copy())
         # increment all of the values for updating the default quota class
-        for quota, default in six.iteritems(body):
+        for quota, default in body.items():
             # NOTE(sdague): we need to increment a lot, otherwise
             # there is a real chance that we go from -1 (unlimited)
             # to a very small number which causes issues.
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 015e14d..0850205 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -52,7 +52,7 @@
                         **{quota_item: default_quota_value})
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
+    @decorators.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
     def test_update_quota_normal_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.client.update_quota_set,
@@ -62,7 +62,7 @@
     # TODO(afazekas): Add dedicated tenant to the skipped quota tests.
     # It can be moved into the setUpClass as well.
     @test.attr(type=['negative'])
-    @test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
+    @decorators.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
         self._update_quota('cores', 0)
@@ -70,7 +70,7 @@
                           self.create_test_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6fdd7012-584d-4327-a61c-49122e0d5864')
+    @decorators.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
         self._update_quota('ram', 0)
@@ -78,7 +78,7 @@
                           self.create_test_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7c6be468-0274-449a-81c3-ac1c32ee0161')
+    @decorators.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
         self._update_quota('instances', 0)
@@ -87,7 +87,7 @@
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
-    @test.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
+    @decorators.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
     @test.services('network')
     def test_security_groups_exceed_limit(self):
         # Negative test: Creation Security Groups over limit should FAIL
@@ -106,7 +106,7 @@
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
     @test.attr(type=['negative'])
-    @test.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
+    @decorators.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
     @test.services('network')
     def test_security_groups_rules_exceed_limit(self):
         # Negative test: Creation of Security Group Rules should FAIL
diff --git a/tempest/api/compute/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
index ce350b6..ab97bd4 100644
--- a/tempest/api/compute/admin/test_security_group_default_rules.py
+++ b/tempest/api/compute/admin/test_security_group_default_rules.py
@@ -16,8 +16,8 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -55,7 +55,7 @@
         self.assertEqual(cidr, rule['ip_range']['cidr'])
         return rule
 
-    @test.idempotent_id('6d880615-eec3-4d29-97c5-7a074dde239d')
+    @decorators.idempotent_id('6d880615-eec3-4d29-97c5-7a074dde239d')
     def test_create_delete_security_group_default_rules(self):
         # Create and delete Security Group default rule
         ip_protocols = ['tcp', 'udp', 'icmp']
@@ -67,7 +67,7 @@
                               self.adm_client.show_security_group_default_rule,
                               rule['id'])
 
-    @test.idempotent_id('4d752e0a-33a1-4c3a-b498-ff8667ca22e5')
+    @decorators.idempotent_id('4d752e0a-33a1-4c3a-b498-ff8667ca22e5')
     def test_create_security_group_default_rule_without_cidr(self):
         ip_protocol = 'udp'
         from_port = 80
@@ -81,7 +81,7 @@
         self.assertNotEqual(0, rule['id'])
         self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
 
-    @test.idempotent_id('29f2d218-69b0-4a95-8f3d-6bd0ef732b3a')
+    @decorators.idempotent_id('29f2d218-69b0-4a95-8f3d-6bd0ef732b3a')
     def test_create_security_group_default_rule_with_blank_cidr(self):
         ip_protocol = 'icmp'
         from_port = 10
@@ -97,7 +97,7 @@
         self.assertNotEqual(0, rule['id'])
         self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
 
-    @test.idempotent_id('6e6de55e-9146-4ae0-89f2-3569586e0b9b')
+    @decorators.idempotent_id('6e6de55e-9146-4ae0-89f2-3569586e0b9b')
     def test_security_group_default_rules_list(self):
         ip_protocol = 'tcp'
         from_port = 22
@@ -114,7 +114,7 @@
         self.assertNotEqual(0, len(rules))
         self.assertIn(rule, rules)
 
-    @test.idempotent_id('15cbb349-86b4-4f71-a048-04b7ef3f150b')
+    @decorators.idempotent_id('15cbb349-86b4-4f71-a048-04b7ef3f150b')
     def test_default_security_group_default_rule_show(self):
         ip_protocol = 'tcp'
         from_port = 22
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index e329869..2efe755 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -32,14 +33,14 @@
         else:
             self.client.delete_security_group(securitygroup_id)
 
-    @test.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
+    @decorators.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
     @test.services('network')
     def test_list_security_groups_list_all_tenants_filter(self):
         # Admin can list security groups of all tenants
         # List of all security groups created
         security_group_list = []
         # Create two security groups for a non-admin tenant
-        for i in range(2):
+        for _ in range(2):
             name = data_utils.rand_name('securitygroup')
             description = data_utils.rand_name('description')
             securitygroup = self.client.create_security_group(
@@ -50,7 +51,7 @@
 
         client_tenant_id = securitygroup['tenant_id']
         # Create two security groups for admin tenant
-        for i in range(2):
+        for _ in range(2):
             name = data_utils.rand_name('securitygroup')
             description = data_utils.rand_name('description')
             adm_securitygroup = self.adm_client.create_security_group(
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index efa55d5..85c7fba 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -18,7 +18,6 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest.lib import decorators
-from tempest import test
 
 
 class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -29,7 +28,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):
@@ -45,7 +43,7 @@
                                         wait_until='ACTIVE')
         cls.s2_id = server['id']
 
-    @test.idempotent_id('06f960bb-15bb-48dc-873d-f96e89be7870')
+    @decorators.idempotent_id('06f960bb-15bb-48dc-873d-f96e89be7870')
     def test_list_servers_filter_by_error_status(self):
         # Filter the list of servers by server error status
         params = {'status': 'error'}
@@ -61,14 +59,14 @@
         self.assertIn(self.s1_id, map(lambda x: x['id'], servers))
         self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('d56e9540-73ed-45e0-9b88-98fc419087eb')
+    @decorators.idempotent_id('d56e9540-73ed-45e0-9b88-98fc419087eb')
     def test_list_servers_detailed_filter_by_invalid_status(self):
         params = {'status': 'invalid_status'}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
+    @decorators.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
     def test_list_servers_by_admin(self):
         # Listing servers by admin user returns a list which doesn't
         # contain the other tenants' server by default
@@ -81,7 +79,7 @@
         self.assertNotIn(self.s1_name, servers_name)
         self.assertNotIn(self.s2_name, servers_name)
 
-    @test.idempotent_id('9f5579ae-19b4-4985-a091-2a5d56106580')
+    @decorators.idempotent_id('9f5579ae-19b4-4985-a091-2a5d56106580')
     def test_list_servers_by_admin_with_all_tenants(self):
         # Listing servers by admin user with all tenants parameter
         # Here should be listed all servers
@@ -93,7 +91,7 @@
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
 
-    @test.idempotent_id('7e5d6b8f-454a-4ba1-8ae2-da857af8338b')
+    @decorators.idempotent_id('7e5d6b8f-454a-4ba1-8ae2-da857af8338b')
     def test_list_servers_by_admin_with_specified_tenant(self):
         # In nova v2, tenant_id is ignored unless all_tenants is specified
 
@@ -102,7 +100,7 @@
         params = {'tenant_id': tenant_id}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        servers_name = map(lambda x: x['name'], servers)
+        servers_name = [x['name'] for x in servers]
         self.assertNotIn(self.s1_name, servers_name)
         self.assertNotIn(self.s2_name, servers_name)
 
@@ -110,7 +108,7 @@
         params = {'all_tenants': '', 'tenant_id': tenant_id}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        servers_name = map(lambda x: x['name'], servers)
+        servers_name = [x['name'] for x in servers]
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
 
@@ -119,11 +117,11 @@
         params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
         body = self.client.list_servers(detail=True, **params)
         servers = body['servers']
-        servers_name = map(lambda x: x['name'], servers)
+        servers_name = [x['name'] for x in servers]
         self.assertNotIn(self.s1_name, servers_name)
         self.assertNotIn(self.s2_name, servers_name)
 
-    @test.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
+    @decorators.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
     def test_list_servers_filter_by_exist_host(self):
         # Filter the list of servers by existent host
         name = data_utils.rand_name(self.__class__.__name__ + '-server')
@@ -148,7 +146,7 @@
         self.assertNotIn(test_server['id'],
                          map(lambda x: x['id'], nonexistent_servers))
 
-    @test.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
+    @decorators.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
     def test_reset_state_server(self):
         # Reset server's state to 'error'
         self.client.reset_state(self.s1_id, state='error')
@@ -165,7 +163,7 @@
         self.assertEqual(server['status'], 'ACTIVE')
 
     @decorators.skip_because(bug="1240043")
-    @test.idempotent_id('31ff3486-b8a0-4f56-a6c0-aab460531db3')
+    @decorators.idempotent_id('31ff3486-b8a0-4f56-a6c0-aab460531db3')
     def test_get_server_diagnostics_by_admin(self):
         # Retrieve server diagnostics by admin user
         diagnostic = self.client.show_server_diagnostics(self.s1_id)
@@ -175,7 +173,7 @@
         for key in basic_attrs:
             self.assertIn(key, str(diagnostic.keys()))
 
-    @test.idempotent_id('682cb127-e5bb-4f53-87ce-cb9003604442')
+    @decorators.idempotent_id('682cb127-e5bb-4f53-87ce-cb9003604442')
     def test_rebuild_server_in_error_state(self):
         # The server in error state should be rebuilt using the provided
         # image and changed to ACTIVE state
@@ -203,7 +201,7 @@
         rebuilt_image_id = server['image']['id']
         self.assertEqual(self.image_ref_alt, rebuilt_image_id)
 
-    @test.idempotent_id('7a1323b4-a6a2-497a-96cb-76c07b945c71')
+    @decorators.idempotent_id('7a1323b4-a6a2-497a-96cb-76c07b945c71')
     def test_reset_network_inject_network_info(self):
         # Reset Network of a Server
         server = self.create_test_server(wait_until='ACTIVE')
@@ -211,7 +209,7 @@
         # Inject the Network Info into Server
         self.client.inject_network_info(server['id'])
 
-    @test.idempotent_id('fdcd9b33-0903-4e00-a1f7-b5f6543068d6')
+    @decorators.idempotent_id('fdcd9b33-0903-4e00-a1f7-b5f6543068d6')
     def test_create_server_with_scheduling_hint(self):
         # Create a server with scheduler hints.
         hints = {
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 23b16e7..1283629 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -19,6 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -56,7 +57,7 @@
             flavor_id = data_utils.rand_int_id(start=1000)
         return flavor_id
 
-    @test.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
+    @decorators.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type=['negative'])
@@ -72,8 +73,8 @@
             raise self.skipException("ram quota set is -1,"
                                      " cannot test overlimit")
         ram += 1
-        vcpus = 8
-        disk = 10
+        vcpus = 1
+        disk = 5
         flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
                                                        ram=ram, vcpus=vcpus,
                                                        disk=disk,
@@ -84,7 +85,7 @@
                           self.servers[0]['id'],
                           flavor_ref['id'])
 
-    @test.idempotent_id('7368a427-2f26-4ad9-9ba9-911a0ec2b0db')
+    @decorators.idempotent_id('7368a427-2f26-4ad9-9ba9-911a0ec2b0db')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type=['negative'])
@@ -93,7 +94,6 @@
         self.useFixture(fixtures.LockFixture('compute_quotas'))
         flavor_name = data_utils.rand_name("flavor")
         flavor_id = self._get_unused_flavor_id()
-        ram = 512
         quota_set = self.quotas_client.show_quota_set(
             self.tenant_id)['quota_set']
         vcpus = int(quota_set['cores'])
@@ -101,7 +101,8 @@
             raise self.skipException("cores quota set is -1,"
                                      " cannot test overlimit")
         vcpus += 1
-        disk = 10
+        ram = 512
+        disk = 5
         flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
                                                        ram=ram, vcpus=vcpus,
                                                        disk=disk,
@@ -113,27 +114,27 @@
                           flavor_ref['id'])
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('b0b4d8af-1256-41ef-9ee7-25f1c19dde80')
+    @decorators.idempotent_id('b0b4d8af-1256-41ef-9ee7-25f1c19dde80')
     def test_reset_state_server_invalid_state(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.client.reset_state, self.s1_id,
                           state='invalid')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('4cdcc984-fab0-4577-9a9d-6d558527ee9d')
+    @decorators.idempotent_id('4cdcc984-fab0-4577-9a9d-6d558527ee9d')
     def test_reset_state_server_invalid_type(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.client.reset_state, self.s1_id,
                           state=1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e741298b-8df2-46f0-81cb-8f814ff2504c')
+    @decorators.idempotent_id('e741298b-8df2-46f0-81cb-8f814ff2504c')
     def test_reset_state_server_nonexistent_server(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.reset_state, '999', state='error')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e84e2234-60d2-42fa-8b30-e2d3049724ac')
+    @decorators.idempotent_id('e84e2234-60d2-42fa-8b30-e2d3049724ac')
     def test_get_server_diagnostics_by_non_admin(self):
         # Non-admin user can not view server diagnostics according to policy
         self.assertRaises(lib_exc.Forbidden,
@@ -141,14 +142,14 @@
                           self.s1_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('46a4e1ca-87ae-4d28-987a-1b6b136a0221')
+    @decorators.idempotent_id('46a4e1ca-87ae-4d28-987a-1b6b136a0221')
     def test_migrate_non_existent_server(self):
         # migrate a non existent server
         self.assertRaises(lib_exc.NotFound,
                           self.client.migrate_server,
                           data_utils.rand_uuid())
 
-    @test.idempotent_id('b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629')
+    @decorators.idempotent_id('b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 1bbde98..6b92273 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -16,6 +16,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -35,7 +36,7 @@
         return self.os_adm.servers_client.show_server(
             server_id)['server']['OS-EXT-SRV-ATTR:host']
 
-    @test.idempotent_id('26a9d5df-6890-45f2-abc4-a659290cb130')
+    @decorators.idempotent_id('26a9d5df-6890-45f2-abc4-a659290cb130')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("SameHostFilter"),
         'SameHostFilter is not available.')
@@ -49,7 +50,7 @@
         host02 = self._get_host(server02)
         self.assertEqual(host01, host02)
 
-    @test.idempotent_id('cc7ca884-6e3e-42a3-a92f-c522fcf25e8e')
+    @decorators.idempotent_id('cc7ca884-6e3e-42a3-a92f-c522fcf25e8e')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("DifferentHostFilter"),
         'DifferentHostFilter is not available.')
@@ -63,7 +64,7 @@
         host02 = self._get_host(server02)
         self.assertNotEqual(host01, host02)
 
-    @test.idempotent_id('7869cc84-d661-4e14-9f00-c18cdc89cf57')
+    @decorators.idempotent_id('7869cc84-d661-4e14-9f00-c18cdc89cf57')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("DifferentHostFilter"),
         'DifferentHostFilter is not available.')
diff --git a/tempest/api/compute/admin/test_services.py b/tempest/api/compute/admin/test_services.py
index 8648b9f..c1c1c82 100644
--- a/tempest/api/compute/admin/test_services.py
+++ b/tempest/api/compute/admin/test_services.py
@@ -15,7 +15,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class ServicesAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -26,12 +26,12 @@
         super(ServicesAdminTestJSON, cls).setup_clients()
         cls.client = cls.os_adm.services_client
 
-    @test.idempotent_id('5be41ef4-53d1-41cc-8839-5c2a48a1b283')
+    @decorators.idempotent_id('5be41ef4-53d1-41cc-8839-5c2a48a1b283')
     def test_list_services(self):
         services = self.client.list_services()['services']
         self.assertNotEqual(0, len(services))
 
-    @test.idempotent_id('f345b1ec-bc6e-4c38-a527-3ca2bc00bef5')
+    @decorators.idempotent_id('f345b1ec-bc6e-4c38-a527-3ca2bc00bef5')
     def test_get_service_by_service_binary_name(self):
         binary_name = 'nova-compute'
         services = self.client.list_services(binary=binary_name)['services']
@@ -39,7 +39,7 @@
         for service in services:
             self.assertEqual(binary_name, service['binary'])
 
-    @test.idempotent_id('affb42d5-5b4b-43c8-8b0b-6dca054abcca')
+    @decorators.idempotent_id('affb42d5-5b4b-43c8-8b0b-6dca054abcca')
     def test_get_service_by_host_name(self):
         services = self.client.list_services()['services']
         host_name = services[0]['host']
@@ -57,7 +57,7 @@
         # on order.
         self.assertEqual(sorted(s1), sorted(s2))
 
-    @test.idempotent_id('39397f6f-37b8-4234-8671-281e44c74025')
+    @decorators.idempotent_id('39397f6f-37b8-4234-8671-281e44c74025')
     def test_get_service_by_service_and_host_name(self):
         services = self.client.list_services()['services']
         host_name = services[0]['host']
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index 710cac4..9447a09 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -27,13 +28,13 @@
         cls.non_admin_client = cls.services_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1126d1f8-266e-485f-a687-adc547492646')
+    @decorators.idempotent_id('1126d1f8-266e-485f-a687-adc547492646')
     def test_list_services_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.list_services)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('d0884a69-f693-4e79-a9af-232d15643bf7')
+    @decorators.idempotent_id('d0884a69-f693-4e79-a9af-232d15643bf7')
     def test_get_service_by_invalid_params(self):
         # return all services if send the request with invalid parameter
         services = self.client.list_services()['services']
@@ -42,7 +43,7 @@
         self.assertEqual(len(services), len(services_xxx))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1e966d4a-226e-47c7-b601-0b18a27add54')
+    @decorators.idempotent_id('1e966d4a-226e-47c7-b601-0b18a27add54')
     def test_get_service_by_invalid_service_and_valid_host(self):
         services = self.client.list_services()['services']
         host_name = services[0]['host']
@@ -51,7 +52,7 @@
         self.assertEqual(0, len(services))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('64e7e7fb-69e8-4cb6-a71d-8d5eb0c98655')
+    @decorators.idempotent_id('64e7e7fb-69e8-4cb6-a71d-8d5eb0c98655')
     def test_get_service_with_valid_service_and_invalid_host(self):
         services = self.client.list_services()['services']
         binary_name = services[0]['binary']
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index dbc22e0..ef55584 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -17,8 +17,8 @@
 
 from tempest.api.compute import base
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as e
-from tempest import test
 
 # Time that waits for until returning valid response
 # TODO(takmatsu): Ideally this value would come from configuration.
@@ -65,7 +65,7 @@
                              func.__name__, duration))
         return self.resp
 
-    @test.idempotent_id('062c8ae9-9912-4249-8b51-e38d664e926e')
+    @decorators.idempotent_id('062c8ae9-9912-4249-8b51-e38d664e926e')
     def test_list_usage_all_tenants(self):
         # Get usage for all tenants
         tenant_usage = self.call_until_valid(
@@ -73,7 +73,7 @@
             start=self.start, end=self.end, detailed="1")['tenant_usages'][0]
         self.assertEqual(len(tenant_usage), 8)
 
-    @test.idempotent_id('94135049-a4c5-4934-ad39-08fa7da4f22e')
+    @decorators.idempotent_id('94135049-a4c5-4934-ad39-08fa7da4f22e')
     def test_get_usage_tenant(self):
         # Get usage for a specific tenant
         tenant_usage = self.call_until_valid(
@@ -82,7 +82,7 @@
 
         self.assertEqual(len(tenant_usage), 8)
 
-    @test.idempotent_id('9d00a412-b40e-4fd9-8eba-97b496316116')
+    @decorators.idempotent_id('9d00a412-b40e-4fd9-8eba-97b496316116')
     def test_get_usage_tenant_with_non_admin_user(self):
         # Get usage for a specific tenant with non admin user
         tenant_usage = self.call_until_valid(
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
index 315116e..35762d6 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -16,6 +16,7 @@
 import datetime
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -41,7 +42,7 @@
         return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('8b21e135-d94b-4991-b6e9-87059609c8ed')
+    @decorators.idempotent_id('8b21e135-d94b-4991-b6e9-87059609c8ed')
     def test_get_usage_tenant_with_empty_tenant_id(self):
         # Get usage for a specific tenant empty
         params = {'start': self.start,
@@ -51,7 +52,7 @@
                           '', **params)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('4079dd2a-9e8d-479f-869d-6fa985ce45b6')
+    @decorators.idempotent_id('4079dd2a-9e8d-479f-869d-6fa985ce45b6')
     def test_get_usage_tenant_with_invalid_date(self):
         # Get usage for tenant with invalid date
         params = {'start': self.end,
@@ -61,7 +62,7 @@
                           self.client.tenant_id, **params)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('bbe6fe2c-15d8-404c-a0a2-44fad0ad5cc7')
+    @decorators.idempotent_id('bbe6fe2c-15d8-404c-a0a2-44fad0ad5cc7')
     def test_list_usage_all_tenants_with_non_admin_user(self):
         # Get usage for all tenants with non admin user
         params = {'start': self.start,
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index f603abd..5f2444a 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -13,6 +13,7 @@
 from tempest.api.compute import base
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -43,7 +44,7 @@
         # We need the admin client for performing the update (swap) volume call
         cls.servers_admin_client = cls.os_adm.servers_client
 
-    @test.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
+    @decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
     @test.services('volume')
     def test_volume_swap(self):
         # Create two volumes.
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index b9dac6f..1f85c18 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -15,6 +15,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -40,7 +41,7 @@
         super(VolumesAdminNegativeTest, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.idempotent_id('309b5ecd-0585-4a7e-a36f-d2b2bf55259d')
+    @decorators.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()
@@ -49,7 +50,8 @@
                           self.server['id'], nonexistent_volume,
                           volumeId=volume['id'])
 
-    @test.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
+    @test.related_bug('1629110', status_code=400)
+    @decorators.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)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index d7e01f0..d77ea90 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -139,15 +139,15 @@
                 test_utils.call_and_ignore_notfound_exc(
                     cls.servers_client.delete_server, server['id'])
             except Exception:
-                LOG.exception('Deleting server %s failed' % server['id'])
+                LOG.exception('Deleting server %s failed', server['id'])
 
         for server in cls.servers:
             try:
                 waiters.wait_for_server_termination(cls.servers_client,
                                                     server['id'])
             except Exception:
-                LOG.exception('Waiting for deletion of server %s failed'
-                              % server['id'])
+                LOG.exception('Waiting for deletion of server %s failed',
+                              server['id'])
 
     @classmethod
     def server_check_teardown(cls):
@@ -179,7 +179,7 @@
                 test_utils.call_and_ignore_notfound_exc(
                     cls.compute_images_client.delete_image, image_id)
             except Exception:
-                LOG.exception('Exception raised deleting image %s' % image_id)
+                LOG.exception('Exception raised deleting image %s', image_id)
 
     @classmethod
     def clear_security_groups(cls):
@@ -283,7 +283,7 @@
             volumes_client.wait_for_resource_deletion(volume_id)
         except lib_exc.NotFound:
             LOG.warning("Unable to delete volume '%s' since it was not found. "
-                        "Maybe it was already deleted?" % volume_id)
+                        "Maybe it was already deleted?", volume_id)
 
     @classmethod
     def prepare_instance_network(cls):
@@ -336,7 +336,7 @@
             waiters.wait_for_server_termination(cls.servers_client,
                                                 server_id)
         except Exception:
-            LOG.exception('Failed to delete server %s' % server_id)
+            LOG.exception('Failed to delete server %s', server_id)
 
     @classmethod
     def resize_server(cls, server_id, new_flavor_id, **kwargs):
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index d5c7302..a39fec9 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -28,14 +28,14 @@
         if not CONF.compute_feature_enabled.nova_cert:
             raise cls.skipException("Nova cert is not available")
 
-    @test.idempotent_id('c070a441-b08e-447e-a733-905909535b1b')
+    @decorators.idempotent_id('c070a441-b08e-447e-a733-905909535b1b')
     def test_create_root_certificate(self):
         # create certificates
         body = self.certificates_client.create_certificate()['certificate']
         self.assertIn('data', body)
         self.assertIn('private_key', body)
 
-    @test.idempotent_id('3ac273d0-92d2-4632-bdfc-afbc21d4606c')
+    @decorators.idempotent_id('3ac273d0-92d2-4632-bdfc-afbc21d4606c')
     def test_get_root_certificate(self):
         # get the root certificate
         body = (self.certificates_client.show_certificate('root')
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index 7e01296..546667f 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -27,7 +28,7 @@
         cls.client = cls.flavors_client
 
     @test.attr(type='smoke')
-    @test.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
+    @decorators.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
     def test_list_flavors(self):
         # List of all flavors should contain the expected flavor
         flavors = self.client.list_flavors()['flavors']
@@ -36,7 +37,7 @@
                              'name': flavor['name']}
         self.assertIn(flavor_min_detail, flavors)
 
-    @test.idempotent_id('6e85fde4-b3cd-4137-ab72-ed5f418e8c24')
+    @decorators.idempotent_id('6e85fde4-b3cd-4137-ab72-ed5f418e8c24')
     def test_list_flavors_with_detail(self):
         # Detailed list of all flavors should contain the expected flavor
         flavors = self.client.list_flavors(detail=True)['flavors']
@@ -44,27 +45,27 @@
         self.assertIn(flavor, flavors)
 
     @test.attr(type='smoke')
-    @test.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
+    @decorators.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
     def test_get_flavor(self):
         # The expected flavor details should be returned
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
         self.assertEqual(self.flavor_ref, flavor['id'])
 
-    @test.idempotent_id('8d7691b3-6ed4-411a-abc9-2839a765adab')
+    @decorators.idempotent_id('8d7691b3-6ed4-411a-abc9-2839a765adab')
     def test_list_flavors_limit_results(self):
         # Only the expected number of flavors should be returned
         params = {'limit': 1}
         flavors = self.client.list_flavors(**params)['flavors']
         self.assertEqual(1, len(flavors))
 
-    @test.idempotent_id('b26f6327-2886-467a-82be-cef7a27709cb')
+    @decorators.idempotent_id('b26f6327-2886-467a-82be-cef7a27709cb')
     def test_list_flavors_detailed_limit_results(self):
         # Only the expected number of flavors (detailed) should be returned
         params = {'limit': 1}
         flavors = self.client.list_flavors(detail=True, **params)['flavors']
         self.assertEqual(1, len(flavors))
 
-    @test.idempotent_id('e800f879-9828-4bd0-8eae-4f17189951fb')
+    @decorators.idempotent_id('e800f879-9828-4bd0-8eae-4f17189951fb')
     def test_list_flavors_using_marker(self):
         # The list of flavors should start from the provided marker
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
@@ -75,7 +76,7 @@
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
                          'The list of flavors did not start after the marker.')
 
-    @test.idempotent_id('6db2f0c0-ddee-4162-9c84-0703d3dd1107')
+    @decorators.idempotent_id('6db2f0c0-ddee-4162-9c84-0703d3dd1107')
     def test_list_flavors_detailed_using_marker(self):
         # The list of flavors should start from the provided marker
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
@@ -86,7 +87,7 @@
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
                          'The list of flavors did not start after the marker.')
 
-    @test.idempotent_id('3df2743e-3034-4e57-a4cb-b6527f6eac79')
+    @decorators.idempotent_id('3df2743e-3034-4e57-a4cb-b6527f6eac79')
     def test_list_flavors_detailed_filter_by_min_disk(self):
         # The detailed list of flavors should be filtered by disk space
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
@@ -96,7 +97,7 @@
         flavors = self.client.list_flavors(detail=True, **params)['flavors']
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @test.idempotent_id('09fe7509-b4ee-4b34-bf8b-39532dc47292')
+    @decorators.idempotent_id('09fe7509-b4ee-4b34-bf8b-39532dc47292')
     def test_list_flavors_detailed_filter_by_min_ram(self):
         # The detailed list of flavors should be filtered by RAM
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
@@ -106,7 +107,7 @@
         flavors = self.client.list_flavors(detail=True, **params)['flavors']
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @test.idempotent_id('10645a4d-96f5-443f-831b-730711e11dd4')
+    @decorators.idempotent_id('10645a4d-96f5-443f-831b-730711e11dd4')
     def test_list_flavors_filter_by_min_disk(self):
         # The list of flavors should be filtered by disk space
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
@@ -116,7 +117,7 @@
         flavors = self.client.list_flavors(**params)['flavors']
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @test.idempotent_id('935cf550-e7c8-4da6-8002-00f92d5edfaa')
+    @decorators.idempotent_id('935cf550-e7c8-4da6-8002-00f92d5edfaa')
     def test_list_flavors_filter_by_min_ram(self):
         # The list of flavors should be filtered by RAM
         flavor = self.client.show_flavor(self.flavor_ref)['flavor']
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 dcb2d2c..4d8416f 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -16,6 +16,7 @@
 from tempest.api.compute.floating_ips import base
 from tempest import config
 from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -52,7 +53,7 @@
             cls.client.delete_floating_ip(cls.floating_ip_id)
         super(FloatingIPsTestJSON, cls).resource_cleanup()
 
-    @test.idempotent_id('f7bfb946-297e-41b8-9e8c-aba8e9bb5194')
+    @decorators.idempotent_id('f7bfb946-297e-41b8-9e8c-aba8e9bb5194')
     @test.services('network')
     def test_allocate_floating_ip(self):
         # Positive test:Allocation of a new floating IP to a project
@@ -68,7 +69,7 @@
         body = self.client.list_floating_ips()['floating_ips']
         self.assertIn(floating_ip_details, body)
 
-    @test.idempotent_id('de45e989-b5ca-4a9b-916b-04a52e7bbb8b')
+    @decorators.idempotent_id('de45e989-b5ca-4a9b-916b-04a52e7bbb8b')
     @test.services('network')
     def test_delete_floating_ip(self):
         # Positive test:Deletion of valid floating IP from project
@@ -83,7 +84,7 @@
         # Check it was really deleted.
         self.client.wait_for_resource_deletion(floating_ip_body['id'])
 
-    @test.idempotent_id('307efa27-dc6f-48a0-8cd2-162ce3ef0b52')
+    @decorators.idempotent_id('307efa27-dc6f-48a0-8cd2-162ce3ef0b52')
     @test.services('network')
     def test_associate_disassociate_floating_ip(self):
         # Positive test:Associate and disassociate the provided floating IP
@@ -104,7 +105,7 @@
             self.floating_ip,
             self.server_id)
 
-    @test.idempotent_id('6edef4b2-aaf1-4abc-bbe3-993e2561e0fe')
+    @decorators.idempotent_id('6edef4b2-aaf1-4abc-bbe3-993e2561e0fe')
     @test.services('network')
     def test_associate_already_associated_floating_ip(self):
         # positive test:Association of an already associated floating IP
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 31cf39c..5e47d18 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
@@ -16,6 +16,7 @@
 from tempest.api.compute.floating_ips import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -48,7 +49,7 @@
                 break
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
+    @decorators.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
     @test.services('network')
     def test_allocate_floating_ip_from_nonexistent_pool(self):
         # Negative test:Allocation of a new floating IP from a nonexistent_pool
@@ -58,7 +59,7 @@
                           pool="non_exist_pool")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
+    @decorators.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
     @test.services('network')
     def test_delete_nonexistent_floating_ip(self):
         # Negative test:Deletion of a nonexistent floating IP
@@ -69,7 +70,7 @@
                           self.non_exist_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
+    @decorators.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
     @test.services('network')
     def test_associate_nonexistent_floating_ip(self):
         # Negative test:Association of a non existent floating IP
@@ -80,7 +81,7 @@
                           "0.0.0.0", self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
+    @decorators.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
     @test.services('network')
     def test_dissociate_nonexistent_floating_ip(self):
         # Negative test:Dissociation of a non existent floating IP should fail
@@ -90,7 +91,7 @@
                           "0.0.0.0", self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
+    @decorators.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
     @test.services('network')
     def test_associate_ip_to_server_without_passing_floating_ip(self):
         # Negative test:Association of empty floating IP to specific server
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 222bf18..71f5f13 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -33,7 +34,7 @@
         super(FloatingIPDetailsTestJSON, cls).resource_setup()
         cls.floating_ip = []
         cls.floating_ip_id = []
-        for i in range(3):
+        for _ in range(3):
             body = cls.client.create_floating_ip(
                 pool=CONF.network.floating_network_name)['floating_ip']
             cls.floating_ip.append(body)
@@ -45,7 +46,7 @@
             cls.client.delete_floating_ip(f_id)
         super(FloatingIPDetailsTestJSON, cls).resource_cleanup()
 
-    @test.idempotent_id('16db31c3-fb85-40c9-bbe2-8cf7b67ff99f')
+    @decorators.idempotent_id('16db31c3-fb85-40c9-bbe2-8cf7b67ff99f')
     @test.services('network')
     def test_list_floating_ips(self):
         # Positive test:Should return the list of floating IPs
@@ -56,7 +57,7 @@
         for i in range(3):
             self.assertIn(self.floating_ip[i], floating_ips)
 
-    @test.idempotent_id('eef497e0-8ff7-43c8-85ef-558440574f84')
+    @decorators.idempotent_id('eef497e0-8ff7-43c8-85ef-558440574f84')
     @test.services('network')
     def test_get_floating_ip_details(self):
         # Positive test:Should be able to GET the details of floatingIP
@@ -78,7 +79,7 @@
                          body['fixed_ip'])
         self.assertEqual(floating_ip_id, body['id'])
 
-    @test.idempotent_id('df389fc8-56f5-43cc-b290-20eda39854d3')
+    @decorators.idempotent_id('df389fc8-56f5-43cc-b290-20eda39854d3')
     @test.services('network')
     def test_list_floating_ip_pools(self):
         # Positive test:Should return the list of floating IP Pools
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index ea56ae9..00a4075 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -16,6 +16,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -30,7 +31,7 @@
         cls.client = cls.floating_ips_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
+    @decorators.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
     @test.services('network')
     def test_get_nonexistent_floating_ip_details(self):
         # Negative test:Should not be able to GET the details
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 26d4efe..f131007 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -20,8 +20,8 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -83,7 +83,7 @@
         meta = {'os_version': 'value1', 'os_distro': 'value2'}
         self.client.set_image_metadata(self.image_id, meta)
 
-    @test.idempotent_id('37ec6edd-cf30-4c53-bd45-ae74db6b0531')
+    @decorators.idempotent_id('37ec6edd-cf30-4c53-bd45-ae74db6b0531')
     def test_list_image_metadata(self):
         # All metadata key/value pairs for an image should be returned
         resp_metadata = self.client.list_image_metadata(self.image_id)
@@ -91,7 +91,7 @@
             'os_version': 'value1', 'os_distro': 'value2'}}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('ece7befc-d3ce-42a4-b4be-c3067a418c29')
+    @decorators.idempotent_id('ece7befc-d3ce-42a4-b4be-c3067a418c29')
     def test_set_image_metadata(self):
         # The metadata for the image should match the new values
         req_metadata = {'os_version': 'value2', 'architecture': 'value3'}
@@ -102,7 +102,7 @@
                          ['metadata'])
         self.assertEqual(req_metadata, resp_metadata)
 
-    @test.idempotent_id('7b491c11-a9d5-40fe-a696-7f7e03d3fea2')
+    @decorators.idempotent_id('7b491c11-a9d5-40fe-a696-7f7e03d3fea2')
     def test_update_image_metadata(self):
         # The metadata for the image should match the updated values
         req_metadata = {'os_version': 'alt1', 'architecture': 'value3'}
@@ -116,14 +116,14 @@
             'architecture': 'value3'}}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('4f5db52f-6685-4c75-b848-f4bb363f9aa6')
+    @decorators.idempotent_id('4f5db52f-6685-4c75-b848-f4bb363f9aa6')
     def test_get_image_metadata_item(self):
         # The value for a specific metadata key should be returned
         meta = self.client.show_image_metadata_item(self.image_id,
                                                     'os_distro')['meta']
         self.assertEqual('value2', meta['os_distro'])
 
-    @test.idempotent_id('f2de776a-4778-4d90-a5da-aae63aee64ae')
+    @decorators.idempotent_id('f2de776a-4778-4d90-a5da-aae63aee64ae')
     def test_set_image_metadata_item(self):
         # The value provided for the given meta item should be set for
         # the image
@@ -134,7 +134,7 @@
         expected = {'metadata': {'os_version': 'alt', 'os_distro': 'value2'}}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('a013796c-ba37-4bb5-8602-d944511def14')
+    @decorators.idempotent_id('a013796c-ba37-4bb5-8602-d944511def14')
     def test_delete_image_metadata_item(self):
         # The metadata value/key pair should be deleted from the image
         self.client.delete_image_metadata_item(self.image_id,
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 489bfbc..0f5b9d8 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -27,7 +28,7 @@
         cls.client = cls.compute_images_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
+    @decorators.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
     def test_list_nonexistent_image_metadata(self):
         # Negative test: List on nonexistent image
         # metadata should not happen
@@ -35,7 +36,7 @@
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a403ef9e-9f95-427c-b70a-3ce3388796f1')
+    @decorators.idempotent_id('a403ef9e-9f95-427c-b70a-3ce3388796f1')
     def test_update_nonexistent_image_metadata(self):
         # Negative test:An update should not happen for a non-existent image
         meta = {'os_distro': 'alt1', 'os_version': 'alt2'}
@@ -44,7 +45,7 @@
                           data_utils.rand_uuid(), meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('41ae052c-6ee6-405c-985e-5712393a620d')
+    @decorators.idempotent_id('41ae052c-6ee6-405c-985e-5712393a620d')
     def test_get_nonexistent_image_metadata_item(self):
         # Negative test: Get on non-existent image should not happen
         self.assertRaises(lib_exc.NotFound,
@@ -52,7 +53,7 @@
                           data_utils.rand_uuid(), 'os_version')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('dc64f2ce-77e8-45b0-88c8-e15041d08eaf')
+    @decorators.idempotent_id('dc64f2ce-77e8-45b0-88c8-e15041d08eaf')
     def test_set_nonexistent_image_metadata(self):
         # Negative test: Metadata should not be set to a non-existent image
         meta = {'os_distro': 'alt1', 'os_version': 'alt2'}
@@ -60,7 +61,7 @@
                           data_utils.rand_uuid(), meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('2154fd03-ab54-457c-8874-e6e3eb56e9cf')
+    @decorators.idempotent_id('2154fd03-ab54-457c-8874-e6e3eb56e9cf')
     def test_set_nonexistent_image_metadata_item(self):
         # Negative test: Metadata item should not be set to a
         # nonexistent image
@@ -71,7 +72,7 @@
                           meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('848e157f-6bcf-4b2e-a5dd-5124025a8518')
+    @decorators.idempotent_id('848e157f-6bcf-4b2e-a5dd-5124025a8518')
     def test_delete_nonexistent_image_metadata_item(self):
         # Negative test: Shouldn't be able to delete metadata
         # item from non-existent image
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index a06f4a7..a0c860a 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -16,7 +16,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -39,7 +39,7 @@
         super(ImagesTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
+    @decorators.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
     def test_delete_saving_image(self):
         server = self.create_test_server(wait_until='ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
@@ -50,7 +50,7 @@
                .format(image_id=image['id']))
         self.assertTrue(self.client.is_resource_deleted(image['id']), msg)
 
-    @test.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
+    @decorators.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
     def test_create_image_from_stopped_server(self):
         server = self.create_test_server(wait_until='ACTIVE')
         self.servers_client.stop_server(server['id'])
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 549262e..10f3c70 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -16,6 +16,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -41,7 +42,7 @@
         cls.client = cls.compute_images_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
+    @decorators.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
     def test_create_image_from_deleted_server(self):
         # An image should not be created if the server instance is removed
         server = self.create_test_server(wait_until='ACTIVE')
@@ -50,24 +51,22 @@
         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
-        name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         self.assertRaises(lib_exc.NotFound,
                           self.create_image_from_server,
-                          server['id'], name=name, meta=meta)
+                          server['id'], meta=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('82c5b0c4-9dbd-463c-872b-20c4755aae7f')
+    @decorators.idempotent_id('82c5b0c4-9dbd-463c-872b-20c4755aae7f')
     def test_create_image_from_invalid_server(self):
         # An image should not be created with invalid server id
         # Create a new image with invalid server id
-        name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
         self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
-                          '!@$^&*()', name=name, meta=meta)
+                          data_utils.rand_name('invalid'), meta=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
+    @decorators.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
     def test_create_image_specify_uuid_35_characters_or_less(self):
         # Return an error if Image ID passed is 35 characters or less
         snapshot_name = data_utils.rand_name('test-snap')
@@ -76,7 +75,7 @@
                           test_uuid, name=snapshot_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('36741560-510e-4cc2-8641-55fe4dfb2437')
+    @decorators.idempotent_id('36741560-510e-4cc2-8641-55fe4dfb2437')
     def test_create_image_specify_uuid_37_characters_or_more(self):
         # Return an error if Image ID passed is 37 characters or more
         snapshot_name = data_utils.rand_name('test-snap')
@@ -85,14 +84,14 @@
                           test_uuid, name=snapshot_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('381acb65-785a-4942-94ce-d8f8c84f1f0f')
+    @decorators.idempotent_id('381acb65-785a-4942-94ce-d8f8c84f1f0f')
     def test_delete_image_with_invalid_image_id(self):
         # An image should not be deleted with invalid image id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
-                          '!@$^&*()')
+                          data_utils.rand_name('invalid'))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('137aef61-39f7-44a1-8ddf-0adf82511701')
+    @decorators.idempotent_id('137aef61-39f7-44a1-8ddf-0adf82511701')
     def test_delete_non_existent_image(self):
         # Return an error while trying to delete a non-existent image
 
@@ -101,13 +100,13 @@
                           non_existent_image_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e6e41425-af5c-4fe6-a4b5-7b7b963ffda5')
+    @decorators.idempotent_id('e6e41425-af5c-4fe6-a4b5-7b7b963ffda5')
     def test_delete_image_blank_id(self):
         # Return an error while trying to delete an image with blank Id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, '')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('924540c3-f1f1-444c-8f58-718958b6724e')
+    @decorators.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
         invalid_image_id = data_utils.rand_uuid()[:-1] + "j"
@@ -115,13 +114,13 @@
                           invalid_image_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('68e2c175-bd26-4407-ac0f-4ea9ce2139ea')
+    @decorators.idempotent_id('68e2c175-bd26-4407-ac0f-4ea9ce2139ea')
     def test_delete_image_negative_image_id(self):
         # Return an error while trying to delete an image with negative id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, -1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('b340030d-82cd-4066-a314-c72fb7c59277')
+    @decorators.idempotent_id('b340030d-82cd-4066-a314-c72fb7c59277')
     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"
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 19e2880..7fff555 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -13,17 +13,14 @@
 #    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
 from tempest import config
 from tempest.lib.common.utils import test_utils
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class ImagesOneServerTestJSON(base.BaseV2ComputeTest):
@@ -49,7 +46,7 @@
         flavor = self.flavors_client.show_flavor(flavor_id)['flavor']
         return flavor['disk']
 
-    @test.idempotent_id('3731d080-d4c5-4872-b41a-64d0d0021314')
+    @decorators.idempotent_id('3731d080-d4c5-4872-b41a-64d0d0021314')
     def test_create_delete_image(self):
         server_id = self.create_test_server(wait_until='ACTIVE')['id']
 
@@ -82,7 +79,7 @@
         self.client.delete_image(image_id)
         self.client.wait_for_resource_deletion(image_id)
 
-    @test.idempotent_id('3b7c6fe4-dfe7-477c-9243-b06359db51e6')
+    @decorators.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']
 
@@ -92,7 +89,7 @@
         # We use a string with 3 byte utf-8 character due to bug
         # #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')
+        utf8_name = data_utils.rand_name(b'\xe2\x82\xa1'.decode('utf-8'))
         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)
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 1c9b3f1..09bbfbe 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -20,6 +20,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -47,8 +48,8 @@
             waiters.wait_for_server_status(self.servers_client, self.server_id,
                                            'ACTIVE')
         except Exception:
-            LOG.exception('server %s timed out to become ACTIVE. rebuilding'
-                          % self.server_id)
+            LOG.exception('server %s timed out to become ACTIVE. rebuilding',
+                          self.server_id)
             # Rebuild server if cannot reach the ACTIVE state
             # Usually it means the server had a serious accident
             self._reset_server()
@@ -82,7 +83,7 @@
         cls.image_ids = []
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('55d1d38c-dd66-4933-9c8e-7d92aeb60ddc')
+    @decorators.idempotent_id('55d1d38c-dd66-4933-9c8e-7d92aeb60ddc')
     def test_create_image_specify_invalid_metadata(self):
         # Return an error when creating image with invalid metadata
         snapshot_name = data_utils.rand_name('test-snap')
@@ -91,7 +92,7 @@
                           self.server_id, name=snapshot_name, metadata=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('3d24d11f-5366-4536-bd28-cff32b748eca')
+    @decorators.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 255 chars
         snapshot_name = data_utils.rand_name('test-snap')
@@ -100,7 +101,7 @@
                           self.server_id, name=snapshot_name, metadata=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0460efcf-ee88-4f94-acef-1bf658695456')
+    @decorators.idempotent_id('0460efcf-ee88-4f94-acef-1bf658695456')
     def test_create_second_image_when_first_image_is_being_saved(self):
         # Disallow creating another image when first image is being saved
 
@@ -117,7 +118,7 @@
                           self.server_id, name=alt_snapshot_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
+    @decorators.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
     def test_create_image_specify_name_over_character_limit(self):
         # Return an error if snapshot name over 255 characters is passed
 
@@ -126,7 +127,7 @@
                           self.server_id, name=snapshot_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0894954d-2db2-4195-a45b-ffec0bc0187e')
+    @decorators.idempotent_id('0894954d-2db2-4195-a45b-ffec0bc0187e')
     def test_delete_image_that_is_not_yet_active(self):
         # Return an error while trying to delete an image what is creating
 
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index a9c2f7a..9c9b8a1 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -23,8 +23,8 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -122,7 +122,7 @@
             cls.server1['id'], wait_until='ACTIVE')
         cls.snapshot2_id = cls.snapshot2['id']
 
-    @test.idempotent_id('a3f5b513-aeb3-42a9-b18e-f091ef73254d')
+    @decorators.idempotent_id('a3f5b513-aeb3-42a9-b18e-f091ef73254d')
     def test_list_images_filter_by_status(self):
         # The list of images should contain only images with the
         # provided status
@@ -133,7 +133,7 @@
         self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
         self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
 
-    @test.idempotent_id('33163b73-79f5-4d07-a7ea-9213bcc468ff')
+    @decorators.idempotent_id('33163b73-79f5-4d07-a7ea-9213bcc468ff')
     def test_list_images_filter_by_name(self):
         # List of all images should contain the expected images filtered
         # by name
@@ -144,7 +144,7 @@
         self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
         self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
 
-    @test.idempotent_id('9f238683-c763-45aa-b848-232ec3ce3105')
+    @decorators.idempotent_id('9f238683-c763-45aa-b848-232ec3ce3105')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     def test_list_images_filter_by_server_id(self):
@@ -161,7 +161,7 @@
         self.assertFalse(any([i for i in images
                               if i['id'] == self.snapshot3_id]))
 
-    @test.idempotent_id('05a377b8-28cf-4734-a1e6-2ab5c38bf606')
+    @decorators.idempotent_id('05a377b8-28cf-4734-a1e6-2ab5c38bf606')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     def test_list_images_filter_by_server_ref(self):
@@ -180,7 +180,7 @@
             self.assertTrue(any([i for i in images
                                  if i['id'] == self.snapshot3_id]))
 
-    @test.idempotent_id('e3356918-4d3e-4756-81d5-abc4524ba29f')
+    @decorators.idempotent_id('e3356918-4d3e-4756-81d5-abc4524ba29f')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     def test_list_images_filter_by_type(self):
@@ -197,14 +197,14 @@
         self.assertFalse(any([i for i in images
                               if i['id'] == self.image_ref]))
 
-    @test.idempotent_id('3a484ca9-67ba-451e-b494-7fcf28d32d62')
+    @decorators.idempotent_id('3a484ca9-67ba-451e-b494-7fcf28d32d62')
     def test_list_images_limit_results(self):
         # Verify only the expected number of results are returned
         params = {'limit': '1'}
         images = self.client.list_images(**params)['images']
         self.assertEqual(1, len([x for x in images if 'id' in x]))
 
-    @test.idempotent_id('18bac3ae-da27-436c-92a9-b22474d13aab')
+    @decorators.idempotent_id('18bac3ae-da27-436c-92a9-b22474d13aab')
     def test_list_images_filter_by_changes_since(self):
         # Verify only updated images are returned in the detailed list
 
@@ -215,7 +215,7 @@
         found = any([i for i in images if i['id'] == self.image3_id])
         self.assertTrue(found)
 
-    @test.idempotent_id('9b0ea018-6185-4f71-948a-a123a107988e')
+    @decorators.idempotent_id('9b0ea018-6185-4f71-948a-a123a107988e')
     def test_list_images_with_detail_filter_by_status(self):
         # Detailed list of all images should only contain images
         # with the provided status
@@ -226,7 +226,7 @@
         self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
         self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
 
-    @test.idempotent_id('644ea267-9bd9-4f3b-af9f-dffa02396a17')
+    @decorators.idempotent_id('644ea267-9bd9-4f3b-af9f-dffa02396a17')
     def test_list_images_with_detail_filter_by_name(self):
         # Detailed list of all images should contain the expected
         # images filtered by name
@@ -237,7 +237,7 @@
         self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
         self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
 
-    @test.idempotent_id('ba2fa9a9-b672-47cc-b354-3b4c0600e2cb')
+    @decorators.idempotent_id('ba2fa9a9-b672-47cc-b354-3b4c0600e2cb')
     def test_list_images_with_detail_limit_results(self):
         # Verify only the expected number of results (with full details)
         # are returned
@@ -245,7 +245,7 @@
         images = self.client.list_images(detail=True, **params)['images']
         self.assertEqual(1, len(images))
 
-    @test.idempotent_id('8c78f822-203b-4bf6-8bba-56ebd551cf84')
+    @decorators.idempotent_id('8c78f822-203b-4bf6-8bba-56ebd551cf84')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     def test_list_images_with_detail_filter_by_server_ref(self):
@@ -264,7 +264,7 @@
             self.assertTrue(any([i for i in images
                                  if i['id'] == self.snapshot3_id]))
 
-    @test.idempotent_id('888c0cc0-7223-43c5-9db0-b125fd0a393b')
+    @decorators.idempotent_id('888c0cc0-7223-43c5-9db0-b125fd0a393b')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
     def test_list_images_with_detail_filter_by_type(self):
@@ -282,7 +282,7 @@
         self.assertFalse(any([i for i in images
                               if i['id'] == self.image_ref]))
 
-    @test.idempotent_id('7d439e18-ac2e-4827-b049-7e18004712c4')
+    @decorators.idempotent_id('7d439e18-ac2e-4827-b049-7e18004712c4')
     def test_list_images_with_detail_filter_by_changes_since(self):
         # Verify an update image is returned
 
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index 2689f88..e04a57a 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -15,6 +15,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -36,7 +37,7 @@
         cls.client = cls.compute_images_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
+    @decorators.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
     def test_get_nonexistent_image(self):
         # Check raises a NotFound
         nonexistent_image = data_utils.rand_uuid()
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index ae3667d..5d3cbf3 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -34,20 +34,20 @@
         super(ListImagesTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
+    @decorators.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
     def test_get_image(self):
         # Returns the correct details for a single image
         image = self.client.show_image(self.image_ref)['image']
         self.assertEqual(self.image_ref, image['id'])
 
-    @test.idempotent_id('fd51b7f4-d4a3-4331-9885-866658112a6f')
+    @decorators.idempotent_id('fd51b7f4-d4a3-4331-9885-866658112a6f')
     def test_list_images(self):
         # The list of all images should contain the image
         images = self.client.list_images()['images']
         found = any([i for i in images if i['id'] == self.image_ref])
         self.assertTrue(found)
 
-    @test.idempotent_id('9f94cb6b-7f10-48c5-b911-a0b84d7d4cd6')
+    @decorators.idempotent_id('9f94cb6b-7f10-48c5-b911-a0b84d7d4cd6')
     def test_list_images_with_detail(self):
         # Detailed list of all images should contain the expected images
         images = self.client.list_images(detail=True)['images']
diff --git a/tempest/api/compute/keypairs/base.py b/tempest/api/compute/keypairs/base.py
index ad7f958..21f504b 100644
--- a/tempest/api/compute/keypairs/base.py
+++ b/tempest/api/compute/keypairs/base.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.common.utils import data_utils
 
 
 class BaseKeypairTest(base.BaseV2ComputeTest):
@@ -27,9 +28,12 @@
     def _delete_keypair(self, keypair_name, **params):
         self.client.delete_keypair(keypair_name, **params)
 
-    def _create_keypair(self, keypair_name,
-                        pub_key=None, keypair_type=None,
-                        user_id=None):
+    def create_keypair(self, keypair_name=None,
+                       pub_key=None, keypair_type=None,
+                       user_id=None):
+        if keypair_name is None:
+            keypair_name = data_utils.rand_name(
+                self.__class__.__name__ + '-keypair')
         kwargs = {'name': keypair_name}
         delete_params = {}
         if pub_key:
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index 562a508..11e84e8 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -15,20 +15,19 @@
 
 from tempest.api.compute.keypairs import base
 from tempest.common.utils import data_utils
-from tempest import test
+from tempest.lib import decorators
 
 
 class KeyPairsV2TestJSON(base.BaseKeypairTest):
     max_microversion = '2.1'
 
-    @test.idempotent_id('1d1dbedb-d7a0-432a-9d09-83f543c3c19b')
+    @decorators.idempotent_id('1d1dbedb-d7a0-432a-9d09-83f543c3c19b')
     def test_keypairs_create_list_delete(self):
         # Keypairs created should be available in the response list
         # Create 3 keypairs
         key_list = list()
-        for i in range(3):
-            k_name = data_utils.rand_name('keypair')
-            keypair = self._create_keypair(k_name)
+        for _ in range(3):
+            keypair = self.create_keypair()
             # Need to pop these keys so that our compare doesn't fail later,
             # as the keypair dicts from list API doesn't have them.
             keypair.pop('private_key')
@@ -47,11 +46,11 @@
                          "Failed to find keypairs %s in fetched list"
                          % ', '.join(m_key['name'] for m_key in missing_kps))
 
-    @test.idempotent_id('6c1d3123-4519-4742-9194-622cb1714b7d')
+    @decorators.idempotent_id('6c1d3123-4519-4742-9194-622cb1714b7d')
     def test_keypair_create_delete(self):
         # Keypair should be created, verified and deleted
         k_name = data_utils.rand_name('keypair')
-        keypair = self._create_keypair(k_name)
+        keypair = self.create_keypair(k_name)
         private_key = keypair['private_key']
         key_name = keypair['name']
         self.assertEqual(key_name, k_name,
@@ -60,11 +59,11 @@
         self.assertIsNotNone(private_key,
                              "Field private_key is empty or not found.")
 
-    @test.idempotent_id('a4233d5d-52d8-47cc-9a25-e1864527e3df')
+    @decorators.idempotent_id('a4233d5d-52d8-47cc-9a25-e1864527e3df')
     def test_get_keypair_detail(self):
         # Keypair should be created, Got details by name and deleted
         k_name = data_utils.rand_name('keypair')
-        self._create_keypair(k_name)
+        self.create_keypair(k_name)
         keypair_detail = self.client.show_keypair(k_name)['keypair']
         self.assertIn('name', keypair_detail)
         self.assertIn('public_key', keypair_detail)
@@ -75,7 +74,7 @@
         self.assertIsNotNone(public_key,
                              "Field public_key is empty or not found.")
 
-    @test.idempotent_id('39c90c6a-304a-49dd-95ec-2366129def05')
+    @decorators.idempotent_id('39c90c6a-304a-49dd-95ec-2366129def05')
     def test_keypair_create_with_pub_key(self):
         # Keypair should be created with a given public key
         k_name = data_utils.rand_name('keypair')
@@ -88,7 +87,7 @@
                    "LOeB1kYMOBaiUPLQTWXR3JpckqFIQwhIH0zoHlJvZE8hh90"
                    "XcPojYN56tI0OlrGqojbediJYD0rUsJu4weZpbn8vilb3JuDY+jws"
                    "snSA8wzBx3A/8y9Pp1B nova@ubuntu")
-        keypair = self._create_keypair(k_name, pub_key)
+        keypair = self.create_keypair(k_name, pub_key)
         self.assertNotIn('private_key', keypair,
                          "Field private_key is not empty!")
         key_name = keypair['name']
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 2a6139b..863ce0d 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -16,22 +16,22 @@
 
 from tempest.api.compute.keypairs import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 
 class KeyPairsNegativeTestJSON(base.BaseKeypairTest):
     @test.attr(type=['negative'])
-    @test.idempotent_id('29cca892-46ae-4d48-bc32-8fe7e731eb81')
+    @decorators.idempotent_id('29cca892-46ae-4d48-bc32-8fe7e731eb81')
     def test_keypair_create_with_invalid_pub_key(self):
         # Keypair should not be created with a non RSA public key
-        k_name = data_utils.rand_name('keypair')
         pub_key = "ssh-rsa JUNK nova@ubuntu"
         self.assertRaises(lib_exc.BadRequest,
-                          self._create_keypair, k_name, pub_key)
+                          self.create_keypair, pub_key=pub_key)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7cc32e47-4c42-489d-9623-c5e2cb5a2fa5')
+    @decorators.idempotent_id('7cc32e47-4c42-489d-9623-c5e2cb5a2fa5')
     def test_keypair_delete_nonexistent_key(self):
         # Non-existent key deletion should throw a proper error
         k_name = data_utils.rand_name("keypair-non-existent")
@@ -39,53 +39,51 @@
                           k_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('dade320e-69ca-42a9-ba4a-345300f127e0')
+    @decorators.idempotent_id('dade320e-69ca-42a9-ba4a-345300f127e0')
     def test_create_keypair_with_empty_public_key(self):
         # Keypair should not be created with an empty public key
-        k_name = data_utils.rand_name("keypair")
         pub_key = ' '
-        self.assertRaises(lib_exc.BadRequest, self._create_keypair,
-                          k_name, pub_key)
+        self.assertRaises(lib_exc.BadRequest, self.create_keypair,
+                          pub_key=pub_key)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fc100c19-2926-4b9c-8fdc-d0589ee2f9ff')
+    @decorators.idempotent_id('fc100c19-2926-4b9c-8fdc-d0589ee2f9ff')
     def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
         # Keypair should not be created when public key bits are too long
-        k_name = data_utils.rand_name("keypair")
         pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
-        self.assertRaises(lib_exc.BadRequest, self._create_keypair,
-                          k_name, pub_key)
+        self.assertRaises(lib_exc.BadRequest, self.create_keypair,
+                          pub_key=pub_key)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0359a7f1-f002-4682-8073-0c91e4011b7c')
+    @decorators.idempotent_id('0359a7f1-f002-4682-8073-0c91e4011b7c')
     def test_create_keypair_with_duplicate_name(self):
         # Keypairs with duplicate names should not be created
         k_name = data_utils.rand_name('keypair')
         self.client.create_keypair(name=k_name)
         # Now try the same keyname to create another key
-        self.assertRaises(lib_exc.Conflict, self._create_keypair,
+        self.assertRaises(lib_exc.Conflict, self.create_keypair,
                           k_name)
         self.client.delete_keypair(k_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1398abe1-4a84-45fb-9294-89f514daff00')
+    @decorators.idempotent_id('1398abe1-4a84-45fb-9294-89f514daff00')
     def test_create_keypair_with_empty_name_string(self):
         # Keypairs with name being an empty string should not be created
-        self.assertRaises(lib_exc.BadRequest, self._create_keypair,
+        self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           '')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('3faa916f-779f-4103-aca7-dc3538eee1b7')
+    @decorators.idempotent_id('3faa916f-779f-4103-aca7-dc3538eee1b7')
     def test_create_keypair_with_long_keynames(self):
         # Keypairs with name longer than 255 chars should not be created
         k_name = 'keypair-'.ljust(260, '0')
-        self.assertRaises(lib_exc.BadRequest, self._create_keypair,
+        self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           k_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('45fbe5e0-acb5-49aa-837a-ff8d0719db91')
+    @decorators.idempotent_id('45fbe5e0-acb5-49aa-837a-ff8d0719db91')
     def test_create_keypair_invalid_name(self):
         # Keypairs with name being an invalid name should not be created
         k_name = 'key_/.\@:'
-        self.assertRaises(lib_exc.BadRequest, self._create_keypair,
+        self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           k_name)
diff --git a/tempest/api/compute/keypairs/test_keypairs_v22.py b/tempest/api/compute/keypairs/test_keypairs_v22.py
index 997ef9b..c893a4f 100644
--- a/tempest/api/compute/keypairs/test_keypairs_v22.py
+++ b/tempest/api/compute/keypairs/test_keypairs_v22.py
@@ -14,7 +14,7 @@
 
 from tempest.api.compute.keypairs import test_keypairs
 from tempest.common.utils import data_utils
-from tempest import test
+from tempest.lib import decorators
 
 
 class KeyPairsV22TestJSON(test_keypairs.KeyPairsV2TestJSON):
@@ -28,7 +28,7 @@
 
     def _test_keypairs_create_list_show(self, keypair_type=None):
         k_name = data_utils.rand_name('keypair')
-        keypair = self._create_keypair(k_name, keypair_type=keypair_type)
+        keypair = self.create_keypair(k_name, keypair_type=keypair_type)
         # Verify whether 'type' is present in keypair create response of
         # version 2.2 and it is with default value 'ssh'.
         self._check_keypair_type(keypair, keypair_type)
@@ -41,11 +41,11 @@
             if keypair['keypair']['name'] == k_name:
                 self._check_keypair_type(keypair['keypair'], keypair_type)
 
-    @test.idempotent_id('8726fa85-7f98-4b20-af9e-f710a4f3391c')
+    @decorators.idempotent_id('8726fa85-7f98-4b20-af9e-f710a4f3391c')
     def test_keypairsv22_create_list_show(self):
         self._test_keypairs_create_list_show()
 
-    @test.idempotent_id('89d59d43-f735-441a-abcf-0601727f47b6')
+    @decorators.idempotent_id('89d59d43-f735-441a-abcf-0601727f47b6')
     def test_keypairsv22_create_list_show_with_type(self):
         keypair_type = 'x509'
         self._test_keypairs_create_list_show(keypair_type=keypair_type)
diff --git a/tempest/api/compute/limits/test_absolute_limits.py b/tempest/api/compute/limits/test_absolute_limits.py
index 6cc722c..58352bd 100644
--- a/tempest/api/compute/limits/test_absolute_limits.py
+++ b/tempest/api/compute/limits/test_absolute_limits.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class AbsoluteLimitsTestJSON(base.BaseV2ComputeTest):
@@ -24,7 +24,7 @@
         super(AbsoluteLimitsTestJSON, cls).setup_clients()
         cls.client = cls.limits_client
 
-    @test.idempotent_id('b54c66af-6ab6-4cf0-a9e5-a0cb58d75e0b')
+    @decorators.idempotent_id('b54c66af-6ab6-4cf0-a9e5-a0cb58d75e0b')
     def test_absLimits_get(self):
         # To check if all limits are present in the response
         limits = self.client.show_limits()['limits']
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index 66bc241..b9ae0c6 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -32,7 +33,7 @@
         cls.client = cls.limits_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('215cd465-d8ae-49c9-bf33-9c911913a5c8')
+    @decorators.idempotent_id('215cd465-d8ae-49c9-bf33-9c911913a5c8')
     def test_max_image_meta_exceed_limit(self):
         # We should not create vm with image meta over maxImageMeta limit
         # Get max limit value
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index f70f6d3..cb18775 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -14,6 +14,11 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
 
 
 class BaseSecurityGroupsTest(base.BaseV2ComputeTest):
@@ -23,3 +28,11 @@
         # A network and a subnet will be created for these tests
         cls.set_network_resources(network=True, subnet=True)
         super(BaseSecurityGroupsTest, cls).setup_credentials()
+
+    @staticmethod
+    def generate_random_security_group_id():
+        if (CONF.service_available.neutron and
+            test.is_extension_enabled('security-group', 'network')):
+            return data_utils.rand_uuid()
+        else:
+            return data_utils.rand_int_id(start=999)
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 38c294b..7658848 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute.security_groups import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -43,7 +44,6 @@
         group = {}
         ip_range = {}
         cls.expected = {
-            'id': None,
             'parent_group_id': None,
             'ip_protocol': cls.ip_protocol,
             'from_port': from_port,
@@ -54,13 +54,11 @@
 
     def _check_expected_response(self, actual_rule):
         for key in self.expected:
-            if key == 'id':
-                continue
             self.assertEqual(self.expected[key], actual_rule[key],
                              "Miss-matched key is %s" % key)
 
     @test.attr(type='smoke')
-    @test.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
+    @decorators.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
     @test.services('network')
     def test_security_group_rules_create(self):
         # Positive test: Creation of Security Group rule
@@ -78,7 +76,7 @@
         self.expected['ip_range'] = {'cidr': '0.0.0.0/0'}
         self._check_expected_response(rule)
 
-    @test.idempotent_id('7a01873e-3c38-4f30-80be-31a043cfe2fd')
+    @decorators.idempotent_id('7a01873e-3c38-4f30-80be-31a043cfe2fd')
     @test.services('network')
     def test_security_group_rules_create_with_optional_cidr(self):
         # Positive test: Creation of Security Group rule
@@ -101,7 +99,7 @@
         self.expected['ip_range'] = {'cidr': cidr}
         self._check_expected_response(rule)
 
-    @test.idempotent_id('7f5d2899-7705-4d4b-8458-4505188ffab6')
+    @decorators.idempotent_id('7f5d2899-7705-4d4b-8458-4505188ffab6')
     @test.services('network')
     def test_security_group_rules_create_with_optional_group_id(self):
         # Positive test: Creation of Security Group rule
@@ -130,7 +128,7 @@
         self._check_expected_response(rule)
 
     @test.attr(type='smoke')
-    @test.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
+    @decorators.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
     @test.services('network')
     def test_security_group_rules_list(self):
         # Positive test: Created Security Group rules should be
@@ -168,7 +166,7 @@
         self.assertTrue(any([i for i in rules if i['id'] == rule1_id]))
         self.assertTrue(any([i for i in rules if i['id'] == rule2_id]))
 
-    @test.idempotent_id('fc5c5acf-2091-43a6-a6ae-e42760e9ffaf')
+    @decorators.idempotent_id('fc5c5acf-2091-43a6-a6ae-e42760e9ffaf')
     @test.services('network')
     def test_security_group_rules_delete_when_peer_group_deleted(self):
         # Positive test:rule will delete when peer group deleting
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 32b3ea3..0312736 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
@@ -15,20 +15,10 @@
 
 from tempest.api.compute.security_groups import base
 from tempest.common.utils import data_utils
-from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
-CONF = config.CONF
-
-
-def not_existing_id():
-    if (CONF.service_available.neutron and
-        test.is_extension_enabled('security-group', 'network')):
-        return data_utils.rand_uuid()
-    else:
-        return data_utils.rand_int_id(start=999)
-
 
 class SecurityGroupRulesNegativeTestJSON(base.BaseSecurityGroupsTest):
 
@@ -38,13 +28,13 @@
         cls.rules_client = cls.security_group_rules_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
+    @decorators.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
     @test.services('network')
     def test_create_security_group_rule_with_non_existent_id(self):
         # Negative test: Creation of Security Group rule should FAIL
         # with non existent Parent group id
         # Adding rules to the non existent Security Group id
-        parent_group_id = not_existing_id()
+        parent_group_id = self.generate_random_security_group_id()
         ip_protocol = 'tcp'
         from_port = 22
         to_port = 22
@@ -55,7 +45,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
+    @decorators.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_id(self):
         # Negative test: Creation of Security Group rule should FAIL
@@ -72,7 +62,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
+    @decorators.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
     @test.services('network')
     def test_create_security_group_rule_duplicate(self):
         # Negative test: Create Security Group rule duplicate should fail
@@ -97,7 +87,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
+    @decorators.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_ip_protocol(self):
         # Negative test: Creation of Security Group rule should FAIL
@@ -117,7 +107,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
+    @decorators.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_from_port(self):
         # Negative test: Creation of Security Group rule should FAIL
@@ -136,7 +126,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
+    @decorators.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_to_port(self):
         # Negative test: Creation of Security Group rule should FAIL
@@ -155,7 +145,7 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
+    @decorators.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_port_range(self):
         # Negative test: Creation of Security Group rule should FAIL
@@ -174,12 +164,12 @@
                           to_port=to_port)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
+    @decorators.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
     @test.services('network')
     def test_delete_security_group_rule_with_non_existent_id(self):
         # Negative test: Deletion of Security Group rule should be FAIL
         # with non existent id
-        non_existent_rule_id = not_existing_id()
+        non_existent_rule_id = self.generate_random_security_group_id()
         self.assertRaises(lib_exc.NotFound,
                           self.rules_client.delete_security_group_rule,
                           non_existent_rule_id)
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 4184afa..e070336 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -16,6 +16,7 @@
 from tempest.api.compute.security_groups import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -28,13 +29,13 @@
         cls.client = cls.security_groups_client
 
     @test.attr(type='smoke')
-    @test.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
+    @decorators.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
     @test.services('network')
     def test_security_groups_create_list_delete(self):
         # Positive test:Should return the list of Security Groups
         # Create 3 Security Groups
         security_group_list = []
-        for i in range(3):
+        for _ in range(3):
             body = self.create_security_group()
             security_group_list.append(body)
         # Fetch all Security Groups and verify the list
@@ -60,7 +61,7 @@
                          "list" % ', '.join(m_group['name']
                                             for m_group in deleted_sgs))
 
-    @test.idempotent_id('ecc0da4a-2117-48af-91af-993cca39a615')
+    @decorators.idempotent_id('ecc0da4a-2117-48af-91af-993cca39a615')
     @test.services('network')
     def test_security_group_create_get_delete(self):
         # Security Group should be created, fetched and deleted
@@ -82,7 +83,7 @@
         self.client.delete_security_group(securitygroup['id'])
         self.client.wait_for_resource_deletion(securitygroup['id'])
 
-    @test.idempotent_id('fe4abc0d-83f5-4c50-ad11-57a1127297a2')
+    @decorators.idempotent_id('fe4abc0d-83f5-4c50-ad11-57a1127297a2')
     @test.services('network')
     def test_server_security_groups(self):
         # Checks that security groups may be added and linked to a server
@@ -124,7 +125,7 @@
         self.client.delete_security_group(sg['id'])
         self.client.delete_security_group(sg2['id'])
 
-    @test.idempotent_id('7d4e1d3c-3209-4d6d-b020-986304ebad1f')
+    @decorators.idempotent_id('7d4e1d3c-3209-4d6d-b020-986304ebad1f')
     @test.services('network')
     def test_update_security_groups(self):
         # Update security group name and description
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index e6abf28..ad18861 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -37,36 +37,20 @@
         super(SecurityGroupsNegativeTestJSON, cls).resource_setup()
         cls.neutron_available = CONF.service_available.neutron
 
-    def _generate_a_non_existent_security_group_id(self):
-        security_group_id = []
-        body = self.client.list_security_groups()['security_groups']
-        for i in range(len(body)):
-            security_group_id.append(body[i]['id'])
-        # Generate a non-existent security group id
-        while True:
-            if (self.neutron_available and
-                test.is_extension_enabled('security-group', 'network')):
-                non_exist_id = data_utils.rand_uuid()
-            else:
-                non_exist_id = data_utils.rand_int_id(start=999)
-            if non_exist_id not in security_group_id:
-                break
-        return non_exist_id
-
     @test.attr(type=['negative'])
-    @test.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
+    @decorators.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
     @test.services('network')
     def test_security_group_get_nonexistent_group(self):
         # Negative test:Should not be able to GET the details
         # of non-existent Security Group
-        non_exist_id = self._generate_a_non_existent_security_group_id()
+        non_exist_id = self.generate_random_security_group_id()
         self.assertRaises(lib_exc.NotFound, self.client.show_security_group,
                           non_exist_id)
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
     @test.attr(type=['negative'])
-    @test.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
+    @decorators.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
     @test.services('network')
     def test_security_group_create_with_invalid_group_name(self):
         # Negative test: Security Group should not be created with group name
@@ -89,7 +73,7 @@
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
     @test.attr(type=['negative'])
-    @test.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
+    @decorators.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
         # Negative test: Security Group should not be created with description
@@ -102,7 +86,7 @@
                           self.client.create_security_group,
                           name=s_name, description=s_description)
 
-    @test.idempotent_id('9fdb4abc-6b66-4b27-b89c-eb215a956168')
+    @decorators.idempotent_id('9fdb4abc-6b66-4b27-b89c-eb215a956168')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron allows duplicate names for security groups")
     @test.attr(type=['negative'])
@@ -119,7 +103,7 @@
                           name=s_name, description=s_description)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
+    @decorators.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
     @test.services('network')
     def test_delete_the_default_security_group(self):
         # Negative test:Deletion of the "default" Security Group should Fail
@@ -135,16 +119,16 @@
                           default_security_group_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
+    @decorators.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
     @test.services('network')
     def test_delete_nonexistent_security_group(self):
         # Negative test:Deletion of a non-existent Security Group should fail
-        non_exist_id = self._generate_a_non_existent_security_group_id()
+        non_exist_id = self.generate_random_security_group_id()
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_security_group, non_exist_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
+    @decorators.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
     @test.services('network')
     def test_delete_security_group_without_passing_id(self):
         # Negative test:Deletion of a Security Group with out passing ID
@@ -152,7 +136,7 @@
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_security_group, '')
 
-    @test.idempotent_id('00579617-fe04-4e1c-9d08-ca7467d2e34b')
+    @decorators.idempotent_id('00579617-fe04-4e1c-9d08-ca7467d2e34b')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group ID")
     @test.attr(type=['negative'])
@@ -167,7 +151,7 @@
                           self.client.update_security_group, sg_id_invalid,
                           name=s_name, description=s_description)
 
-    @test.idempotent_id('cda8d8b4-59f8-4087-821d-20cf5a03b3b1')
+    @decorators.idempotent_id('cda8d8b4-59f8-4087-821d-20cf5a03b3b1')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group name")
     @test.attr(type=['negative'])
@@ -183,7 +167,7 @@
                           self.client.update_security_group,
                           securitygroup_id, name=s_new_name)
 
-    @test.idempotent_id('97d12b1c-a610-4194-93f1-ba859e718b45')
+    @decorators.idempotent_id('97d12b1c-a610-4194-93f1-ba859e718b45')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group description")
     @test.attr(type=['negative'])
@@ -200,11 +184,11 @@
                           securitygroup_id, description=s_new_des)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
+    @decorators.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
     @test.services('network')
     def test_update_non_existent_security_group(self):
         # Update a non-existent Security Group should Fail
-        non_exist_id = self._generate_a_non_existent_security_group_id()
+        non_exist_id = self.generate_random_security_group_id()
         s_name = data_utils.rand_name('sg')
         s_description = data_utils.rand_name('description')
         self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index a21ce94..9bba733 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -184,7 +184,7 @@
 
         self.assertEqual(sorted(list1), sorted(list2))
 
-    @test.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
+    @decorators.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
     @test.services('network')
     def test_create_list_show_delete_interfaces(self):
         server, ifs = self._create_server_get_interfaces()
@@ -221,7 +221,7 @@
         self.assertEqual(len(ifs) - 1, len(_ifs))
 
     @test.attr(type='smoke')
-    @test.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
+    @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
     @test.services('network')
     def test_add_remove_fixed_ip(self):
         # Add and Remove the fixed IP to server.
@@ -246,7 +246,7 @@
         self.servers_client.remove_fixed_ip(server['id'], address=fixed_ip)
 
     @decorators.skip_because(bug='1607714')
-    @test.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
+    @decorators.idempotent_id('2f3a0127-95c7-4977-92d2-bc5aec602fb4')
     def test_reassign_port_between_servers(self):
         """Tests the following:
 
@@ -268,9 +268,7 @@
             self.os, tenant_network=network, wait_until='ACTIVE', min_count=2)
         # add our cleanups for the servers since we bypassed the base class
         for server in servers:
-            self.addCleanup(waiters.wait_for_server_termination,
-                            self.servers_client, server['id'])
-            self.addCleanup(self.servers_client.delete_server, server['id'])
+            self.addCleanup(self.delete_server, server['id'])
 
         for server in servers:
             # attach the port to the server
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 00df86b..82e74ed 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class AZV2TestJSON(base.BaseV2ComputeTest):
@@ -25,7 +25,7 @@
         super(AZV2TestJSON, cls).setup_clients()
         cls.client = cls.availability_zone_client
 
-    @test.idempotent_id('a8333aa2-205c-449f-a828-d38c2489bf25')
+    @decorators.idempotent_id('a8333aa2-205c-449f-a828-d38c2489bf25')
     def test_get_availability_zone_list_with_non_admin_user(self):
         # List of availability zone with non-administrator user
         availability_zone = self.client.list_availability_zones()
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 82ebcd0..5ddae5e 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -20,6 +20,7 @@
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -77,7 +78,7 @@
         return net
 
     @test.attr(type='smoke')
-    @test.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
+    @decorators.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
     def test_verify_server_details(self):
         # Verify the specified server attributes are set correctly
         self.assertEqual(self.accessIPv4, self.server['accessIPv4'])
@@ -91,7 +92,7 @@
         self.assertEqual(self.meta, self.server['metadata'])
 
     @test.attr(type='smoke')
-    @test.idempotent_id('9a438d88-10c6-4bcd-8b5b-5b6e25e1346f')
+    @decorators.idempotent_id('9a438d88-10c6-4bcd-8b5b-5b6e25e1346f')
     def test_list_servers(self):
         # The created server should be in the list of all servers
         body = self.client.list_servers()
@@ -99,7 +100,7 @@
         found = any([i for i in servers if i['id'] == self.server['id']])
         self.assertTrue(found)
 
-    @test.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
+    @decorators.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
     def test_list_servers_with_detail(self):
         # The created server should be in the detailed list of all servers
         body = self.client.list_servers(detail=True)
@@ -107,7 +108,7 @@
         found = any([i for i in servers if i['id'] == self.server['id']])
         self.assertTrue(found)
 
-    @test.idempotent_id('cbc0f52f-05aa-492b-bdc1-84b575ca294b')
+    @decorators.idempotent_id('cbc0f52f-05aa-492b-bdc1-84b575ca294b')
     @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_vcpus(self):
@@ -123,7 +124,7 @@
             servers_client=self.client)
         self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
 
-    @test.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
+    @decorators.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
     @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_host_name_is_same_as_server_name(self):
@@ -140,7 +141,7 @@
                'hostname "%s" but got "%s".' % (self.name, hostname))
         self.assertEqual(self.name.lower(), hostname, msg)
 
-    @test.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
+    @decorators.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
     @testtools.skipUnless(
         test.is_scheduler_filter_enabled("ServerGroupAffinityFilter"),
         'ServerGroupAffinityFilter is not available.')
@@ -156,7 +157,7 @@
                         ['server_group'])
         self.assertIn(server['id'], server_group['members'])
 
-    @test.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
+    @decorators.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
     @testtools.skipUnless(CONF.service_available.neutron,
                           'Neutron service must be available.')
     def test_verify_multiple_nics_order(self):
@@ -194,7 +195,7 @@
         for address, network in zip(addr, networks):
             self.assertIn(address, network)
 
-    @test.idempotent_id('1678d144-ed74-43f8-8e57-ab10dbf9b3c2')
+    @decorators.idempotent_id('1678d144-ed74-43f8-8e57-ab10dbf9b3c2')
     @testtools.skipUnless(CONF.service_available.neutron,
                           'Neutron service must be available.')
     def test_verify_duplicate_network_nics(self):
@@ -244,7 +245,7 @@
 
         super(ServersWithSpecificFlavorTestJSON, cls).resource_setup()
 
-    @test.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
+    @decorators.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
     @testtools.skipUnless(CONF.validation.run_validation,
                           'Instance validation tests are disabled.')
     def test_verify_created_server_ephemeral_disk(self):
@@ -253,24 +254,18 @@
             self.flavor_ref)['flavor']
 
         def create_flavor_with_ephemeral(ephem_disk):
-            flavor_with_eph_disk_id = data_utils.rand_int_id(start=1000)
+            flavor_id = data_utils.rand_int_id(start=1000)
+            name = 'flavor_with_ephemeral_%s' % ephem_disk
+            flavor_name = data_utils.rand_name(name)
 
             ram = flavor_base['ram']
             vcpus = flavor_base['vcpus']
             disk = flavor_base['disk']
 
-            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']
+            # Create a flavor with ephemeral disk
+            flavor = self.flavor_client.create_flavor(
+                name=flavor_name, ram=ram, vcpus=vcpus, disk=disk,
+                id=flavor_id, ephemeral=ephem_disk)['flavor']
             self.addCleanup(flavor_clean_up, flavor['id'])
 
             return flavor['id']
@@ -300,7 +295,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'])
@@ -320,8 +315,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_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 07f46c5..83b2e1b 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -19,6 +19,7 @@
 from tempest.common import compute
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -34,21 +35,21 @@
         super(DeleteServersTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
 
-    @test.idempotent_id('9e6e0c87-3352-42f7-9faf-5d6210dbd159')
+    @decorators.idempotent_id('9e6e0c87-3352-42f7-9faf-5d6210dbd159')
     def test_delete_server_while_in_building_state(self):
         # Delete a server while it's VM state is Building
         server = self.create_test_server(wait_until='BUILD')
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('925fdfb4-5b13-47ea-ac8a-c36ae6fddb05')
+    @decorators.idempotent_id('925fdfb4-5b13-47ea-ac8a-c36ae6fddb05')
     def test_delete_active_server(self):
         # Delete a server while it's VM state is Active
         server = self.create_test_server(wait_until='ACTIVE')
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('546d368c-bb6c-4645-979a-83ed16f3a6be')
+    @decorators.idempotent_id('546d368c-bb6c-4645-979a-83ed16f3a6be')
     def test_delete_server_while_in_shutoff_state(self):
         # Delete a server while it's VM state is Shutoff
         server = self.create_test_server(wait_until='ACTIVE')
@@ -57,7 +58,7 @@
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('943bd6e8-4d7a-4904-be83-7a6cc2d4213b')
+    @decorators.idempotent_id('943bd6e8-4d7a-4904-be83-7a6cc2d4213b')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     def test_delete_server_while_in_pause_state(self):
@@ -68,7 +69,7 @@
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('1f82ebd3-8253-4f4e-b93f-de9b7df56d8b')
+    @decorators.idempotent_id('1f82ebd3-8253-4f4e-b93f-de9b7df56d8b')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     def test_delete_server_while_in_suspended_state(self):
@@ -79,7 +80,7 @@
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('bb0cb402-09dd-4947-b6e5-5e7e1cfa61ad')
+    @decorators.idempotent_id('bb0cb402-09dd-4947-b6e5-5e7e1cfa61ad')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     def test_delete_server_while_in_shelved_state(self):
@@ -90,7 +91,7 @@
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('ab0c38b4-cdd8-49d3-9b92-0cb898723c01')
+    @decorators.idempotent_id('ab0c38b4-cdd8-49d3-9b92-0cb898723c01')
     @testtools.skipIf(not CONF.compute_feature_enabled.resize,
                       'Resize not available.')
     def test_delete_server_while_in_verify_resize_state(self):
@@ -102,7 +103,7 @@
         self.client.delete_server(server['id'])
         waiters.wait_for_server_termination(self.client, server['id'])
 
-    @test.idempotent_id('d0f3f0d6-d9b6-4a32-8da4-23015dcab23c')
+    @decorators.idempotent_id('d0f3f0d6-d9b6-4a32-8da4-23015dcab23c')
     @test.services('volume')
     def test_delete_server_while_in_attached_volume(self):
         # Delete a server while a volume is attached to it
@@ -128,7 +129,7 @@
         cls.non_admin_client = cls.servers_client
         cls.admin_client = cls.os_adm.servers_client
 
-    @test.idempotent_id('99774678-e072-49d1-9d2a-49a59bc56063')
+    @decorators.idempotent_id('99774678-e072-49d1-9d2a-49a59bc56063')
     def test_delete_server_while_in_error_state(self):
         # Delete a server while it's VM state is error
         server = self.create_test_server(wait_until='ACTIVE')
@@ -141,7 +142,7 @@
                                             server['id'],
                                             ignore_error=True)
 
-    @test.idempotent_id('73177903-6737-4f27-a60c-379e8ae8cf48')
+    @decorators.idempotent_id('73177903-6737-4f27-a60c-379e8ae8cf48')
     def test_admin_delete_servers_of_others(self):
         # Administrator can delete servers of others
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index 7252e1b..ae8f47d 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -19,8 +19,8 @@
 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 decorators
 from tempest.lib import exceptions
 from tempest import test
 
@@ -52,9 +52,7 @@
         super(DeviceTaggingTest, cls).setup_clients()
         cls.networks_client = cls.os.networks_client
         cls.ports_client = cls.os.ports_client
-        cls.volumes_client = cls.os.volumes_client
         cls.subnets_client = cls.os.subnets_client
-        cls.routers_client = cls.os.routers_client
         cls.interfaces_client = cls.os.interfaces_client
 
     @classmethod
@@ -86,7 +84,7 @@
                                               'net-2-100', 'net-2-200',
                                               'boot', 'other'])
 
-    @test.idempotent_id('a2e65a6c-66f1-4442-aaa8-498c31778d96')
+    @decorators.idempotent_id('a2e65a6c-66f1-4442-aaa8-498c31778d96')
     @test.services('network', 'volume', 'image')
     def test_device_tagging(self):
         # Create volumes
@@ -198,9 +196,7 @@
                 }
             ])
 
-        self.addCleanup(waiters.wait_for_server_termination,
-                        self.servers_client, server['id'])
-        self.addCleanup(self.servers_client.delete_server, server['id'])
+        self.addCleanup(self.delete_server, server['id'])
 
         self.ssh_client = remote_client.RemoteClient(
             self.get_server_ip(server),
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index ff8ea6e..4709180 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -18,7 +18,7 @@
 from tempest.api.compute import base
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -46,7 +46,7 @@
             server = self.client.show_server(server['id'])['server']
             self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
 
-    @test.idempotent_id('bef56b09-2e8c-4883-a370-4950812f430e')
+    @decorators.idempotent_id('bef56b09-2e8c-4883-a370-4950812f430e')
     def test_rebuild_server_with_manual_disk_config(self):
         # A server should be rebuilt using the manual disk config option
         server = self.create_test_server(wait_until='ACTIVE')
@@ -65,7 +65,7 @@
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
 
-    @test.idempotent_id('9c9fae77-4feb-402f-8450-bf1c8b609713')
+    @decorators.idempotent_id('9c9fae77-4feb-402f-8450-bf1c8b609713')
     def test_rebuild_server_with_auto_disk_config(self):
         # A server should be rebuilt using the auto disk config option
         server = self.create_test_server(wait_until='ACTIVE')
@@ -84,7 +84,7 @@
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
 
-    @test.idempotent_id('414e7e93-45b5-44bc-8e03-55159c6bfc97')
+    @decorators.idempotent_id('414e7e93-45b5-44bc-8e03-55159c6bfc97')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_from_manual_to_auto(self):
@@ -100,7 +100,7 @@
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
 
-    @test.idempotent_id('693d16f3-556c-489a-8bac-3d0ca2490bad')
+    @decorators.idempotent_id('693d16f3-556c-489a-8bac-3d0ca2490bad')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_from_auto_to_manual(self):
@@ -116,7 +116,7 @@
         server = self.client.show_server(server['id'])['server']
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
 
-    @test.idempotent_id('5ef18867-358d-4de9-b3c9-94d4ba35742f')
+    @decorators.idempotent_id('5ef18867-358d-4de9-b3c9-94d4ba35742f')
     def test_update_server_from_auto_to_manual(self):
         # A server should be updated from auto to manual disk config
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index e50881f..b916a42 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common import waiters
-from tempest import test
+from tempest.lib import decorators
 
 
 class InstanceActionsTestJSON(base.BaseV2ComputeTest):
@@ -31,7 +31,7 @@
         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')
+    @decorators.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')
@@ -44,7 +44,7 @@
         self.assertEqual(sorted([i['action'] for i in body]),
                          ['create', 'reboot'])
 
-    @test.idempotent_id('aacc71ca-1d70-4aa5-bbf6-0ff71470e43c')
+    @decorators.idempotent_id('aacc71ca-1d70-4aa5-bbf6-0ff71470e43c')
     def test_get_instance_action(self):
         # Get the action details of the provided server
         body = self.client.show_instance_action(
@@ -63,7 +63,7 @@
         super(InstanceActionsV221TestJSON, cls).setup_clients()
         cls.client = cls.servers_client
 
-    @test.idempotent_id('0a0f85d4-10fa-41f6-bf80-a54fb4aa2ae1')
+    @decorators.idempotent_id('0a0f85d4-10fa-41f6-bf80-a54fb4aa2ae1')
     def test_get_list_deleted_instance_actions(self):
 
         # List actions of the deleted server
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 33fed08..85e3281 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -32,7 +33,7 @@
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('67e1fce6-7ec2-45c6-92d4-0a8f1a632910')
+    @decorators.idempotent_id('67e1fce6-7ec2-45c6-92d4-0a8f1a632910')
     def test_list_instance_actions_non_existent_server(self):
         # List actions of the non-existent server id
         non_existent_server_id = data_utils.rand_uuid()
@@ -41,7 +42,7 @@
                           non_existent_server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0269f40a-6f18-456c-b336-c03623c897f1')
+    @decorators.idempotent_id('0269f40a-6f18-456c-b336-c03623c897f1')
     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,
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 611d5a2..c0a8eae 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -19,7 +19,6 @@
 from tempest.common import waiters
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
@@ -84,7 +83,7 @@
                                         flavor=cls.flavor_ref_alt,
                                         wait_until='ACTIVE')
 
-    @test.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
+    @decorators.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
     @decorators.skip_unless_attr('multiple_images', 'Only one image found')
     def test_list_servers_filter_by_image(self):
         # Filter the list of servers by image
@@ -96,7 +95,7 @@
         self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('573637f5-7325-47bb-9144-3476d0416908')
+    @decorators.idempotent_id('573637f5-7325-47bb-9144-3476d0416908')
     def test_list_servers_filter_by_flavor(self):
         # Filter the list of servers by flavor
         params = {'flavor': self.flavor_ref_alt}
@@ -107,7 +106,7 @@
         self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('9b067a7b-7fee-4f6a-b29c-be43fe18fc5a')
+    @decorators.idempotent_id('9b067a7b-7fee-4f6a-b29c-be43fe18fc5a')
     def test_list_servers_filter_by_server_name(self):
         # Filter the list of servers by server name
         params = {'name': self.s1_name}
@@ -118,7 +117,7 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @test.idempotent_id('ca78e20e-fddb-4ce6-b7f7-bcbf8605e66e')
+    @decorators.idempotent_id('ca78e20e-fddb-4ce6-b7f7-bcbf8605e66e')
     def test_list_servers_filter_by_active_status(self):
         # Filter the list of servers by server active status
         params = {'status': 'active'}
@@ -129,7 +128,7 @@
         self.assertIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('451dbbb2-f330-4a9f-b0e1-5f5d2cb0f34c')
+    @decorators.idempotent_id('451dbbb2-f330-4a9f-b0e1-5f5d2cb0f34c')
     def test_list_servers_filter_by_shutoff_status(self):
         # Filter the list of servers by server shutoff status
         params = {'status': 'shutoff'}
@@ -146,21 +145,21 @@
         self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertNotIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('614cdfc1-d557-4bac-915b-3e67b48eee76')
+    @decorators.idempotent_id('614cdfc1-d557-4bac-915b-3e67b48eee76')
     def test_list_servers_filter_by_limit(self):
         # Verify only the expected number of servers are returned
         params = {'limit': 1}
         servers = self.client.list_servers(**params)
         self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
 
-    @test.idempotent_id('b1495414-2d93-414c-8019-849afe8d319e')
+    @decorators.idempotent_id('b1495414-2d93-414c-8019-849afe8d319e')
     def test_list_servers_filter_by_zero_limit(self):
         # Verify only the expected number of servers are returned
         params = {'limit': 0}
         servers = self.client.list_servers(**params)
         self.assertEqual(0, len(servers['servers']))
 
-    @test.idempotent_id('37791bbd-90c0-4de0-831e-5f38cba9c6b3')
+    @decorators.idempotent_id('37791bbd-90c0-4de0-831e-5f38cba9c6b3')
     def test_list_servers_filter_by_exceed_limit(self):
         # Verify only the expected number of servers are returned
         params = {'limit': 100000}
@@ -169,7 +168,7 @@
         self.assertEqual(len([x for x in all_servers['servers'] if 'id' in x]),
                          len([x for x in servers['servers'] if 'id' in x]))
 
-    @test.idempotent_id('b3304c3b-97df-46d2-8cd3-e2b6659724e7')
+    @decorators.idempotent_id('b3304c3b-97df-46d2-8cd3-e2b6659724e7')
     @decorators.skip_unless_attr('multiple_images', 'Only one image found')
     def test_list_servers_detailed_filter_by_image(self):
         # Filter the detailed list of servers by image
@@ -181,7 +180,7 @@
         self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('80c574cc-0925-44ba-8602-299028357dd9')
+    @decorators.idempotent_id('80c574cc-0925-44ba-8602-299028357dd9')
     def test_list_servers_detailed_filter_by_flavor(self):
         # Filter the detailed list of servers by flavor
         params = {'flavor': self.flavor_ref_alt}
@@ -192,7 +191,7 @@
         self.assertNotIn(self.s2['id'], map(lambda x: x['id'], servers))
         self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
 
-    @test.idempotent_id('f9eb2b70-735f-416c-b260-9914ac6181e4')
+    @decorators.idempotent_id('f9eb2b70-735f-416c-b260-9914ac6181e4')
     def test_list_servers_detailed_filter_by_server_name(self):
         # Filter the detailed list of servers by server name
         params = {'name': self.s1_name}
@@ -203,7 +202,7 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @test.idempotent_id('de2612ab-b7dd-4044-b0b1-d2539601911f')
+    @decorators.idempotent_id('de2612ab-b7dd-4044-b0b1-d2539601911f')
     def test_list_servers_detailed_filter_by_server_status(self):
         # Filter the detailed list of servers by server status
         params = {'status': 'active'}
@@ -217,7 +216,7 @@
         self.assertEqual(['ACTIVE'] * 3, [x['status'] for x in servers
                                           if x['id'] in test_ids])
 
-    @test.idempotent_id('e9f624ee-92af-4562-8bec-437945a18dcb')
+    @decorators.idempotent_id('e9f624ee-92af-4562-8bec-437945a18dcb')
     def test_list_servers_filtered_by_name_wildcard(self):
         # List all servers that contains '-instance' in name
         params = {'name': '-instance'}
@@ -239,7 +238,7 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @test.idempotent_id('24a89b0c-0d55-4a28-847f-45075f19b27b')
+    @decorators.idempotent_id('24a89b0c-0d55-4a28-847f-45075f19b27b')
     def test_list_servers_filtered_by_name_regex(self):
         # list of regex that should match s1, s2 and s3
         regexes = ['^.*\-instance\-[0-9]+$', '^.*\-instance\-.*$']
@@ -263,7 +262,7 @@
         self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
-    @test.idempotent_id('43a1242e-7b31-48d1-88f2-3f72aa9f2077')
+    @decorators.idempotent_id('43a1242e-7b31-48d1-88f2-3f72aa9f2077')
     def test_list_servers_filtered_by_ip(self):
         # Filter servers by ip
         # Here should be listed 1 server
@@ -282,7 +281,7 @@
         self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
 
     @decorators.skip_because(bug="1540645")
-    @test.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
+    @decorators.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
     def test_list_servers_filtered_by_ip_regex(self):
         # Filter servers by regex ip
         # List all servers filtered by part of ip address.
@@ -312,7 +311,7 @@
                       "%s not found in %s, all servers %s" %
                       (self.s3_name, servers, all_servers))
 
-    @test.idempotent_id('67aec2d0-35fe-4503-9f92-f13272b867ed')
+    @decorators.idempotent_id('67aec2d0-35fe-4503-9f92-f13272b867ed')
     def test_list_servers_detailed_limit_results(self):
         # Verify only the expected number of detailed results are returned
         params = {'limit': 1}
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 5a35b4e..594c5c9 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common import waiters
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -36,22 +37,17 @@
         # tearDownClass method of the super-class.
         cls.existing_fixtures = []
         cls.deleted_fixtures = []
-        for x in range(2):
+        for _ in range(2):
             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'])
-    @test.idempotent_id('24a26f1a-1ddc-4eea-b0d7-a90cc874ad8f')
+    @decorators.idempotent_id('24a26f1a-1ddc-4eea-b0d7-a90cc874ad8f')
     def test_list_servers_with_a_deleted_server(self):
         # Verify deleted servers do not show by default in list servers
         # List servers and verify server not returned
@@ -63,7 +59,7 @@
         self.assertEqual([], actual)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('ff01387d-c7ad-47b4-ae9e-64fa214638fe')
+    @decorators.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
         body = self.client.list_servers(image='non_existing_image')
@@ -71,7 +67,7 @@
         self.assertEqual([], servers)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5913660b-223b-44d4-a651-a0fbfd44ca75')
+    @decorators.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
         body = self.client.list_servers(flavor='non_existing_flavor')
@@ -79,7 +75,7 @@
         self.assertEqual([], servers)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('e2c77c4a-000a-4af3-a0bd-629a328bde7c')
+    @decorators.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
         body = self.client.list_servers(name='non_existing_server_name')
@@ -87,21 +83,21 @@
         self.assertEqual([], servers)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fcdf192d-0f74-4d89-911f-1ec002b822c4')
+    @decorators.idempotent_id('fcdf192d-0f74-4d89-911f-1ec002b822c4')
     def test_list_servers_status_non_existing(self):
         # Return an empty list when invalid status is specified
         body = self.client.list_servers(status='non_existing_status')
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.idempotent_id('12c80a9f-2dec-480e-882b-98ba15757659')
+    @decorators.idempotent_id('12c80a9f-2dec-480e-882b-98ba15757659')
     def test_list_servers_by_limits(self):
         # List servers by specifying limits
         body = self.client.list_servers(limit=1)
         self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('d47c17fb-eebd-4287-8e95-f20a7e627b18')
+    @decorators.idempotent_id('d47c17fb-eebd-4287-8e95-f20a7e627b18')
     def test_list_servers_by_limits_greater_than_actual_count(self):
         # Gather the complete list of servers in the project for reference
         full_list = self.client.list_servers()['servers']
@@ -111,21 +107,21 @@
         self.assertEqual(len(full_list), len(body['servers']))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('679bc053-5e70-4514-9800-3dfab1a380a6')
+    @decorators.idempotent_id('679bc053-5e70-4514-9800-3dfab1a380a6')
     def test_list_servers_by_limits_pass_string(self):
         # Return an error if a string value is passed for limit
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           limit='testing')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('62610dd9-4713-4ee0-8beb-fd2c1aa7f950')
+    @decorators.idempotent_id('62610dd9-4713-4ee0-8beb-fd2c1aa7f950')
     def test_list_servers_by_limits_pass_negative_value(self):
         # Return an error if a negative value for limit is passed
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           limit=-1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('87d12517-e20a-4c9c-97b6-dd1628d6d6c9')
+    @decorators.idempotent_id('87d12517-e20a-4c9c-97b6-dd1628d6d6c9')
     def test_list_servers_by_changes_since_invalid_date(self):
         # Return an error when invalid date format is passed
         params = {'changes-since': '2011/01/01'}
@@ -133,7 +129,7 @@
                           **params)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('74745ad8-b346-45b5-b9b8-509d7447fc1f')
+    @decorators.idempotent_id('74745ad8-b346-45b5-b9b8-509d7447fc1f')
     def test_list_servers_by_changes_since_future_date(self):
         # Return an empty list when a date in the future is passed
         changes_since = {'changes-since': '2051-01-01T12:34:00Z'}
@@ -141,7 +137,7 @@
         self.assertEqual(0, len(body['servers']))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('93055106-2d34-46fe-af68-d9ddbf7ee570')
+    @decorators.idempotent_id('93055106-2d34-46fe-af68-d9ddbf7ee570')
     def test_list_servers_detail_server_is_deleted(self):
         # Server details are not listed for a deleted server
         deleted_ids = [s['id'] for s in self.deleted_fixtures]
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 9fc30f9..7e55b12 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -14,12 +14,12 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class MultipleCreateTestJSON(base.BaseV2ComputeTest):
 
-    @test.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
+    @decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
         body = self.create_test_server(wait_until='ACTIVE',
                                        min_count=1,
@@ -29,7 +29,7 @@
         # contains return_reservation_id=False
         self.assertNotIn('reservation_id', body)
 
-    @test.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
+    @decorators.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
     def test_multiple_create_with_reservation_return(self):
         body = self.create_test_server(wait_until='ACTIVE',
                                        min_count=1,
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index d9fb4ca..675cbee 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -21,35 +22,35 @@
 class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('daf29d8d-e928-4a01-9a8c-b129603f3fc0')
+    @decorators.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_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('999aa722-d624-4423-b813-0d1ac9884d7a')
+    @decorators.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_test_server,
                           min_count=invalid_min_count)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a6f9c2ab-e060-4b82-b23c-4532cb9390ff')
+    @decorators.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_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9c5698d1-d7af-4c80-b971-9d403135eea2')
+    @decorators.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_test_server,
                           max_count=invalid_max_count)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('476da616-f1ef-4271-a9b1-b9fc87727cdf')
+    @decorators.idempotent_id('476da616-f1ef-4271-a9b1-b9fc87727cdf')
     def test_max_count_less_than_min_count(self):
         min_count = 3
         max_count = 2
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 0a94d5e..6160024 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -75,7 +75,7 @@
         super(ServerActionsTestJSON, cls).resource_setup()
         cls.server_id = cls.rebuild_server(None, validatable=True)
 
-    @test.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
+    @decorators.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
     @testtools.skipUnless(CONF.compute_feature_enabled.change_password,
                           'Change password not available.')
     def test_change_server_password(self):
@@ -134,13 +134,13 @@
                                '%s > %s' % (new_boot_time, boot_time))
 
     @test.attr(type='smoke')
-    @test.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
+    @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
     def test_reboot_server_hard(self):
         # The server should be power cycled
         self._test_reboot_server('HARD')
 
     @decorators.skip_because(bug="1014647")
-    @test.idempotent_id('4640e3ef-a5df-482e-95a1-ceeeb0faa84d')
+    @decorators.idempotent_id('4640e3ef-a5df-482e-95a1-ceeeb0faa84d')
     def test_reboot_server_soft(self):
         # The server should be signaled to reboot gracefully
         self._test_reboot_server('SOFT')
@@ -154,7 +154,7 @@
                .format(image_ref, rebuilt_server['image']['id']))
         self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
 
-    @test.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
+    @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
     def test_rebuild_server(self):
         # The server should be rebuilt using the provided image and data
         meta = {'rebuild': 'server'}
@@ -202,7 +202,7 @@
                 servers_client=self.client)
             linux_client.validate_authentication()
 
-    @test.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
+    @decorators.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
     def test_rebuild_server_in_stop_state(self):
         # The server in stop state  should be rebuilt using the provided
         # image and remain in SHUTOFF state
@@ -234,7 +234,7 @@
 
         self.client.start_server(self.server_id)
 
-    @test.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace')
+    @decorators.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace')
     @test.services('volume')
     def test_rebuild_server_with_volume_attached(self):
         # create a new volume and attach it to the server
@@ -281,19 +281,19 @@
             # NOTE(mriedem): tearDown requires the server to be started.
             self.client.start_server(self.server_id)
 
-    @test.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
+    @decorators.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_confirm(self):
         self._test_resize_server_confirm(stop=False)
 
-    @test.idempotent_id('138b131d-66df-48c9-a171-64f45eb92962')
+    @decorators.idempotent_id('138b131d-66df-48c9-a171-64f45eb92962')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_confirm_from_stopped(self):
         self._test_resize_server_confirm(stop=True)
 
-    @test.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68')
+    @decorators.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     def test_resize_server_revert(self):
@@ -313,7 +313,7 @@
         server = self.client.show_server(self.server_id)['server']
         self.assertEqual(self.flavor_ref, server['flavor']['id'])
 
-    @test.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
+    @decorators.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting not available, backup not possible.')
     @test.services('image')
@@ -350,7 +350,7 @@
                 else:
                     LOG.warning("Deletion of oldest backup %s should not have "
                                 "been successful as it should have been "
-                                "deleted during rotation." % oldest_backup)
+                                "deleted during rotation.", oldest_backup)
 
         image1_id = data_utils.parse_image_id(resp['location'])
         self.addCleanup(_clean_oldest_backup, image1_id)
@@ -428,7 +428,7 @@
         lines = len(output.split('\n'))
         self.assertEqual(lines, 10)
 
-    @test.idempotent_id('4b8867e6-fffa-4d54-b1d1-6fdda57be2f3')
+    @decorators.idempotent_id('4b8867e6-fffa-4d54-b1d1-6fdda57be2f3')
     @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
                           'Console output not supported.')
     def test_get_console_output(self):
@@ -444,7 +444,7 @@
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
         self.wait_for(self._get_output)
 
-    @test.idempotent_id('89104062-69d8-4b19-a71b-f47b7af093d7')
+    @decorators.idempotent_id('89104062-69d8-4b19-a71b-f47b7af093d7')
     @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
                           'Console output not supported.')
     def test_get_console_output_with_unlimited_size(self):
@@ -462,7 +462,7 @@
 
         self.wait_for(_check_full_length_console_log)
 
-    @test.idempotent_id('5b65d4e7-4ecd-437c-83c0-d6b79d927568')
+    @decorators.idempotent_id('5b65d4e7-4ecd-437c-83c0-d6b79d927568')
     @testtools.skipUnless(CONF.compute_feature_enabled.console_output,
                           'Console output not supported.')
     def test_get_console_output_server_id_in_shutoff_status(self):
@@ -479,7 +479,7 @@
         waiters.wait_for_server_status(self.client, temp_server_id, 'SHUTOFF')
         self.wait_for(self._get_output)
 
-    @test.idempotent_id('bd61a9fd-062f-4670-972b-2d6c3e3b9e73')
+    @decorators.idempotent_id('bd61a9fd-062f-4670-972b-2d6c3e3b9e73')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     def test_pause_unpause_server(self):
@@ -488,7 +488,7 @@
         self.client.unpause_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
-    @test.idempotent_id('0d8ee21e-b749-462d-83da-b85b41c86c7f')
+    @decorators.idempotent_id('0d8ee21e-b749-462d-83da-b85b41c86c7f')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     def test_suspend_resume_server(self):
@@ -498,7 +498,7 @@
         self.client.resume_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
-    @test.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
+    @decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     def test_shelve_unshelve_server(self):
@@ -515,14 +515,14 @@
         self.client.unshelve_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
-    @test.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
+    @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
     def test_stop_start_server(self):
         self.client.stop_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
         self.client.start_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
-    @test.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
+    @decorators.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
     def test_lock_unlock_server(self):
         # Lock the server,try server stop(exceptions throw),unlock it and retry
         self.client.lock_server(self.server_id)
@@ -545,7 +545,7 @@
         self.assertNotEqual('None', parsed_url.hostname)
         self.assertIn(parsed_url.scheme, valid_scheme)
 
-    @test.idempotent_id('c6bc11bf-592e-4015-9319-1c98dc64daf5')
+    @decorators.idempotent_id('c6bc11bf-592e-4015-9319-1c98dc64daf5')
     @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
                           'VNC Console feature is disabled.')
     def test_get_vnc_console(self):
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index d31b6f8..dfda51b 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -13,9 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
-
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -39,7 +38,7 @@
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @test.attr(type='smoke')
-    @test.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
+    @decorators.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
     @test.services('network')
     def test_list_server_addresses(self):
         # All public and private addresses for
@@ -50,14 +49,14 @@
         # We do not know the exact network configuration, but an instance
         # should at least have a single public or private address
         self.assertGreaterEqual(len(addresses), 1)
-        for network_name, network_addresses in six.iteritems(addresses):
+        for network_name, network_addresses in addresses.items():
             self.assertGreaterEqual(len(network_addresses), 1)
             for address in network_addresses:
                 self.assertTrue(address['addr'])
                 self.assertTrue(address['version'])
 
     @test.attr(type='smoke')
-    @test.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
+    @decorators.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
     @test.services('network')
     def test_list_server_addresses_by_network(self):
         # Providing a network type should filter
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index b4753e1..1884e4f 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -36,7 +37,7 @@
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
+    @decorators.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
     @test.services('network')
     def test_list_server_addresses_invalid_server_id(self):
         # List addresses request should fail if server id not in system
@@ -44,7 +45,7 @@
                           '999')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
+    @decorators.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
     @test.services('network')
     def test_list_server_addresses_by_network_neg(self):
         # List addresses by network should fail if network name not valid
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index bc49e7b..6679b58 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -67,23 +68,23 @@
         server_group = self._create_server_group(name, policy)
         self._delete_server_group(server_group)
 
-    @test.idempotent_id('5dc57eda-35b7-4af7-9e5f-3c2be3d2d68b')
+    @decorators.idempotent_id('5dc57eda-35b7-4af7-9e5f-3c2be3d2d68b')
     def test_create_delete_server_group_with_affinity_policy(self):
         # Create and Delete the server-group with affinity policy
         self._create_delete_server_group(self.policy)
 
-    @test.idempotent_id('3645a102-372f-4140-afad-13698d850d23')
+    @decorators.idempotent_id('3645a102-372f-4140-afad-13698d850d23')
     def test_create_delete_server_group_with_anti_affinity_policy(self):
         # Create and Delete the server-group with anti-affinity policy
         policy = ['anti-affinity']
         self._create_delete_server_group(policy)
 
-    @test.idempotent_id('154dc5a4-a2fe-44b5-b99e-f15806a4a113')
+    @decorators.idempotent_id('154dc5a4-a2fe-44b5-b99e-f15806a4a113')
     def test_create_delete_multiple_server_groups_with_same_name_policy(self):
         # Create and Delete the server-groups with same name and same policy
         server_groups = []
         server_group_name = data_utils.rand_name('server-group')
-        for i in range(0, 2):
+        for _ in range(0, 2):
             server_groups.append(self._create_server_group(server_group_name,
                                                            self.policy))
         for key in ['name', 'policies']:
@@ -93,14 +94,14 @@
         for i in range(0, 2):
             self._delete_server_group(server_groups[i])
 
-    @test.idempotent_id('b3545034-dd78-48f0-bdc2-a4adfa6d0ead')
+    @decorators.idempotent_id('b3545034-dd78-48f0-bdc2-a4adfa6d0ead')
     def test_show_server_group(self):
         # Get the server-group
         body = self.client.show_server_group(
             self.created_server_group['id'])['server_group']
         self.assertEqual(self.created_server_group, body)
 
-    @test.idempotent_id('d4874179-27b4-4d7d-80e4-6c560cdfe321')
+    @decorators.idempotent_id('d4874179-27b4-4d7d-80e4-6c560cdfe321')
     def test_list_server_groups(self):
         # List the server-group
         body = self.client.list_server_groups()['server_groups']
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 847b7a1..f77e7d3 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class ServerMetadataTestJSON(base.BaseV2ComputeTest):
@@ -34,7 +34,7 @@
         meta = {'key1': 'value1', 'key2': 'value2'}
         self.client.set_server_metadata(self.server['id'], meta)['metadata']
 
-    @test.idempotent_id('479da087-92b3-4dcf-aeb3-fd293b2d14ce')
+    @decorators.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'])
@@ -44,7 +44,7 @@
         expected = {'key1': 'value1', 'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('211021f6-21de-4657-a68f-908878cfe251')
+    @decorators.idempotent_id('211021f6-21de-4657-a68f-908878cfe251')
     def test_set_server_metadata(self):
         # The server's metadata should be replaced with the provided values
         # Create a new set of metadata for the server
@@ -58,7 +58,7 @@
                          ['metadata'])
         self.assertEqual(resp_metadata, req_metadata)
 
-    @test.idempotent_id('344d981e-0c33-4997-8a5d-6c1d803e4134')
+    @decorators.idempotent_id('344d981e-0c33-4997-8a5d-6c1d803e4134')
     def test_update_server_metadata(self):
         # The server's metadata values should be updated to the
         # provided values
@@ -71,7 +71,7 @@
         expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('0f58d402-e34a-481d-8af8-b392b17426d9')
+    @decorators.idempotent_id('0f58d402-e34a-481d-8af8-b392b17426d9')
     def test_update_metadata_empty_body(self):
         # The original metadata should not be lost if empty metadata body is
         # passed
@@ -82,14 +82,14 @@
         expected = {'key1': 'value1', 'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('3043c57d-7e0e-49a6-9a96-ad569c265e6a')
+    @decorators.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'],
                                                      'key2')['meta']
         self.assertEqual('value2', meta['key2'])
 
-    @test.idempotent_id('58c02d4f-5c67-40be-8744-d3fa5982eb1c')
+    @decorators.idempotent_id('58c02d4f-5c67-40be-8744-d3fa5982eb1c')
     def test_set_server_metadata_item(self):
         # The item's value should be updated to the provided value
         # Update the metadata value
@@ -102,7 +102,7 @@
         expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
         self.assertEqual(expected, resp_metadata)
 
-    @test.idempotent_id('127642d6-4c7b-4486-b7cd-07265a378658')
+    @decorators.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')
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 62b8962..92ffa86 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -33,7 +34,7 @@
         cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fe114a8f-3a57-4eff-9ee2-4e14628df049')
+    @decorators.idempotent_id('fe114a8f-3a57-4eff-9ee2-4e14628df049')
     def test_server_create_metadata_key_too_long(self):
         # Attempt to start a server with a meta-data key that is > 255
         # characters
@@ -49,7 +50,7 @@
         # no teardown - all creates should fail
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('92431555-4d8b-467c-b95b-b17daa5e57ff')
+    @decorators.idempotent_id('92431555-4d8b-467c-b95b-b17daa5e57ff')
     def test_create_server_metadata_blank_key(self):
         # Blank key should trigger an error.
         meta = {'': 'data1'}
@@ -58,7 +59,7 @@
                           metadata=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
+    @decorators.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
     def test_server_metadata_non_existent_server(self):
         # GET on a non-existent server should not succeed
         non_existent_server_id = data_utils.rand_uuid()
@@ -68,7 +69,7 @@
                           'test2')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f408e78e-3066-4097-9299-3b0182da812e')
+    @decorators.idempotent_id('f408e78e-3066-4097-9299-3b0182da812e')
     def test_list_server_metadata_non_existent_server(self):
         # List metadata on a non-existent server should not succeed
         non_existent_server_id = data_utils.rand_uuid()
@@ -77,7 +78,7 @@
                           non_existent_server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0025fbd6-a4ba-4cde-b8c2-96805dcfdabc')
+    @decorators.idempotent_id('0025fbd6-a4ba-4cde-b8c2-96805dcfdabc')
     def test_wrong_key_passed_in_body(self):
         # Raise BadRequest if key in uri does not match
         # the key passed in body.
@@ -87,7 +88,7 @@
                           self.server['id'], 'key', meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0df38c2a-3d4e-4db5-98d8-d4d9fa843a12')
+    @decorators.idempotent_id('0df38c2a-3d4e-4db5-98d8-d4d9fa843a12')
     def test_set_metadata_non_existent_server(self):
         # Set metadata on a non-existent server should not succeed
         non_existent_server_id = data_utils.rand_uuid()
@@ -98,7 +99,7 @@
                           meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('904b13dc-0ef2-4e4c-91cd-3b4a0f2f49d8')
+    @decorators.idempotent_id('904b13dc-0ef2-4e4c-91cd-3b4a0f2f49d8')
     def test_update_metadata_non_existent_server(self):
         # An update should not happen for a non-existent server
         non_existent_server_id = data_utils.rand_uuid()
@@ -109,7 +110,7 @@
                           meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a452f38c-05c2-4b47-bd44-a4f0bf5a5e48')
+    @decorators.idempotent_id('a452f38c-05c2-4b47-bd44-a4f0bf5a5e48')
     def test_update_metadata_with_blank_key(self):
         # Blank key should trigger an error
         meta = {'': 'data1'}
@@ -118,7 +119,7 @@
                           self.server['id'], meta=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6bbd88e1-f8b3-424d-ba10-ae21c45ada8d')
+    @decorators.idempotent_id('6bbd88e1-f8b3-424d-ba10-ae21c45ada8d')
     def test_delete_metadata_non_existent_server(self):
         # Should not be able to delete metadata item from a non-existent server
         non_existent_server_id = data_utils.rand_uuid()
@@ -128,7 +129,7 @@
                           'd')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('d8c0a210-a5c3-4664-be04-69d96746b547')
+    @decorators.idempotent_id('d8c0a210-a5c3-4664-be04-69d96746b547')
     def test_metadata_items_limit(self):
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
         # will be raised while exceeding metadata items limit for
@@ -154,7 +155,7 @@
                           self.server['id'], req_metadata)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
+    @decorators.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
     def test_set_server_metadata_blank_key(self):
         # Raise a bad request error for blank key.
         # set_server_metadata will replace all metadata with new value
@@ -164,7 +165,7 @@
                           self.server['id'], meta=meta)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('64a91aee-9723-4863-be44-4c9d9f1e7d0e')
+    @decorators.idempotent_id('64a91aee-9723-4863-be44-4c9d9f1e7d0e')
     def test_set_server_metadata_missing_metadata(self):
         # Raise a bad request error for a missing metadata field
         # set_server_metadata will replace all metadata with new value
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index 9b41708..e7591a5 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -15,7 +15,7 @@
 
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class ServerPasswordTestJSON(base.BaseV2ComputeTest):
@@ -30,10 +30,10 @@
         super(ServerPasswordTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until="ACTIVE")
 
-    @test.idempotent_id('f83b582f-62a8-4f22-85b0-0dee50ff783a')
+    @decorators.idempotent_id('f83b582f-62a8-4f22-85b0-0dee50ff783a')
     def test_get_server_password(self):
         self.client.show_password(self.server['id'])
 
-    @test.idempotent_id('f8229e8b-b625-4493-800a-bde86ac611ea')
+    @decorators.idempotent_id('f8229e8b-b625-4493-800a-bde86ac611ea')
     def test_delete_server_password(self):
         self.client.delete_password(self.server['id'])
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index ab291b4..957d24a 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -20,8 +20,8 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -50,7 +50,7 @@
         cls.client = cls.servers_client
         cls.user_client = cls.limits_client
 
-    @test.idempotent_id('3cfe87fd-115b-4a02-b942-7dc36a337fdf')
+    @decorators.idempotent_id('3cfe87fd-115b-4a02-b942-7dc36a337fdf')
     def test_create_server_with_personality(self):
         file_contents = 'This is a test file.'
         file_path = '/test.txt'
@@ -73,7 +73,7 @@
                              linux_client.exec_command(
                                  'sudo cat %s' % file_path))
 
-    @test.idempotent_id('128966d8-71fc-443c-8cab-08e24114ecc9')
+    @decorators.idempotent_id('128966d8-71fc-443c-8cab-08e24114ecc9')
     def test_rebuild_server_with_personality(self):
         server = self.create_test_server(wait_until='ACTIVE', validatable=True)
         server_id = server['id']
@@ -87,7 +87,7 @@
         self.assertEqual(self.image_ref_alt,
                          rebuilt_server['server']['image']['id'])
 
-    @test.idempotent_id('176cd8c9-b9e8-48ee-a480-180beab292bf')
+    @decorators.idempotent_id('176cd8c9-b9e8-48ee-a480-180beab292bf')
     def test_personality_files_exceed_limit(self):
         # Server creation should fail if greater than the maximum allowed
         # number of files are injected into the server.
@@ -107,7 +107,7 @@
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server, personality=personality)
 
-    @test.idempotent_id('52f12ee8-5180-40cc-b417-31572ea3d555')
+    @decorators.idempotent_id('52f12ee8-5180-40cc-b417-31572ea3d555')
     def test_can_create_server_with_max_number_personality_files(self):
         # Server should be created successfully if maximum allowed number of
         # files is injected into the server during creation.
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 9834d02..5db7f4f 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -17,7 +17,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -74,7 +74,7 @@
         waiters.wait_for_server_status(self.servers_client, server_id,
                                        'ACTIVE')
 
-    @test.idempotent_id('fd032140-714c-42e4-a8fd-adcd8df06be6')
+    @decorators.idempotent_id('fd032140-714c-42e4-a8fd-adcd8df06be6')
     def test_rescue_unrescue_instance(self):
         self.servers_client.rescue_server(
             self.server_id, adminPass=self.password)
@@ -84,7 +84,7 @@
         waiters.wait_for_server_status(self.servers_client, self.server_id,
                                        'ACTIVE')
 
-    @test.idempotent_id('4842e0cf-e87d-4d9d-b61f-f4791da3cacc')
+    @decorators.idempotent_id('4842e0cf-e87d-4d9d-b61f-f4791da3cacc')
     def test_rescued_vm_associate_dissociate_floating_ip(self):
         # Rescue the server
         self.servers_client.rescue_server(
@@ -102,7 +102,7 @@
         client.disassociate_floating_ip_from_server(self.floating_ip,
                                                     self.server_id)
 
-    @test.idempotent_id('affca41f-7195-492d-8065-e09eee245404')
+    @decorators.idempotent_id('affca41f-7195-492d-8065-e09eee245404')
     def test_rescued_vm_add_remove_security_group(self):
         # Rescue the server
         self.servers_client.rescue_server(
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 41b648c..c3a8c36 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -19,6 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -70,7 +71,7 @@
         waiters.wait_for_server_status(self.servers_client,
                                        server_id, 'ACTIVE')
 
-    @test.idempotent_id('cc3a883f-43c0-4fb6-a9bb-5579d64984ed')
+    @decorators.idempotent_id('cc3a883f-43c0-4fb6-a9bb-5579d64984ed')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     @test.attr(type=['negative'])
@@ -85,13 +86,13 @@
                           self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('db22b618-f157-4566-a317-1b6d467a8094')
+    @decorators.idempotent_id('db22b618-f157-4566-a317-1b6d467a8094')
     def test_rescued_vm_reboot(self):
         self.assertRaises(lib_exc.Conflict, self.servers_client.reboot_server,
                           self.rescue_id, type='HARD')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
+    @decorators.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
     def test_rescue_non_existent_server(self):
         # Rescue a non-existing server
         non_existent_server = data_utils.rand_uuid()
@@ -100,14 +101,14 @@
                           non_existent_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('70cdb8a1-89f8-437d-9448-8844fd82bf46')
+    @decorators.idempotent_id('70cdb8a1-89f8-437d-9448-8844fd82bf46')
     def test_rescued_vm_rebuild(self):
         self.assertRaises(lib_exc.Conflict,
                           self.servers_client.rebuild_server,
                           self.rescue_id,
                           self.image_ref_alt)
 
-    @test.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
+    @decorators.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
     @test.services('volume')
     @test.attr(type=['negative'])
     def test_rescued_vm_attach_volume(self):
@@ -127,7 +128,7 @@
                           volumeId=volume['id'],
                           device='/dev/%s' % self.device)
 
-    @test.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
+    @decorators.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
     @test.services('volume')
     @test.attr(type=['negative'])
     def test_rescued_vm_detach_volume(self):
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 5aeba4e..b463726 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -19,7 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -35,7 +35,7 @@
         self.clear_servers()
         super(ServersTestJSON, self).tearDown()
 
-    @test.idempotent_id('b92d5ec7-b1dd-44a2-87e4-45e888c46ef0')
+    @decorators.idempotent_id('b92d5ec7-b1dd-44a2-87e4-45e888c46ef0')
     @testtools.skipUnless(CONF.compute_feature_enabled.
                           enable_instance_password,
                           'Instance password not available.')
@@ -47,7 +47,7 @@
         # Verify the password is set correctly in the response
         self.assertEqual('testpassword', server['adminPass'])
 
-    @test.idempotent_id('8fea6be7-065e-47cf-89b8-496e6f96c699')
+    @decorators.idempotent_id('8fea6be7-065e-47cf-89b8-496e6f96c699')
     def test_create_with_existing_server_name(self):
         # Creating a server with a name that already exists is allowed
 
@@ -67,7 +67,7 @@
         name2 = server['name']
         self.assertEqual(name1, name2)
 
-    @test.idempotent_id('f9e15296-d7f9-4e62-b53f-a04e89160833')
+    @decorators.idempotent_id('f9e15296-d7f9-4e62-b53f-a04e89160833')
     def test_create_specify_keypair(self):
         # Specify a keypair while creating a server
 
@@ -94,7 +94,7 @@
         self.assertEqual(new_name, server['name'])
         return server
 
-    @test.idempotent_id('5e6ccff8-349d-4852-a8b3-055df7988dd2')
+    @decorators.idempotent_id('5e6ccff8-349d-4852-a8b3-055df7988dd2')
     def test_update_server_name(self):
         # The server name should be changed to the provided value
         server = self.create_test_server(wait_until='ACTIVE')
@@ -102,7 +102,7 @@
         prefix_name = u'\u00CD\u00F1st\u00E1\u00F1c\u00E9'
         self._update_server_name(server['id'], 'ACTIVE', prefix_name)
 
-    @test.idempotent_id('6ac19cb1-27a3-40ec-b350-810bdc04c08e')
+    @decorators.idempotent_id('6ac19cb1-27a3-40ec-b350-810bdc04c08e')
     def test_update_server_name_in_stop_state(self):
         # The server name should be changed to the provided value
         server = self.create_test_server(wait_until='ACTIVE')
@@ -115,7 +115,7 @@
                                                   prefix_name)
         self.assertNotIn('progress', updated_server)
 
-    @test.idempotent_id('89b90870-bc13-4b73-96af-f9d4f2b70077')
+    @decorators.idempotent_id('89b90870-bc13-4b73-96af-f9d4f2b70077')
     def test_update_access_server_address(self):
         # The server's access addresses should reflect the provided values
         server = self.create_test_server(wait_until='ACTIVE')
@@ -131,7 +131,7 @@
         self.assertEqual('1.1.1.1', server['accessIPv4'])
         self.assertEqual('::babe:202:202', server['accessIPv6'])
 
-    @test.idempotent_id('38fb1d02-c3c5-41de-91d3-9bc2025a75eb')
+    @decorators.idempotent_id('38fb1d02-c3c5-41de-91d3-9bc2025a75eb')
     def test_create_server_with_ipv6_addr_only(self):
         # Create a server without an IPv4 address(only IPv6 address).
         server = self.create_test_server(accessIPv6='2001:2001::3')
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 1b1b339..853d2ff 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -22,6 +22,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -54,7 +55,7 @@
         cls.server_id = server['id']
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('dbbfd247-c40c-449e-8f6c-d2aa7c7da7cf')
+    @decorators.idempotent_id('dbbfd247-c40c-449e-8f6c-d2aa7c7da7cf')
     def test_server_name_blank(self):
         # Create a server with name parameter empty
 
@@ -63,7 +64,7 @@
                           name='')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
+    @decorators.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
     @testtools.skipUnless(CONF.compute_feature_enabled.personality,
                           'Nova personality feature disabled')
     def test_personality_file_contents_not_encoded(self):
@@ -78,7 +79,7 @@
                           personality=person)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fcba1052-0a50-4cf3-b1ac-fae241edf02f')
+    @decorators.idempotent_id('fcba1052-0a50-4cf3-b1ac-fae241edf02f')
     def test_create_with_invalid_image(self):
         # Create a server with an unknown image
 
@@ -87,7 +88,7 @@
                           image_id=-1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('18f5227f-d155-4429-807c-ccb103887537')
+    @decorators.idempotent_id('18f5227f-d155-4429-807c-ccb103887537')
     def test_create_with_invalid_flavor(self):
         # Create a server with an unknown flavor
 
@@ -96,7 +97,7 @@
                           flavor=-1,)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7f70a4d1-608f-4794-9e56-cb182765972c')
+    @decorators.idempotent_id('7f70a4d1-608f-4794-9e56-cb182765972c')
     def test_invalid_access_ip_v4_address(self):
         # An access IPv4 address must match a valid address pattern
 
@@ -105,7 +106,7 @@
                           self.create_test_server, accessIPv4=IPv4)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5226dd80-1e9c-4d8a-b5f9-b26ca4763fd0')
+    @decorators.idempotent_id('5226dd80-1e9c-4d8a-b5f9-b26ca4763fd0')
     def test_invalid_ip_v6_address(self):
         # An access IPv6 address must match a valid address pattern
 
@@ -114,7 +115,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.create_test_server, accessIPv6=IPv6)
 
-    @test.idempotent_id('7ea45b3e-e770-46fa-bfcc-9daaf6d987c0')
+    @decorators.idempotent_id('7ea45b3e-e770-46fa-bfcc-9daaf6d987c0')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type=['negative'])
@@ -125,7 +126,7 @@
                           self.client.resize_server,
                           nonexistent_server, self.flavor_ref)
 
-    @test.idempotent_id('ced1a1d7-2ab6-45c9-b90f-b27d87b30efd')
+    @decorators.idempotent_id('ced1a1d7-2ab6-45c9-b90f-b27d87b30efd')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type=['negative'])
@@ -135,7 +136,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.resize_server,
                           self.server_id, flavor_ref=nonexistent_flavor)
 
-    @test.idempotent_id('45436a7d-a388-4a35-a9d8-3adc5d0d940b')
+    @decorators.idempotent_id('45436a7d-a388-4a35-a9d8-3adc5d0d940b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
     @test.attr(type=['negative'])
@@ -145,14 +146,14 @@
                           self.server_id, flavor_ref="")
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
+    @decorators.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
     def test_reboot_non_existent_server(self):
         # Reboot a non existent server
         nonexistent_server = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
                           nonexistent_server, type='SOFT')
 
-    @test.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
+    @decorators.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     @test.attr(type=['negative'])
@@ -166,7 +167,7 @@
         self.client.unpause_server(self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
+    @decorators.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
     def test_rebuild_deleted_server(self):
         # Rebuild a deleted server
         server = self.create_test_server()
@@ -178,7 +179,7 @@
                           server['id'], self.image_ref_alt)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
+    @decorators.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
     def test_reboot_deleted_server(self):
         # Reboot a deleted server
         server = self.create_test_server()
@@ -189,7 +190,7 @@
                           server['id'], type='SOFT')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
+    @decorators.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
     def test_rebuild_non_existent_server(self):
         # Rebuild a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -199,7 +200,7 @@
                           self.image_ref_alt)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
+    @decorators.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
     def test_create_numeric_server_name(self):
         server_name = 12345
         self.assertRaises(lib_exc.BadRequest,
@@ -207,9 +208,9 @@
                           name=server_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('c3e0fb12-07fc-4d76-a22e-37409887afe8')
+    @decorators.idempotent_id('c3e0fb12-07fc-4d76-a22e-37409887afe8')
     def test_create_server_name_length_exceeds_256(self):
-        # Create a server with name length exceeding 256 characters
+        # Create a server with name length exceeding 255 characters
 
         server_name = 'a' * 256
         self.assertRaises(lib_exc.BadRequest,
@@ -217,7 +218,27 @@
                           name=server_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('4e72dc2d-44c5-4336-9667-f7972e95c402')
+    @test.related_bug('1651064', status_code=500)
+    @decorators.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
+    def test_create_server_invalid_bdm_in_2nd_dict(self):
+        volume = self.create_volume()
+        bdm_1st = {"source_type": "image",
+                   "delete_on_termination": True,
+                   "boot_index": 0,
+                   "uuid": self.image_ref,
+                   "destination_type": "local"}
+        bdm_2nd = {"source_type": "volume",
+                   "uuid": volume["id"],
+                   "destination_type": "invalid"}
+        bdm = [bdm_1st, bdm_2nd]
+
+        self.assertRaises(lib_exc.BadRequest,
+                          self.create_test_server,
+                          image_id=self.image_ref,
+                          block_device_mapping_v2=bdm)
+
+    @test.attr(type=['negative'])
+    @decorators.idempotent_id('4e72dc2d-44c5-4336-9667-f7972e95c402')
     def test_create_with_invalid_network_uuid(self):
         # Pass invalid network uuid while creating a server
 
@@ -228,7 +249,7 @@
                           networks=networks)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7a2efc39-530c-47de-b875-2dd01c8d39bd')
+    @decorators.idempotent_id('7a2efc39-530c-47de-b875-2dd01c8d39bd')
     def test_create_with_non_existent_keypair(self):
         # Pass a non-existent keypair while creating a server
 
@@ -238,7 +259,7 @@
                           key_name=key_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7fc74810-0bd2-4cd7-8244-4f33a9db865a')
+    @decorators.idempotent_id('7fc74810-0bd2-4cd7-8244-4f33a9db865a')
     def test_create_server_metadata_exceeds_length_limit(self):
         # Pass really long metadata while creating a server
 
@@ -248,7 +269,7 @@
                           metadata=metadata)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
+    @decorators.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
     def test_update_name_of_non_existent_server(self):
         # Update name of a non-existent server
 
@@ -260,7 +281,7 @@
                           nonexistent_server, name=new_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('38204696-17c6-44da-9590-40f87fb5a899')
+    @decorators.idempotent_id('38204696-17c6-44da-9590-40f87fb5a899')
     def test_update_server_set_empty_name(self):
         # Update name of the server to an empty string
 
@@ -270,7 +291,7 @@
                           self.server_id, name=new_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5c8e244c-dada-4590-9944-749c455b431f')
+    @decorators.idempotent_id('5c8e244c-dada-4590-9944-749c455b431f')
     def test_update_server_name_length_exceeds_256(self):
         # Update name of server exceed the name length limit
 
@@ -281,7 +302,7 @@
                           name=new_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('1041b4e6-514b-4855-96a5-e974b60870a3')
+    @decorators.idempotent_id('1041b4e6-514b-4855-96a5-e974b60870a3')
     def test_delete_non_existent_server(self):
         # Delete a non existent server
 
@@ -290,14 +311,14 @@
                           nonexistent_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('75f79124-277c-45e6-a373-a1d6803f4cc4')
+    @decorators.idempotent_id('75f79124-277c-45e6-a373-a1d6803f4cc4')
     def test_delete_server_pass_negative_id(self):
         # Pass an invalid string parameter to delete server
 
         self.assertRaises(lib_exc.NotFound, self.client.delete_server, -1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('f4d7279b-5fd2-4bf2-9ba4-ae35df0d18c5')
+    @decorators.idempotent_id('f4d7279b-5fd2-4bf2-9ba4-ae35df0d18c5')
     def test_delete_server_pass_id_exceeding_length_limit(self):
         # Pass a server ID that exceeds length limit to delete server
 
@@ -305,7 +326,7 @@
                           sys.maxsize + 1)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
+    @decorators.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
     def test_create_with_nonexistent_security_group(self):
         # Create a server with a nonexistent security group
 
@@ -315,7 +336,7 @@
                           security_groups=security_groups)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('3436b02f-1b1e-4f03-881e-c6a602327439')
+    @decorators.idempotent_id('3436b02f-1b1e-4f03-881e-c6a602327439')
     def test_get_non_existent_server(self):
         # Get a non existent server details
         nonexistent_server = data_utils.rand_uuid()
@@ -323,14 +344,14 @@
                           nonexistent_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('a31460a9-49e1-42aa-82ee-06e0bb7c2d03')
+    @decorators.idempotent_id('a31460a9-49e1-42aa-82ee-06e0bb7c2d03')
     def test_stop_non_existent_server(self):
         # Stop a non existent server
         nonexistent_server = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.servers_client.stop_server,
                           nonexistent_server)
 
-    @test.idempotent_id('6a8dc0c6-6cd4-4c0a-9f32-413881828091')
+    @decorators.idempotent_id('6a8dc0c6-6cd4-4c0a-9f32-413881828091')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     @test.attr(type=['negative'])
@@ -340,7 +361,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.pause_server,
                           nonexistent_server)
 
-    @test.idempotent_id('705b8e3a-e8a7-477c-a19b-6868fc24ac75')
+    @decorators.idempotent_id('705b8e3a-e8a7-477c-a19b-6868fc24ac75')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     @test.attr(type=['negative'])
@@ -350,7 +371,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.unpause_server,
                           nonexistent_server)
 
-    @test.idempotent_id('c8e639a7-ece8-42dd-a2e0-49615917ba4f')
+    @decorators.idempotent_id('c8e639a7-ece8-42dd-a2e0-49615917ba4f')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
     @test.attr(type=['negative'])
@@ -360,7 +381,7 @@
                           self.client.unpause_server,
                           self.server_id)
 
-    @test.idempotent_id('d1f032d5-7b6e-48aa-b252-d5f16dd994ca')
+    @decorators.idempotent_id('d1f032d5-7b6e-48aa-b252-d5f16dd994ca')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @test.attr(type=['negative'])
@@ -370,7 +391,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.suspend_server,
                           nonexistent_server)
 
-    @test.idempotent_id('7f323206-05a9-4bf8-996b-dd5b2036501b')
+    @decorators.idempotent_id('7f323206-05a9-4bf8-996b-dd5b2036501b')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @test.attr(type=['negative'])
@@ -384,7 +405,7 @@
                           self.server_id)
         self.client.resume_server(self.server_id)
 
-    @test.idempotent_id('221cd282-bddb-4837-a683-89c2487389b6')
+    @decorators.idempotent_id('221cd282-bddb-4837-a683-89c2487389b6')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @test.attr(type=['negative'])
@@ -394,7 +415,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.resume_server,
                           nonexistent_server)
 
-    @test.idempotent_id('ccb6294d-c4c9-498f-8a43-554c098bfadb')
+    @decorators.idempotent_id('ccb6294d-c4c9-498f-8a43-554c098bfadb')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @test.attr(type=['negative'])
@@ -405,7 +426,7 @@
                           self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7dd919e7-413f-4198-bebb-35e2a01b13e9')
+    @decorators.idempotent_id('7dd919e7-413f-4198-bebb-35e2a01b13e9')
     def test_get_console_output_of_non_existent_server(self):
         # get the console output for a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -414,7 +435,7 @@
                           nonexistent_server, length=10)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
+    @decorators.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
     def test_force_delete_nonexistent_server_id(self):
         # force-delete a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -423,7 +444,7 @@
                           nonexistent_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('9c6d38cc-fcfb-437a-85b9-7b788af8bf01')
+    @decorators.idempotent_id('9c6d38cc-fcfb-437a-85b9-7b788af8bf01')
     def test_restore_nonexistent_server_id(self):
         # restore-delete a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -432,14 +453,14 @@
                           nonexistent_server)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7fcadfab-bd6a-4753-8db7-4a51e51aade9')
+    @decorators.idempotent_id('7fcadfab-bd6a-4753-8db7-4a51e51aade9')
     def test_restore_server_invalid_state(self):
         # we can only restore-delete a server in 'soft-delete' state
         self.assertRaises(lib_exc.Conflict,
                           self.client.restore_soft_deleted_server,
                           self.server_id)
 
-    @test.idempotent_id('abca56e2-a892-48ea-b5e5-e07e69774816')
+    @decorators.idempotent_id('abca56e2-a892-48ea-b5e5-e07e69774816')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     @test.attr(type=['negative'])
@@ -449,7 +470,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.shelve_server,
                           nonexistent_server)
 
-    @test.idempotent_id('443e4f9b-e6bf-4389-b601-3a710f15fddd')
+    @decorators.idempotent_id('443e4f9b-e6bf-4389-b601-3a710f15fddd')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     @test.attr(type=['negative'])
@@ -470,7 +491,7 @@
 
         self.client.unshelve_server(self.server_id)
 
-    @test.idempotent_id('23d23b37-afaf-40d7-aa5d-5726f82d8821')
+    @decorators.idempotent_id('23d23b37-afaf-40d7-aa5d-5726f82d8821')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     @test.attr(type=['negative'])
@@ -480,7 +501,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.unshelve_server,
                           nonexistent_server)
 
-    @test.idempotent_id('8f198ded-1cca-4228-9e65-c6b449c54880')
+    @decorators.idempotent_id('8f198ded-1cca-4228-9e65-c6b449c54880')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     @test.attr(type=['negative'])
@@ -491,7 +512,7 @@
                           self.server_id)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
+    @decorators.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
     @test.services('volume', 'image')
     def test_create_server_from_non_bootable_volume(self):
         # Create a volume
@@ -545,7 +566,7 @@
         cls.server_id = server['id']
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('543d84c1-dd2e-4c6d-8cb2-b9da0efaa384')
+    @decorators.idempotent_id('543d84c1-dd2e-4c6d-8cb2-b9da0efaa384')
     def test_update_server_of_another_tenant(self):
         # Update name of a server that belongs to another tenant
 
@@ -555,7 +576,7 @@
                           name=new_name)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5c75009d-3eea-423e-bea3-61b09fd25f9c')
+    @decorators.idempotent_id('5c75009d-3eea-423e-bea3-61b09fd25f9c')
     def test_delete_a_server_of_another_tenant(self):
         # Delete a server that belongs to another tenant
         self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index 08c34d3..610121b 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -18,6 +18,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
 
@@ -42,7 +43,7 @@
         super(VirtualInterfacesTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
+    @decorators.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
     @test.services('network')
     def test_list_virtual_interfaces(self):
         # Positive test:Should be able to GET the virtual interfaces list
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index 912b0a1..b1374d2 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -33,7 +34,7 @@
         cls.client = cls.servers_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
+    @decorators.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
     @test.services('network')
     def test_list_virtual_interfaces_invalid_server_id(self):
         # Negative test: Should not be able to GET virtual interfaces
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 6e57aff..f87bf6d 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -17,6 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
@@ -27,7 +28,7 @@
 
 class ExtensionsTestJSON(base.BaseV2ComputeTest):
 
-    @test.idempotent_id('3bb27738-b759-4e0d-a5fa-37d7a6df07d1')
+    @decorators.idempotent_id('3bb27738-b759-4e0d-a5fa-37d7a6df07d1')
     def test_list_extensions(self):
         # List of all extensions
         if len(CONF.compute_feature_enabled.api_extensions) == 0:
@@ -42,9 +43,9 @@
             raise self.skipException('There are not any extensions configured')
         # Log extensions list
         extension_list = map(lambda x: x['alias'], extensions)
-        LOG.debug("Nova extensions: %s" % ','.join(extension_list))
+        LOG.debug("Nova extensions: %s", ','.join(extension_list))
 
-    @test.idempotent_id('05762f39-bdfa-4cdb-9b46-b78f8e78e2fd')
+    @decorators.idempotent_id('05762f39-bdfa-4cdb-9b46-b78f8e78e2fd')
     @test.requires_ext(extension='os-consoles', service='compute')
     def test_get_extension(self):
         # get the specified extensions
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index f072b81..40d0746 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -17,6 +17,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -37,13 +38,12 @@
 
     def _migrate_server_to(self, server_id, dest_host):
         bmflm = CONF.compute_feature_enabled.block_migration_for_live_migration
-        body = self.admin_servers_client.live_migrate_server(
+        self.admin_servers_client.live_migrate_server(
             server_id, host=dest_host, block_migration=bmflm,
             disk_over_commit=False)
-        return body
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('7fb7856e-ae92-44c9-861a-af62d7830bcb')
+    @decorators.idempotent_id('7fb7856e-ae92-44c9-861a-af62d7830bcb')
     def test_invalid_host_for_migration(self):
         # Migrating to an invalid host should not change the status
         target_host = data_utils.rand_name('host')
diff --git a/tempest/api/compute/test_networks.py b/tempest/api/compute/test_networks.py
index d4b8003..4d21fed 100644
--- a/tempest/api/compute/test_networks.py
+++ b/tempest/api/compute/test_networks.py
@@ -14,7 +14,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
 
@@ -31,7 +31,7 @@
         super(ComputeNetworksTest, cls).setup_clients()
         cls.client = cls.os.compute_networks_client
 
-    @test.idempotent_id('3fe07175-312e-49a5-a623-5f52eeada4c2')
+    @decorators.idempotent_id('3fe07175-312e-49a5-a623-5f52eeada4c2')
     def test_list_networks(self):
         networks = self.client.list_networks()['networks']
         self.assertNotEmpty(networks, "No networks found.")
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index b9e0c35..0ad2df8 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -15,6 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -51,7 +52,7 @@
                                      'cores', 'security_groups',
                                      'server_group_members', 'server_groups'))
 
-    @test.idempotent_id('f1ef0a97-dbbb-4cca-adc5-c9fbc4f76107')
+    @decorators.idempotent_id('f1ef0a97-dbbb-4cca-adc5-c9fbc4f76107')
     def test_get_quotas(self):
         # User can get the quota set for it's tenant
         expected_quota_set = self.default_quota_set | set(['id'])
@@ -67,7 +68,7 @@
         for quota in expected_quota_set:
             self.assertIn(quota, quota_set.keys())
 
-    @test.idempotent_id('9bfecac7-b966-4f47-913f-1a9e2c12134a')
+    @decorators.idempotent_id('9bfecac7-b966-4f47-913f-1a9e2c12134a')
     def test_get_default_quotas(self):
         # User can get the default quota set for it's tenant
         expected_quota_set = self.default_quota_set | set(['id'])
@@ -77,7 +78,7 @@
         for quota in expected_quota_set:
             self.assertIn(quota, quota_set.keys())
 
-    @test.idempotent_id('cd65d997-f7e4-4966-a7e9-d5001b674fdc')
+    @decorators.idempotent_id('cd65d997-f7e4-4966-a7e9-d5001b674fdc')
     def test_compare_tenant_quotas_with_default_quotas(self):
         # Tenants are created with the default quota values
         default_quota_set = \
diff --git a/tempest/api/compute/test_tenant_networks.py b/tempest/api/compute/test_tenant_networks.py
index 96b7ef6..b203c7e 100644
--- a/tempest/api/compute/test_tenant_networks.py
+++ b/tempest/api/compute/test_tenant_networks.py
@@ -13,6 +13,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.lib import decorators
 from tempest import test
 
 
@@ -29,7 +30,7 @@
         cls.set_network_resources(network=True)
         super(ComputeTenantNetworksTest, cls).setup_credentials()
 
-    @test.idempotent_id('edfea98e-bbe3-4c7a-9739-87b986baff26')
+    @decorators.idempotent_id('edfea98e-bbe3-4c7a-9739-87b986baff26')
     @test.services('network')
     def test_list_show_tenant_networks(self):
         # Fetch all networks that are visible to the tenant: this may include
diff --git a/tempest/api/compute/test_versions.py b/tempest/api/compute/test_versions.py
index 8b84a21..c9f0724 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -13,12 +13,12 @@
 # under the License.
 
 from tempest.api.compute import base
-from tempest import test
+from tempest.lib import decorators
 
 
 class TestVersions(base.BaseV2ComputeTest):
 
-    @test.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
+    @decorators.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
     def test_list_api_versions(self):
         """Test that a get of the unversioned url returns the choices doc.
 
@@ -36,7 +36,7 @@
         self.assertEqual(versions[0]['id'], 'v2.0',
                          "The first listed version should be v2.0")
 
-    @test.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
+    @decorators.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
     def test_get_version_details(self):
         """Test individual version endpoints info works.
 
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 56ec8c6..cbe7178 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
+from oslo_log import log as logging
 import testtools
 
 from tempest.api.compute import base
@@ -21,8 +21,8 @@
 from tempest.common.utils.linux import remote_client
 from tempest.common import waiters
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -68,8 +68,8 @@
                                            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))
+                        "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
@@ -85,7 +85,7 @@
 
         return attachment
 
-    @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
+    @decorators.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.
@@ -111,9 +111,9 @@
                 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_volume(server['id'], attachment['volumeId'])
         self.servers_client.stop_server(server['id'])
@@ -133,10 +133,10 @@
                 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')
+    @decorators.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
     def test_list_get_volume_attachments(self):
         # List volume attachment of the server
         server = self._create_server()
@@ -156,7 +156,7 @@
         self.assertEqual(volume['id'], body['volumeId'])
         self.assertEqual(attachment['id'], body['id'])
 
-    @test.idempotent_id('757d488b-a951-4bc7-b3cd-f417028da08a')
+    @decorators.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
@@ -243,7 +243,7 @@
             counted_volumes = self._count_volumes(server)
             self.assertEqual(number_of_volumes, counted_volumes)
 
-    @test.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
+    @decorators.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     def test_attach_volume_shelved_or_offload_server(self):
@@ -269,7 +269,7 @@
         # case of shelved_offloaded.
         self.assertIsNotNone(volume_attachment['device'])
 
-    @test.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
+    @decorators.idempotent_id('b54e86dd-a070-49c4-9c07-59ae6dae15aa')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
     def test_detach_volume_shelved_or_offload_server(self):
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index 1f18bfe..acab4b1 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -14,6 +14,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -30,7 +31,7 @@
             raise cls.skipException(skip_msg)
 
     @test.related_bug('1630783', status_code=500)
-    @test.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
+    @decorators.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
     def test_delete_attached_volume(self):
         server = self.create_test_server(wait_until='ACTIVE')
         volume = self.create_volume()
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index 01718cc..3d5d23b 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -19,7 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 
 CONF = config.CONF
@@ -40,7 +40,7 @@
         cls.volumes_client = cls.volumes_extensions_client
         cls.snapshots_client = cls.snapshots_extensions_client
 
-    @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
+    @decorators.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):
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index 7549d4a..63c247e 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -19,7 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 
 CONF = config.CONF
@@ -39,7 +39,7 @@
         super(VolumesGetTestJSON, cls).setup_clients()
         cls.client = cls.volumes_extensions_client
 
-    @test.idempotent_id('f10f25eb-9775-4d9d-9cbe-1cf54dae9d5f')
+    @decorators.idempotent_id('f10f25eb-9775-4d9d-9cbe-1cf54dae9d5f')
     def test_volume_create_get_delete(self):
         # CREATE, GET, DELETE Volume
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index e4e625b..dd9d408 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -13,14 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
-
 from tempest.api.compute import base
 from tempest import config
-from tempest import test
+from tempest.lib import decorators
 
 CONF = config.CONF
-LOG = logging.getLogger(__name__)
 
 
 class VolumesTestJSON(base.BaseV2ComputeTest):
@@ -48,14 +45,14 @@
         # Create 3 Volumes
         cls.volume_list = []
         cls.volume_id_list = []
-        for i in range(3):
+        for _ in range(3):
             metadata = {'Type': 'work'}
             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')
+    @decorators.idempotent_id('bc2dd1a0-15af-48e5-9990-f2e75a48325d')
     def test_volume_list(self):
         # Should return the list of Volumes
         # Fetch all Volumes
@@ -70,7 +67,7 @@
                          ', '.join(m_vol['displayName']
                                    for m_vol in missing_volumes))
 
-    @test.idempotent_id('bad0567a-5a4f-420b-851e-780b55bb867c')
+    @decorators.idempotent_id('bad0567a-5a4f-420b-851e-780b55bb867c')
     def test_volume_list_with_details(self):
         # Should return the list of Volumes with details
         # Fetch all Volumes
@@ -85,7 +82,7 @@
                          ', '.join(m_vol['displayName']
                                    for m_vol in missing_volumes))
 
-    @test.idempotent_id('1048ed81-2baf-487a-b284-c0622b86e7b8')
+    @decorators.idempotent_id('1048ed81-2baf-487a-b284-c0622b86e7b8')
     def test_volume_list_param_limit(self):
         # Return the list of volumes based on limit set
         params = {'limit': 2}
@@ -94,7 +91,7 @@
         self.assertEqual(len(fetched_vol_list), params['limit'],
                          "Failed to list volumes by limit set")
 
-    @test.idempotent_id('33985568-4965-49d5-9bcc-0aa007ca5b7a')
+    @decorators.idempotent_id('33985568-4965-49d5-9bcc-0aa007ca5b7a')
     def test_volume_list_with_detail_param_limit(self):
         # Return the list of volumes with details based on limit set.
         params = {'limit': 2}
@@ -104,7 +101,7 @@
         self.assertEqual(len(fetched_vol_list), params['limit'],
                          "Failed to list volume details by limit set")
 
-    @test.idempotent_id('51c22651-a074-4ea7-af0b-094f9331303e')
+    @decorators.idempotent_id('51c22651-a074-4ea7-af0b-094f9331303e')
     def test_volume_list_param_offset_and_limit(self):
         # Return the list of volumes based on offset and limit set.
         # get all volumes list
@@ -121,7 +118,7 @@
                              all_vol_list[index + params['offset']]['id'],
                              "Failed to list volumes by offset and limit")
 
-    @test.idempotent_id('06b6abc4-3f10-48e9-a7a1-3facc98f03e5')
+    @decorators.idempotent_id('06b6abc4-3f10-48e9-a7a1-3facc98f03e5')
     def test_volume_list_with_detail_param_offset_and_limit(self):
         # Return the list of volumes details based on offset and limit set.
         # get all volumes list
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index c4041cb..2ad8631 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -16,6 +16,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -37,7 +38,7 @@
         cls.client = cls.volumes_extensions_client
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('c03ea686-905b-41a2-8748-9635154b7c57')
+    @decorators.idempotent_id('c03ea686-905b-41a2-8748-9635154b7c57')
     def test_volume_get_nonexistent_volume_id(self):
         # Negative: Should not be able to get details of nonexistent volume
         # Creating a nonexistent volume id
@@ -46,7 +47,7 @@
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('54a34226-d910-4b00-9ef8-8683e6c55846')
+    @decorators.idempotent_id('54a34226-d910-4b00-9ef8-8683e6c55846')
     def test_volume_delete_nonexistent_volume_id(self):
         # Negative: Should not be able to delete nonexistent Volume
         # Creating nonexistent volume id
@@ -55,7 +56,7 @@
                           data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('5125ae14-152b-40a7-b3c5-eae15e9022ef')
+    @decorators.idempotent_id('5125ae14-152b-40a7-b3c5-eae15e9022ef')
     def test_create_volume_with_invalid_size(self):
         # Negative: Should not be able to create volume with invalid size
         # in request
@@ -65,7 +66,7 @@
                           size='#$%', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
+    @decorators.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
     def test_create_volume_without_passing_size(self):
         # Negative: Should not be able to create volume without passing size
         # in request
@@ -75,7 +76,7 @@
                           size='', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('8cce995e-0a83-479a-b94d-e1e40b8a09d1')
+    @decorators.idempotent_id('8cce995e-0a83-479a-b94d-e1e40b8a09d1')
     def test_create_volume_with_size_zero(self):
         # Negative: Should not be able to create volume with size zero
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
@@ -84,21 +85,22 @@
                           size='0', display_name=v_name, metadata=metadata)
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('62bab09a-4c03-4617-8cca-8572bc94af9b')
+    @decorators.idempotent_id('62bab09a-4c03-4617-8cca-8572bc94af9b')
     def test_get_volume_without_passing_volume_id(self):
         # Negative: Should not be able to get volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound, self.client.show_volume, '')
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('62972737-124b-4513-b6cf-2f019f178494')
+    @decorators.idempotent_id('62972737-124b-4513-b6cf-2f019f178494')
     def test_delete_invalid_volume_id(self):
         # Negative: Should not be able to delete volume when invalid ID is
         # passed
         self.assertRaises(lib_exc.NotFound,
-                          self.client.delete_volume, '!@#$%^&*()')
+                          self.client.delete_volume,
+                          data_utils.rand_name('invalid'))
 
     @test.attr(type=['negative'])
-    @test.idempotent_id('0d1417c5-4ae8-4c2c-adc5-5f0b864253e5')
+    @decorators.idempotent_id('0d1417c5-4ae8-4c2c-adc5-5f0b864253e5')
     def test_delete_volume_without_passing_volume_id(self):
         # Negative: Should not be able to delete volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound, self.client.delete_volume, '')
diff --git a/tempest/api/identity/admin/v2/test_endpoints.py b/tempest/api/identity/admin/v2/test_endpoints.py
index 651a316..0da579c 100644
--- a/tempest/api/identity/admin/v2/test_endpoints.py
+++ b/tempest/api/identity/admin/v2/test_endpoints.py
@@ -34,7 +34,7 @@
         cls.service_ids.append(cls.service_id)
         # Create endpoints so as to use for LIST and GET test cases
         cls.setup_endpoints = list()
-        for i in range(2):
+        for _ in range(2):
             region = data_utils.rand_name('region')
             url = data_utils.rand_url()
             endpoint = cls.endpoints_client.create_endpoint(
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index a0d8748..d4fe32d 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -31,7 +31,7 @@
         u_desc = '%s description' % u_name
         u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_password()
-        for i in range(2):
+        for _ in range(2):
             cls.project = cls.projects_client.create_project(
                 data_utils.rand_name('project'),
                 description=data_utils.rand_name('project-desc'))['project']
@@ -92,7 +92,7 @@
         created_cred_ids = list()
         fetched_cred_ids = list()
 
-        for i in range(2):
+        for _ in range(2):
             blob = '{"access": "%s", "secret": "%s"}' % (
                 data_utils.rand_name('Access'), data_utils.rand_name('Secret'))
             cred = self.creds_client.create_credential(
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 655e4ef..ef450a2 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -40,7 +40,7 @@
         cls.service_ids.append(cls.service_id)
         # Create endpoints so as to use for LIST and GET test cases
         cls.setup_endpoints = list()
-        for i in range(2):
+        for _ in range(2):
             region = data_utils.rand_name('region')
             url = data_utils.rand_url()
             interface = 'public'
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 3cbcc1f..34b4468 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -80,7 +80,7 @@
         self.addCleanup(self.groups_client.delete_group, group['id'])
         # add user into group
         users = []
-        for i in range(3):
+        for _ in range(3):
             name = data_utils.rand_name('User')
             password = data_utils.rand_password()
             user = self.users_client.create_user(name=name,
@@ -110,7 +110,7 @@
         self.addCleanup(self.users_client.delete_user, user['id'])
         # create two groups, and add user into them
         groups = []
-        for i in range(2):
+        for _ in range(2):
             name = data_utils.rand_name('Group')
             group = self.groups_client.create_group(
                 name=name, domain_id=self.domain['id'])['group']
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index 95894a6..b5ea90d 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -30,7 +30,7 @@
     def resource_setup(cls):
         super(RegionsTestJSON, cls).resource_setup()
         cls.setup_regions = list()
-        for i in range(2):
+        for _ in range(2):
             r_description = data_utils.rand_name('description')
             region = cls.client.create_region(
                 description=r_description)['region']
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index fd2683e..54c62c7 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -15,11 +15,17 @@
 
 import time
 
+import testtools
+
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import test
 
 
+CONF = config.CONF
+
+
 class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
 
     @test.idempotent_id('b537d090-afb9-4519-b95d-270b0708e87e')
@@ -119,7 +125,7 @@
 
         user = self.users_client.show_user(user_body['id'])['user']
         role = self.roles_client.show_role(role_body['id'])['role']
-        for i in range(2):
+        for _ in range(2):
             # Creating project so as to assign role
             project_body = self.projects_client.create_project(
                 data_utils.rand_name('project'),
@@ -152,3 +158,30 @@
         user = self.setup_test_user()
         fetched_user = self.users_client.show_user(user['id'])['user']
         self.assertEqual(user['id'], fetched_user['id'])
+
+    @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
+                          'Security compliance not available.')
+    @test.idempotent_id('568cd46c-ee6c-4ab4-a33a-d3791931979e')
+    def test_password_history_not_enforced_in_admin_reset(self):
+        old_password = self.os.credentials.password
+        user_id = self.os.credentials.user_id
+
+        new_password = data_utils.rand_password()
+        self.users_client.update_user(user_id, password=new_password)
+        # To be safe, we add this cleanup to restore the original password in
+        # case something goes wrong before it is restored later.
+        self.addCleanup(
+            self.users_client.update_user, user_id, password=old_password)
+
+        # Check authorization with new password
+        self.token.auth(user_id=user_id, password=new_password)
+
+        if CONF.identity.user_unique_last_password_count > 1:
+            # The password history is not enforced via the admin reset route.
+            # We can set the same password.
+            self.users_client.update_user(user_id, password=new_password)
+
+        # Restore original password
+        self.users_client.update_user(user_id, password=old_password)
+        # Check authorization with old password
+        self.token.auth(user_id=user_id, password=old_password)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 14bf4f8..9515788 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -105,6 +105,15 @@
 
     credentials = ['primary', 'admin']
 
+    # NOTE(andreaf) Identity tests work with credentials, so it is safer
+    # for them to always use disposable credentials. Forcing dynamic creds
+    # on regular identity tests would be however to restrictive, since it
+    # would prevent any identity test from being executed against clouds where
+    # admin credentials are not available.
+    # Since All admin tests require admin credentials to be
+    # executed, so this will not impact the ability to execute tests.
+    force_tenant_isolation = True
+
     @classmethod
     def setup_clients(cls):
         super(BaseIdentityV2AdminTest, cls).setup_clients()
@@ -165,6 +174,15 @@
 
     credentials = ['primary', 'admin']
 
+    # NOTE(andreaf) Identity tests work with credentials, so it is safer
+    # for them to always use disposable credentials. Forcing dynamic creds
+    # on regular identity tests would be however to restrictive, since it
+    # would prevent any identity test from being executed against clouds where
+    # admin credentials are not available.
+    # Since All admin tests require admin credentials to be
+    # executed, so this will not impact the ability to execute tests.
+    force_tenant_isolation = True
+
     @classmethod
     def setup_clients(cls):
         super(BaseIdentityV3AdminTest, cls).setup_clients()
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 33d212c..06730f8 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -16,11 +16,15 @@
 import time
 
 from tempest.api.identity 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 IdentityUsersTest(base.BaseIdentityV2Test):
 
     @classmethod
@@ -31,36 +35,10 @@
         cls.password = cls.creds.password
         cls.tenant_name = cls.creds.tenant_name
 
-    @test.idempotent_id('165859c9-277f-4124-9479-a7d1627b0ca7')
-    def test_user_update_own_password(self):
-
-        def _restore_password(client, user_id, old_pass, new_pass):
-            # Reset auth to get a new token with the new password
-            client.auth_provider.clear_auth()
-            client.auth_provider.credentials.password = new_pass
-            client.update_user_own_password(user_id, password=old_pass,
-                                            original_password=new_pass)
-            # Reset auth again to verify the password restore does work.
-            # Clear auth restores the original credentials and deletes
-            # cached auth data
-            client.auth_provider.clear_auth()
-            # NOTE(lbragstad): Fernet tokens are not subsecond aware and
-            # Keystone should only be precise to the second. Sleep to ensure we
-            # are passing the second boundary before attempting to
-            # authenticate.
-            time.sleep(1)
-            client.auth_provider.set_auth()
-
-        old_pass = self.creds.password
-        new_pass = data_utils.rand_password()
-        user_id = self.creds.user_id
-        # to change password back. important for allow_tenant_isolation = false
-        self.addCleanup(_restore_password, self.non_admin_users_client,
-                        user_id, old_pass=old_pass, new_pass=new_pass)
-
-        # user updates own password
+    def _update_password(self, user_id, original_password, password):
         self.non_admin_users_client.update_user_own_password(
-            user_id, password=new_pass, original_password=old_pass)
+            user_id, password=password, original_password=original_password)
+
         # NOTE(morganfainberg): Fernet tokens are not subsecond aware and
         # Keystone should only be precise to the second. Sleep to ensure
         # we are passing the second boundary.
@@ -68,13 +46,55 @@
 
         # check authorization with new password
         self.non_admin_token_client.auth(self.username,
-                                         new_pass,
+                                         password,
                                          self.tenant_name)
 
+        # Reset auth to get a new token with the new password
+        self.non_admin_users_client.auth_provider.clear_auth()
+        self.non_admin_users_client.auth_provider.credentials.password = (
+            password)
+
+    def _restore_password(self, user_id, old_pass, new_pass):
+        if CONF.identity_feature_enabled.security_compliance:
+            # First we need to clear the password history
+            unique_count = CONF.identity.user_unique_last_password_count
+            for _ in range(unique_count):
+                random_pass = data_utils.rand_password()
+                self._update_password(
+                    user_id, original_password=new_pass, password=random_pass)
+                new_pass = random_pass
+
+        self._update_password(
+            user_id, original_password=new_pass, password=old_pass)
+        # Reset auth again to verify the password restore does work.
+        # Clear auth restores the original credentials and deletes
+        # cached auth data
+        self.non_admin_users_client.auth_provider.clear_auth()
+        # NOTE(lbragstad): Fernet tokens are not subsecond aware and
+        # Keystone should only be precise to the second. Sleep to ensure we
+        # are passing the second boundary before attempting to
+        # authenticate.
+        time.sleep(1)
+        self.non_admin_users_client.auth_provider.set_auth()
+
+    @test.idempotent_id('165859c9-277f-4124-9479-a7d1627b0ca7')
+    def test_user_update_own_password(self):
+        old_pass = self.creds.password
+        old_token = self.non_admin_users_client.token
+        new_pass = data_utils.rand_password()
+        user_id = self.creds.user_id
+
+        # to change password back. important for allow_tenant_isolation = false
+        self.addCleanup(self._restore_password, user_id, old_pass, new_pass)
+
+        # user updates own password
+        self._update_password(
+            user_id, original_password=old_pass, password=new_pass)
+
         # authorize with old token should lead to Unauthorized
         self.assertRaises(exceptions.Unauthorized,
                           self.non_admin_token_client.auth_token,
-                          self.non_admin_users_client.token)
+                          old_token)
 
         # authorize with old password should lead to Unauthorized
         self.assertRaises(exceptions.Unauthorized,
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index 1a38f3a..9592cb9 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -15,12 +15,18 @@
 
 import time
 
+import testtools
+
 from tempest.api.identity 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 IdentityV3UsersTest(base.BaseIdentityV3Test):
 
     @classmethod
@@ -31,36 +37,11 @@
         cls.username = cls.creds.username
         cls.password = cls.creds.password
 
-    @test.idempotent_id('ad71bd23-12ad-426b-bb8b-195d2b635f27')
-    def test_user_update_own_password(self):
-
-        def _restore_password(client, user_id, old_pass, new_pass):
-            # Reset auth to get a new token with the new password
-            client.auth_provider.clear_auth()
-            client.auth_provider.credentials.password = new_pass
-            client.update_user_password(user_id, password=old_pass,
-                                        original_password=new_pass)
-            # Reset auth again to verify the password restore does work.
-            # Clear auth restores the original credentials and deletes
-            # cached auth data
-            client.auth_provider.clear_auth()
-            # NOTE(lbragstad): Fernet tokens are not subsecond aware and
-            # Keystone should only be precise to the second. Sleep to ensure we
-            # are passing the second boundary before attempting to
-            # authenticate.
-            time.sleep(1)
-            client.auth_provider.set_auth()
-
-        old_pass = self.creds.password
-        new_pass = data_utils.rand_password()
-        user_id = self.creds.user_id
-        # to change password back. important for allow_tenant_isolation = false
-        self.addCleanup(_restore_password, self.non_admin_users_client,
-                        user_id, old_pass=old_pass, new_pass=new_pass)
-
-        # user updates own password
+    def _update_password(self, original_password, password):
         self.non_admin_users_client.update_user_password(
-            user_id, password=new_pass, original_password=old_pass)
+            self.user_id,
+            password=password,
+            original_password=original_password)
 
         # NOTE(morganfainberg): Fernet tokens are not subsecond aware and
         # Keystone should only be precise to the second. Sleep to ensure
@@ -68,15 +49,112 @@
         time.sleep(1)
 
         # check authorization with new password
-        self.non_admin_token.auth(user_id=self.user_id, password=new_pass)
+        self.non_admin_token.auth(user_id=self.user_id, password=password)
+
+        # Reset auth to get a new token with the new password
+        self.non_admin_users_client.auth_provider.clear_auth()
+        self.non_admin_users_client.auth_provider.credentials.password = (
+            password)
+
+    def _restore_password(self, old_pass, new_pass):
+        if CONF.identity_feature_enabled.security_compliance:
+            # First we need to clear the password history
+            unique_count = CONF.identity.user_unique_last_password_count
+            for _ in range(unique_count):
+                random_pass = data_utils.rand_password()
+                self._update_password(
+                    original_password=new_pass, password=random_pass)
+                new_pass = random_pass
+
+        self._update_password(original_password=new_pass, password=old_pass)
+        # Reset auth again to verify the password restore does work.
+        # Clear auth restores the original credentials and deletes
+        # cached auth data
+        self.non_admin_users_client.auth_provider.clear_auth()
+        # NOTE(lbragstad): Fernet tokens are not subsecond aware and
+        # Keystone should only be precise to the second. Sleep to ensure we
+        # are passing the second boundary before attempting to
+        # authenticate.
+        time.sleep(1)
+        self.non_admin_users_client.auth_provider.set_auth()
+
+    @test.idempotent_id('ad71bd23-12ad-426b-bb8b-195d2b635f27')
+    def test_user_update_own_password(self):
+        old_pass = self.creds.password
+        old_token = self.non_admin_client.token
+        new_pass = data_utils.rand_password()
+
+        # to change password back. important for allow_tenant_isolation = false
+        self.addCleanup(self._restore_password, old_pass, new_pass)
+
+        # user updates own password
+        self._update_password(original_password=old_pass, password=new_pass)
 
         # authorize with old token should lead to IdentityError (404 code)
         self.assertRaises(exceptions.IdentityError,
                           self.non_admin_token.auth,
-                          token=self.non_admin_client.token)
+                          token=old_token)
 
         # authorize with old password should lead to Unauthorized
         self.assertRaises(exceptions.Unauthorized,
                           self.non_admin_token.auth,
                           user_id=self.user_id,
                           password=old_pass)
+
+    @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
+                          'Security compliance not available.')
+    @test.idempotent_id('941784ee-5342-4571-959b-b80dd2cea516')
+    def test_password_history_check_self_service_api(self):
+        old_pass = self.creds.password
+        new_pass1 = data_utils.rand_password()
+        new_pass2 = data_utils.rand_password()
+
+        self.addCleanup(self._restore_password, old_pass, new_pass2)
+
+        # Update password
+        self._update_password(original_password=old_pass, password=new_pass1)
+
+        if CONF.identity.user_unique_last_password_count > 1:
+            # Can not reuse a previously set password
+            self.assertRaises(exceptions.BadRequest,
+                              self.non_admin_users_client.update_user_password,
+                              self.user_id,
+                              password=new_pass1,
+                              original_password=new_pass1)
+
+            self.assertRaises(exceptions.BadRequest,
+                              self.non_admin_users_client.update_user_password,
+                              self.user_id,
+                              password=old_pass,
+                              original_password=new_pass1)
+
+        # A different password can be set
+        self._update_password(original_password=new_pass1, password=new_pass2)
+
+    @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
+                          'Security compliance not available.')
+    @test.idempotent_id('a7ad8bbf-2cff-4520-8c1d-96332e151658')
+    def test_user_account_lockout(self):
+        password = self.creds.password
+
+        # First, we login using the correct credentials
+        self.non_admin_token.auth(user_id=self.user_id, password=password)
+
+        # Lock user account by using the wrong password to login
+        bad_password = data_utils.rand_password()
+        for _ in range(CONF.identity.user_lockout_failure_attempts):
+            self.assertRaises(exceptions.Unauthorized,
+                              self.non_admin_token.auth,
+                              user_id=self.user_id,
+                              password=bad_password)
+
+        # The user account must be locked, so now it is not possible to login
+        # even using the correct password
+        self.assertRaises(exceptions.Unauthorized,
+                          self.non_admin_token.auth,
+                          user_id=self.user_id,
+                          password=password)
+
+        # If we wait the required time, the user account will be unlocked
+        time.sleep(CONF.identity.user_lockout_duration + 1)
+        self.non_admin_token.auth(user_id=self.user_id, password=password)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 812c436..cd4f820 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -142,6 +142,8 @@
         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.namespace_objects_client = cls.os.namespace_objects_client
+        cls.namespace_tags_client = cls.os.namespace_tags_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_image_members.py b/tempest/api/image/v1/test_image_members.py
index 50f0926..9c211ef 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -14,6 +14,7 @@
 
 
 from tempest.api.image import base
+from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 
@@ -54,3 +55,5 @@
         body = self.image_member_client.list_image_members(image_id)
         members = body['members']
         self.assertEqual(0, len(members), str(members))
+        self.assertRaises(
+            lib_exc.NotFound, self.alt_img_cli.show_image, image_id)
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 9fbdcd7..b22ceed 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -30,13 +30,23 @@
     a_formats = ['ami', 'ari', 'aki']
 
     container_format = CONF.image.container_formats[0]
-    disk_format = CONF.image.disk_formats[0]
 
-    if container_format in a_formats and container_format != disk_format:
-        msg = ("The container format and the disk format don't match. "
-               "Container format: %(container)s, Disk format: %(disk)s." %
-               {'container': container_format, 'disk': disk_format})
-        raise exceptions.InvalidConfiguration(message=msg)
+    # In v1, If container_format is one of ['ami', 'ari', 'aki'], then
+    # disk_format must be same with container_format.
+    # If they are of different item sequence in tempest.conf, such as:
+    #     container_formats = ami,ari,aki,bare
+    #     disk_formats = ari,ami,aki,vhd
+    # we can select one in disk_format list that is same with container_format.
+    if container_format in a_formats:
+        if container_format in CONF.image.disk_formats:
+            disk_format = container_format
+        else:
+            msg = ("The container format and the disk format don't match. "
+                   "Container format: %(container)s, Disk format: %(disk)s." %
+                   {'container': container_format, 'disk': disk_format})
+            raise exceptions.InvalidConfiguration(msg)
+    else:
+        disk_format = CONF.image.disk_formats[0]
 
     return container_format, disk_format
 
@@ -54,7 +64,6 @@
                                   disk_format=disk_format,
                                   is_public=False,
                                   properties=properties)
-        self.assertIn('id', image)
         self.assertEqual('New Name', image.get('name'))
         self.assertFalse(image.get('is_public'))
         self.assertEqual('queued', image.get('status'))
@@ -77,7 +86,6 @@
                                  location=CONF.image.http_image,
                                  properties={'key1': 'value1',
                                              'key2': 'value2'})
-        self.assertIn('id', body)
         self.assertEqual('New Remote Image', body.get('name'))
         self.assertFalse(body.get('is_public'))
         self.assertEqual('active', body.get('status'))
@@ -92,7 +100,6 @@
                                   container_format=container_format,
                                   disk_format=disk_format, is_public=False,
                                   copy_from=CONF.image.http_image)
-        self.assertIn('id', image)
         self.assertEqual('New Http Image', image.get('name'))
         self.assertFalse(image.get('is_public'))
         waiters.wait_for_image_status(self.client, image['id'], 'active')
@@ -109,7 +116,6 @@
                                  is_public=False,
                                  min_ram=40,
                                  properties=properties)
-        self.assertIn('id', body)
         self.assertEqual('New_image_with_min_ram', body.get('name'))
         self.assertFalse(body.get('is_public'))
         self.assertEqual('queued', body.get('status'))
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index d8f103a..3493cc2 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -15,6 +15,7 @@
 
 
 from tempest.api.image import base
+from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -44,7 +45,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)
 
@@ -58,9 +59,9 @@
     @test.idempotent_id('950e5054-a3c7-4dee-ada5-e576f1087abd')
     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('4ed757cd-450c-44b1-9fd1-c819748c650d')
@@ -70,7 +71,8 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a4a448ab-3db2-4d2d-b9b2-6a1271241dfe')
-    def test_delete_image_id_is_over_35_character_limit(self):
+    def test_delete_image_id_over_character_limit(self):
         # Return an error while trying to delete image with id over limit
+        overlimit_image_id = data_utils.rand_uuid() + "1"
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
-                          '11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
+                          overlimit_image_id)
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 7b9244b..36dc6c3 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -49,7 +49,6 @@
                                   disk_format=disk_format,
                                   visibility='private',
                                   ramdisk_id=uuid)
-        self.assertIn('id', image)
         self.assertIn('name', image)
         self.assertEqual(image_name, image['name'])
         self.assertIn('visibility', image)
@@ -127,11 +126,12 @@
         self.assertEqual(new_image_name, body['name'])
 
 
-class ListImagesTest(base.BaseV2ImageTest):
+class ListUserImagesTest(base.BaseV2ImageTest):
+    """Here we test the listing of image information"""
 
     @classmethod
     def resource_setup(cls):
-        super(ListImagesTest, cls).resource_setup()
+        super(ListUserImagesTest, cls).resource_setup()
         # We add a few images here to test the listing functionality of
         # the images API
         container_fmts = CONF.image.container_formats
@@ -167,10 +167,6 @@
 
         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
@@ -324,7 +320,7 @@
         self.assertEqual("images", body['name'])
 
 
-class ListSharedImagesTest(ListImagesTest):
+class ListSharedImagesTest(base.BaseV2ImageTest):
     """Here we test the listing of a shared image information"""
 
     credentials = ['primary', 'alt']
@@ -337,17 +333,22 @@
 
     @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
+        # Create an image to be shared using default visibility
+        image_file = six.BytesIO(data_utils.random_bytes(2048))
+        container_format = CONF.image.container_formats[0]
+        disk_format = CONF.image.disk_formats[0]
+        image = self.create_image(container_format=container_format,
+                                  disk_format=disk_format)
+        self.client.store_image_file(image['id'], data=image_file)
+
+        # Share the image 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']
+            image_id=image['id'], member=self.alt_img_client.tenant_id)
+
         # 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'])
+        self.assertEqual(image['id'], fetched_images[0]['id'])
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_objects.py b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
new file mode 100644
index 0000000..95d1521
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
@@ -0,0 +1,73 @@
+#    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.lib.common.utils import test_utils
+from tempest import test
+
+
+class MetadataNamespaceObjectsTest(base.BaseV2ImageTest):
+    """Test the Metadata definition namespace objects basic functionality"""
+
+    def _create_namespace_object(self, namespace):
+        object_name = data_utils.rand_name(self.__class__.__name__ + '-object')
+        namespace_object = self.namespace_objects_client.\
+            create_namespace_object(namespace['namespace'], name=object_name)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.namespace_objects_client.delete_namespace_object,
+                        namespace['namespace'], object_name)
+        return namespace_object
+
+    @test.idempotent_id('b1a3775e-3b5c-4f6a-a3b4-1ba3574ae718')
+    def test_create_update_delete_meta_namespace_objects(self):
+        # Create a namespace
+        namespace = self.create_namespace()
+        # Create a namespace object
+        body = self._create_namespace_object(namespace)
+        # Update a namespace object
+        up_object_name = data_utils.rand_name('update-object')
+        body = self.namespace_objects_client.update_namespace_object(
+            namespace['namespace'], body['name'],
+            name=up_object_name)
+        self.assertEqual(up_object_name, body['name'])
+        # Delete a namespace object
+        self.namespace_objects_client.delete_namespace_object(
+            namespace['namespace'], up_object_name)
+        # List namespace objects and validate deletion
+        namespace_objects = [
+            namespace_object['name'] for namespace_object in
+            self.namespace_objects_client.list_namespace_objects(
+                namespace['namespace'])['objects']]
+        self.assertNotIn(up_object_name, namespace_objects)
+
+    @test.idempotent_id('a2a3615e-3b5c-3f6a-a2b1-1ba3574ae738')
+    def test_list_meta_namespace_objects(self):
+        # Create a namespace object
+        namespace = self.create_namespace()
+        meta_namespace_object = self._create_namespace_object(namespace)
+        # List namespace objects
+        namespace_objects = [
+            namespace_object['name'] for namespace_object in
+            self.namespace_objects_client.list_namespace_objects(
+                namespace['namespace'])['objects']]
+        self.assertIn(meta_namespace_object['name'], namespace_objects)
+
+    @test.idempotent_id('b1a3674e-3b4c-3f6a-a3b4-1ba3573ca768')
+    def test_show_meta_namespace_objects(self):
+        # Create a namespace object
+        namespace = self.create_namespace()
+        namespace_object = self._create_namespace_object(namespace)
+        # Show a namespace object
+        body = self.namespace_objects_client.show_namespace_object(
+            namespace['namespace'], namespace_object['name'])
+        self.assertEqual(namespace_object['name'], body['name'])
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_tags.py b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
new file mode 100644
index 0000000..186d9c8
--- /dev/null
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
@@ -0,0 +1,90 @@
+#    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.lib.common.utils import test_utils
+from tempest import test
+
+
+class MetadataNamespaceTagsTest(base.BaseV2ImageTest):
+    """Test the Metadata definition namespace tags basic functionality"""
+
+    tags = [
+        {
+            "name": "sample-tag1"
+        },
+        {
+            "name": "sample-tag2"
+        },
+        {
+            "name": "sample-tag3"
+        }
+    ]
+    tag_list = ["sample-tag1", "sample-tag2", "sample-tag3"]
+
+    def _create_namespace_tags(self, namespace):
+        # Create a namespace
+        namespace_tags = self.namespace_tags_client.create_namespace_tags(
+            namespace['namespace'], tags=self.tags)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.namespace_tags_client.delete_namespace_tags,
+                        namespace['namespace'])
+        return namespace_tags
+
+    @test.idempotent_id('a2a3765e-3a6d-4f6d-a3a7-3cc3476aa876')
+    def test_create_list_delete_namespace_tags(self):
+        # Create a namespace
+        namespace = self.create_namespace()
+        self._create_namespace_tags(namespace)
+        # List namespace tags
+        body = self.namespace_tags_client.list_namespace_tags(
+            namespace['namespace'])
+        self.assertTrue(3, len(body['tags']))
+        self.assertIn(body['tags'][0]['name'], self.tag_list)
+        self.assertIn(body['tags'][1]['name'], self.tag_list)
+        self.assertIn(body['tags'][2]['name'], self.tag_list)
+        # Delete all tag definitions
+        self.namespace_tags_client.delete_namespace_tags(
+            namespace['namespace'])
+        body = self.namespace_tags_client.list_namespace_tags(
+            namespace['namespace'])
+        self.assertEqual([], body['tags'])
+
+    @test.idempotent_id('a2a3765e-1a2c-3f6d-a3a7-3cc3466ab875')
+    def test_create_update_delete_tag(self):
+        # Create a namespace
+        namespace = self.create_namespace()
+        self._create_namespace_tags(namespace)
+        # Create a tag
+        tag_name = data_utils.rand_name('tag_name')
+        self.namespace_tags_client.create_namespace_tag(
+            namespace=namespace['namespace'], tag_name=tag_name)
+
+        body = self.namespace_tags_client.show_namespace_tag(
+            namespace['namespace'], tag_name)
+        self.assertEqual(tag_name, body['name'])
+        # Update tag definition
+        update_tag_definition = data_utils.rand_name('update-tag')
+        body = self.namespace_tags_client.update_namespace_tag(
+            namespace['namespace'], tag_name=tag_name,
+            name=update_tag_definition)
+        self.assertEqual(update_tag_definition, body['name'])
+        # Delete tag definition
+        self.namespace_tags_client.delete_namespace_tag(
+            namespace['namespace'], update_tag_definition)
+        # List namespace tags and validate deletion
+        namespace_tags = [
+            namespace_tag['name'] for namespace_tag in
+            self.namespace_tags_client.list_namespace_tags(
+                namespace['namespace'])['tags']]
+        self.assertNotIn(update_tag_definition, namespace_tags)
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index c256b5b..beb6ce6 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -57,8 +57,7 @@
         # Try to create a third network while the quota is two
         with self.assertRaisesRegex(
                 lib_exc.Conflict,
-                "An object with that identifier already exists\\n" +
-                "Details.*Quota exceeded for resources: \['network'\].*"):
+                "Quota exceeded for resources: \['network'\].*"):
             n3 = self.networks_client.create_network()
             self.addCleanup(self.networks_client.delete_network,
                             n3['network']['id'])
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 978fb8f..8695ebd 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
-
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
@@ -57,7 +55,7 @@
             project_id, **new_quotas)['quota']
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.admin_quotas_client.reset_quotas, project_id)
-        for key, value in six.iteritems(new_quotas):
+        for key, value in new_quotas.items():
             self.assertEqual(value, quota_set[key])
 
         # Confirm our project is listed among projects with non default quotas
@@ -71,7 +69,7 @@
         # Confirm from API quotas were changed as requested for project
         quota_set = self.admin_quotas_client.show_quotas(project_id)
         quota_set = quota_set['quota']
-        for key, value in six.iteritems(new_quotas):
+        for key, value in new_quotas.items():
             self.assertEqual(value, quota_set[key])
 
         # Reset quotas to default and confirm
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index c2c42bb..132e23e 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -108,10 +108,10 @@
             # Not all classes in the hierarchy have the client class variable
             if len(cls.metering_label_rules) > 0:
                 label_rules_client = cls.admin_metering_label_rules_client
-            for metering_label_rule in cls.metering_label_rules:
-                test_utils.call_and_ignore_notfound_exc(
-                    label_rules_client.delete_metering_label_rule,
-                    metering_label_rule['id'])
+                for metering_label_rule in cls.metering_label_rules:
+                    test_utils.call_and_ignore_notfound_exc(
+                        label_rules_client.delete_metering_label_rule,
+                        metering_label_rule['id'])
             # Clean up metering labels
             for metering_label in cls.metering_labels:
                 test_utils.call_and_ignore_notfound_exc(
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 84c48ec..3c96a93 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -16,8 +16,6 @@
 import netaddr
 import random
 
-import six
-
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest.common.utils import net_info
@@ -126,7 +124,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
+            kwargs = dict((k, v) for k, v in kwargs.items() if v)
             real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
             self._clean_network()
             self.assertEqual(eui_ip, real_ip,
@@ -269,7 +267,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
+            kwargs = dict((k, v) for k, v in kwargs.items() if v)
             subnet = self.create_subnet(self.network, **kwargs)
             port = self.create_port(self.network)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
@@ -291,7 +289,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
+            kwargs = dict((k, v) for k, v in kwargs.items() if v)
             subnet = self.create_subnet(self.network, **kwargs)
             ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
                                        subnet["allocation_pools"][0]["end"])
@@ -340,7 +338,7 @@
                              {'subnet_id': subnet['id'],
                               'ip_address': ip}])
         self.assertRaisesRegex(lib_exc.Conflict,
-                               "object with that identifier already exists",
+                               "IpAddressAlreadyAllocated|IpAddressInUse",
                                self.create_port,
                                self.network,
                                fixed_ips=[{'subnet_id': subnet['id'],
@@ -364,7 +362,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = dict((k, v) for k, v in six.iteritems(kwargs) if v)
+            kwargs = dict((k, v) for k, v in kwargs.items() if v)
             subnet, port = self._create_subnet_router(kwargs)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
             self._clean_network()
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index acac22b..8e2f3f6 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -130,7 +130,7 @@
                                     **kwargs)
         compare_args_full = dict(gateway_ip=gateway, cidr=cidr,
                                  mask_bits=mask_bits, **kwargs)
-        compare_args = dict((k, v) for k, v in six.iteritems(compare_args_full)
+        compare_args = dict((k, v) for k, v in compare_args_full.items()
                             if v is not None)
 
         if 'dns_nameservers' in set(subnet).intersection(compare_args):
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 5b46088..e7153f0 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -108,7 +108,7 @@
         if ((address.version == 4 and address.prefixlen >= 30) or
            (address.version == 6 and address.prefixlen >= 126)):
             msg = ("Subnet %s isn't large enough for the test" % address.cidr)
-            raise exceptions.InvalidConfiguration(message=msg)
+            raise exceptions.InvalidConfiguration(msg)
         allocation_pools = {'allocation_pools': [{'start': str(address[2]),
                                                   'end': str(address[-2])}]}
         subnet = self.create_subnet(network, cidr=address,
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index f2170ad..101e4dd 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 import netaddr
-import six
 
 from tempest.api.network import base_routers as base
 from tempest.common.utils import data_utils
@@ -163,7 +162,7 @@
             self.assertIsNone(actual_ext_gw_info)
             return
         # Verify only keys passed in exp_ext_gw_info
-        for k, v in six.iteritems(exp_ext_gw_info):
+        for k, v in exp_ext_gw_info.items():
             self.assertEqual(v, actual_ext_gw_info[k])
 
     def _verify_gateway_port(self, router_id):
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 1031ab8..be01852 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
-
 from tempest.api.network import base_security_groups as base
 from tempest.common.utils import data_utils
 from tempest import config
@@ -62,7 +60,7 @@
                     'port_range_max': port_range_max,
                     'remote_group_id': remote_group_id,
                     'remote_ip_prefix': remote_ip_prefix}
-        for key, value in six.iteritems(expected):
+        for key, value in expected.items():
             self.assertEqual(value, sec_group_rule[key],
                              "Field %s of the created security group "
                              "rule does not match with %s." %
@@ -131,7 +129,7 @@
                 rule_create_body['security_group_rule']['id']
             )
             create_dict = rule_create_body['security_group_rule']
-            for key, value in six.iteritems(create_dict):
+            for key, value in create_dict.items():
                 self.assertEqual(value,
                                  show_rule_body['security_group_rule'][key],
                                  "%s does not match." % key)
diff --git a/tempest/api/network/test_service_providers.py b/tempest/api/network/test_service_providers.py
index 09fb5fe..be17b3e 100644
--- a/tempest/api/network/test_service_providers.py
+++ b/tempest/api/network/test_service_providers.py
@@ -10,6 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.network import base
 from tempest import test
 
@@ -17,6 +19,9 @@
 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)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index eb313d2..e0216fd 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -25,6 +25,38 @@
 CONF = config.CONF
 
 
+def delete_containers(containers, container_client, object_client):
+    """Remove containers and all objects in them.
+
+    The containers should be visible from the container_client given.
+    Will not throw any error if the containers don't exist.
+    Will not check that object and container deletions succeed.
+    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 containers: List of containers to be deleted
+    :param container_client: Client to be used to delete containers
+    :param object_client: Client to be used to delete objects
+    """
+    for cont in containers:
+        try:
+            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
+
+
 class BaseObjectTest(tempest.test.BaseTestCase):
 
     credentials = [['operator', CONF.object_storage.operator_role]]
@@ -89,7 +121,7 @@
         if object_name is None:
             object_name = data_utils.rand_name(name='TestObject')
         if data is None:
-            data = data_utils.arbitrary_string()
+            data = data_utils.random_bytes()
         cls.object_client.create_object(container_name,
                                         object_name,
                                         data,
@@ -98,42 +130,12 @@
         return object_name, data
 
     @classmethod
-    def delete_containers(cls, container_client=None,
-                          object_client=None):
-        """Remove containers and all objects in them.
-
-        The containers should be visible from the container_client given.
-        Will not throw any error if the containers don't exist.
-        Will not check that object and container deletions succeed.
-        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
-            'etc/tempest.conf')
-        :param object_client: if None, use cls.object_client
-        """
+    def delete_containers(cls, container_client=None, object_client=None):
         if container_client is None:
             container_client = cls.container_client
         if object_client is None:
             object_client = cls.object_client
-        for cont in cls.containers:
-            try:
-                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
+        delete_containers(cls.containers, container_client, object_client)
 
     def assertHeaders(self, resp, target, method):
         """Check the existence and the format of response headers"""
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index a75ed98..1eda49a 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -27,7 +27,10 @@
         self.containers = []
 
     def tearDown(self):
-        self.delete_containers()
+        # NOTE(andreaf) BulkTests needs to cleanup containers after each
+        # test is executed.
+        base.delete_containers(self.containers, self.container_client,
+                               self.object_client)
         super(BulkTest, self).tearDown()
 
     def _create_archive(self):
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index ffdd1de..e555fd9 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -26,17 +26,6 @@
     credentials = [['operator', CONF.object_storage.operator_role],
                    ['operator_alt', CONF.object_storage.operator_role]]
 
-    @classmethod
-    def setup_credentials(cls):
-        super(ObjectTestACLs, cls).setup_credentials()
-        cls.os = cls.os_roles_operator
-        cls.os_operator = cls.os_roles_operator_alt
-
-    @classmethod
-    def resource_setup(cls):
-        super(ObjectTestACLs, cls).resource_setup()
-        cls.test_auth_data = cls.os_operator.auth_provider.auth_data
-
     def setUp(self):
         super(ObjectTestACLs, self).setUp()
         self.container_name = self.create_container()
@@ -49,24 +38,26 @@
     def test_read_object_with_rights(self):
         # attempt to read object using authorized user
         # update X-Container-Read metadata ACL
-        tenant_name = self.os_operator.credentials.tenant_name
-        username = self.os_operator.credentials.username
+        tenant_name = self.os_roles_operator_alt.credentials.tenant_name
+        username = self.os_roles_operator_alt.credentials.username
         cont_headers = {'X-Container-Read': tenant_name + ':' + username}
-        resp_meta, body = self.container_client.update_container_metadata(
-            self.container_name, metadata=cont_headers,
-            metadata_prefix='')
+        resp_meta, body = self.os_roles_operator.container_client.\
+            update_container_metadata(
+                self.container_name, metadata=cont_headers,
+                metadata_prefix='')
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
         object_name = data_utils.rand_name(name='Object')
-        resp, _ = self.object_client.create_object(self.container_name,
-                                                   object_name, 'data')
+        resp, _ = self.os_roles_operator.object_client.create_object(
+            self.container_name, object_name, 'data')
         self.assertHeaders(resp, 'Object', 'PUT')
-        # Trying to read the object with rights
-        self.object_client.auth_provider.set_alt_auth_data(
+        # set alternative authentication data; cannot simply use the
+        # other object client.
+        self.os_roles_operator.object_client.auth_provider.set_alt_auth_data(
             request_part='headers',
-            auth_data=self.test_auth_data
-        )
-        resp, _ = self.object_client.get_object(
+            auth_data=self.os_roles_operator_alt.object_client.auth_provider.
+            auth_data)
+        resp, _ = self.os_roles_operator.object_client.get_object(
             self.container_name, object_name)
         self.assertHeaders(resp, 'Object', 'GET')
 
@@ -74,20 +65,23 @@
     def test_write_object_with_rights(self):
         # attempt to write object using authorized user
         # update X-Container-Write metadata ACL
-        tenant_name = self.os_operator.credentials.tenant_name
-        username = self.os_operator.credentials.username
+        tenant_name = self.os_roles_operator_alt.credentials.tenant_name
+        username = self.os_roles_operator_alt.credentials.username
         cont_headers = {'X-Container-Write': tenant_name + ':' + username}
-        resp_meta, body = self.container_client.update_container_metadata(
-            self.container_name, metadata=cont_headers,
-            metadata_prefix='')
+        resp_meta, body = self.os_roles_operator.container_client.\
+            update_container_metadata(self.container_name,
+                                      metadata=cont_headers,
+                                      metadata_prefix='')
         self.assertHeaders(resp_meta, 'Container', 'POST')
-        # Trying to write the object with rights
-        self.object_client.auth_provider.set_alt_auth_data(
+        # set alternative authentication data; cannot simply use the
+        # other object client.
+        self.os_roles_operator.object_client.auth_provider.set_alt_auth_data(
             request_part='headers',
-            auth_data=self.test_auth_data
-        )
+            auth_data=self.os_roles_operator_alt.object_client.auth_provider.
+            auth_data)
+        # Trying to write the object with rights
         object_name = data_utils.rand_name(name='Object')
-        resp, _ = self.object_client.create_object(
+        resp, _ = self.os_roles_operator.object_client.create_object(
             self.container_name,
             object_name, 'data', headers={})
         self.assertHeaders(resp, 'Object', 'PUT')
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 9ce1b18..e4476a1 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -133,7 +133,7 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.idempotent_id('4646ac2d-9bfb-4c7d-a3c5-0f527402b3df')
     def test_list_container_contents_with_no_object(self):
@@ -143,7 +143,7 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual('', object_list.strip('\n'))
+        self.assertEmpty(object_list)
 
     @test.idempotent_id('fe323a32-57b9-4704-a996-2e68f83b09bc')
     def test_list_container_contents_with_delimiter(self):
@@ -157,7 +157,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name.split('/')[0], object_list.strip('/\n'))
+        self.assertEqual([object_name.split('/')[0] + '/'], object_list)
 
     @test.idempotent_id('55b4fa5c-e12e-4ca9-8fcf-a79afe118522')
     def test_list_container_contents_with_end_marker(self):
@@ -170,7 +170,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.idempotent_id('196f5034-6ab0-4032-9da9-a937bbb9fba9')
     def test_list_container_contents_with_format_json(self):
@@ -226,7 +226,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.idempotent_id('c31ddc63-2a58-4f6b-b25c-94d2937e6867')
     def test_list_container_contents_with_marker(self):
@@ -239,7 +239,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.idempotent_id('58ca6cc9-6af0-408d-aaec-2a6a7b2f0df9')
     def test_list_container_contents_with_path(self):
@@ -253,7 +253,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.idempotent_id('77e742c7-caf2-4ec9-8aa4-f7d509a3344c')
     def test_list_container_contents_with_prefix(self):
@@ -267,7 +267,7 @@
             container_name,
             params=params)
         self.assertHeaders(resp, 'Container', 'GET')
-        self.assertEqual(object_name, object_list.strip('\n'))
+        self.assertEqual([object_name], object_list)
 
     @test.attr(type='smoke')
     @test.idempotent_id('96e68f0e-19ec-4aa2-86f3-adc6a45e14dd')
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index f63c518..2856fab 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.py
@@ -173,5 +173,5 @@
         ex = self.assertRaises(exceptions.Conflict,
                                self.container_client.delete_container,
                                container_name)
-        self.assertIn('An object with that identifier already exists',
-                      str(ex))
+        self.assertIn('There was a conflict when trying to complete your '
+                      'request.', str(ex))
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 47ef0d3..edc9271 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -96,7 +96,7 @@
         # Check only the format of common headers with custom matcher
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
-        self.assertIn(self.object_name, body)
+        self.assertIn(self.object_name, body.decode())
 
         # clean up before exiting
         self.container_client.update_container_metadata(self.container_name,
@@ -126,9 +126,9 @@
         resp, body = self.account_client.request("GET",
                                                  self.container_name,
                                                  headers={})
-        self.assertIn(self.object_name, body)
+        self.assertIn(self.object_name, body.decode())
         css = '<link rel="stylesheet" type="text/css" href="listings.css" />'
-        self.assertIn(css, body)
+        self.assertIn(css, body.decode())
 
     @test.idempotent_id('f18b4bef-212e-45e7-b3ca-59af3a465f82')
     @test.requires_ext(extension='staticweb', service='object')
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index e10b900..f134335 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -96,7 +96,7 @@
                 cont_client[0].put(str(cont[0]), body=None, headers=headers)
             # create object in container
             object_name = data_utils.rand_name(name='TestSyncObject')
-            data = object_name[::-1]  # data_utils.arbitrary_string()
+            data = object_name[::-1].encode()  # Raw data, we need bytes
             resp, _ = obj_client[0].create_object(cont[0], object_name, data)
             self.objects.append(object_name)
 
@@ -127,7 +127,7 @@
         for obj_client, cont in obj_clients:
             for obj_name in object_lists[0]:
                 resp, object_content = obj_client.get_object(cont, obj_name)
-                self.assertEqual(object_content, obj_name[::-1])
+                self.assertEqual(object_content, obj_name[::-1].encode())
 
     @test.attr(type='slow')
     @decorators.skip_because(bug='1317133')
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index 8dbfd06..18dc254 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -40,6 +40,7 @@
     @test.requires_ext(extension='crossdomain', service='object')
     def test_get_crossdomain_policy(self):
         resp, body = self.account_client.get("crossdomain.xml", {})
+        body = body.decode()
 
         self.assertTrue(body.startswith(self.xml_start) and
                         body.endswith(self.xml_end))
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 102ec2f..0a87a64 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -72,7 +72,9 @@
                                             max_file_count,
                                             expires)
 
-        signature = hmac.new(self.key, hmac_body, hashlib.sha1).hexdigest()
+        signature = hmac.new(
+            self.key.encode(), hmac_body.encode(), hashlib.sha1
+        ).hexdigest()
 
         fields = {'redirect': redirect,
                   'max_file_size': str(max_file_size),
@@ -119,4 +121,4 @@
         resp, body = self.object_client.get("%s/%s%s" % (
             self.container_name, self.object_name, "testfile"))
         self.assertHeaders(resp, "Object", "GET")
-        self.assertEqual(body, "hello world")
+        self.assertEqual(body.decode(), "hello world")
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index 8ff5d82..f193111 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -73,7 +73,9 @@
                                             max_file_count,
                                             expires)
 
-        signature = hmac.new(self.key, hmac_body, hashlib.sha1).hexdigest()
+        signature = hmac.new(
+            self.key.encode(), hmac_body.encode(), hashlib.sha1
+        ).hexdigest()
 
         fields = {'redirect': redirect,
                   'max_file_size': str(max_file_size),
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 8736f9a..7716bdb 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -19,8 +19,6 @@
 import time
 import zlib
 
-import six
-
 from tempest.api.object_storage import base
 from tempest.common import custom_matchers
 from tempest.common.utils import data_utils
@@ -81,12 +79,12 @@
     def test_create_object(self):
         # create object
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # create another object
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertHeaders(resp, 'Object', 'PUT')
@@ -100,7 +98,7 @@
     def test_create_object_with_content_disposition(self):
         # create object with content_disposition
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata = {}
         metadata['content-disposition'] = 'inline'
         resp, _ = self.object_client.create_object(
@@ -124,7 +122,7 @@
         object_name = data_utils.rand_name(name='TestObject')
 
         # put compressed string
-        data_before = 'x' * 2000
+        data_before = b'x' * 2000
         data = zlib.compress(data_before)
         metadata = {}
         metadata['content-encoding'] = 'deflate'
@@ -149,7 +147,7 @@
     def test_create_object_with_etag(self):
         # create object with etag
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         md5 = hashlib.md5(data).hexdigest()
         metadata = {'Etag': md5}
         resp, _ = self.object_client.create_object(
@@ -169,7 +167,7 @@
         # create object with expect_continue
 
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
 
         status, _ = self.object_client.create_object_continue(
             self.container_name, object_name, data)
@@ -185,7 +183,7 @@
     def test_create_object_with_transfer_encoding(self):
         # create object with transfer_encoding
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string(1024)
+        data = data_utils.random_bytes(1024)
         status, _, resp_headers = self.object_client.put_object_with_chunk(
             container=self.container_name,
             name=object_name,
@@ -202,7 +200,7 @@
     def test_create_object_with_x_fresh_metadata(self):
         # create object with x_fresh_metadata
         object_name_base = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata_1 = {'X-Object-Meta-test-meta': 'Meta'}
         self.object_client.create_object(self.container_name,
                                          object_name_base,
@@ -228,7 +226,7 @@
     def test_create_object_with_x_object_meta(self):
         # create object with object_meta
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata = {'X-Object-Meta-test-meta': 'Meta'}
         resp, _ = self.object_client.create_object(
             self.container_name,
@@ -247,7 +245,7 @@
     def test_create_object_with_x_object_metakey(self):
         # create object with the blank value of metadata
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata = {'X-Object-Meta-test-meta': ''}
         resp, _ = self.object_client.create_object(
             self.container_name,
@@ -266,7 +264,7 @@
     def test_create_object_with_x_remove_object_meta(self):
         # create object with x_remove_object_meta
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata_add = {'X-Object-Meta-test-meta': 'Meta'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -289,7 +287,7 @@
     def test_create_object_with_x_remove_object_metakey(self):
         # create object with the blank value of remove metadata
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata_add = {'X-Object-Meta-test-meta': 'Meta'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -312,7 +310,7 @@
     def test_delete_object(self):
         # create object
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         # delete object
@@ -344,7 +342,7 @@
     def test_update_object_metadata_with_remove_metadata(self):
         # update object metadata with remove metadata
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         create_metadata = {'X-Object-Meta-test-meta1': 'Meta1'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -368,7 +366,7 @@
     def test_update_object_metadata_with_create_and_remove_metadata(self):
         # creation and deletion of metadata with one request
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         create_metadata = {'X-Object-Meta-test-meta1': 'Meta1'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -466,7 +464,7 @@
     def test_list_object_metadata(self):
         # get object metadata
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata = {'X-Object-Meta-test-meta': 'Meta'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -549,7 +547,7 @@
     def test_get_object_with_metadata(self):
         # get object with metadata
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         metadata = {'X-Object-Meta-test-meta': 'Meta'}
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -568,7 +566,7 @@
     def test_get_object_with_range(self):
         # get object with range
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string(100)
+        data = data_utils.random_bytes(100)
         self.object_client.create_object(self.container_name,
                                          object_name,
                                          data,
@@ -623,13 +621,13 @@
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s' % (self.container_name, object_name))
 
-        self.assertEqual(''.join(data_segments), body)
+        self.assertEqual(''.join(data_segments), body.decode())
 
     @test.idempotent_id('c05b4013-e4de-47af-be84-e598062b16fc')
     def test_get_object_with_if_match(self):
         # get object with if_match
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string(10)
+        data = data_utils.random_bytes(10)
         create_md5 = hashlib.md5(data).hexdigest()
         create_metadata = {'Etag': create_md5}
         self.object_client.create_object(self.container_name,
@@ -649,7 +647,7 @@
     def test_get_object_with_if_modified_since(self):
         # get object with if_modified_since
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
+        data = data_utils.random_bytes()
         time_now = time.time()
         self.object_client.create_object(self.container_name,
                                          object_name,
@@ -669,7 +667,7 @@
     def test_get_object_with_if_none_match(self):
         # get object with if_none_match
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string(10)
+        data = data_utils.random_bytes()
         create_md5 = hashlib.md5(data).hexdigest()
         create_metadata = {'Etag': create_md5}
         self.object_client.create_object(self.container_name,
@@ -677,7 +675,7 @@
                                          data,
                                          metadata=create_metadata)
 
-        list_data = data_utils.arbitrary_string(15)
+        list_data = data_utils.random_bytes()
         list_md5 = hashlib.md5(list_data).hexdigest()
         list_metadata = {'If-None-Match': list_md5}
         resp, body = self.object_client.get_object(
@@ -719,15 +717,13 @@
     def test_copy_object_in_same_container(self):
         # create source object
         src_object_name = data_utils.rand_name(name='SrcObject')
-        src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
-                                               base_text=src_object_name)
+        src_data = data_utils.random_bytes(size=len(src_object_name) * 2)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    src_object_name,
                                                    src_data)
         # create destination object
         dst_object_name = data_utils.rand_name(name='DstObject')
-        dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
-                                               base_text=dst_object_name)
+        dst_data = data_utils.random_bytes(size=len(dst_object_name) * 3)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    dst_object_name,
                                                    dst_data)
@@ -766,14 +762,12 @@
     def test_copy_object_2d_way(self):
         # create source object
         src_object_name = data_utils.rand_name(name='SrcObject')
-        src_data = data_utils.arbitrary_string(size=len(src_object_name) * 2,
-                                               base_text=src_object_name)
+        src_data = data_utils.random_bytes(size=len(src_object_name) * 2)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    src_object_name, src_data)
         # create destination object
         dst_object_name = data_utils.rand_name(name='DstObject')
-        dst_data = data_utils.arbitrary_string(size=len(dst_object_name) * 3,
-                                               base_text=dst_object_name)
+        dst_data = data_utils.random_bytes(size=len(dst_object_name) * 3)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    dst_object_name, dst_data)
         # copy source object to destination
@@ -801,8 +795,7 @@
         self.containers.append(dst_container_name)
         # create object in source container
         object_name = data_utils.rand_name(name='Object')
-        data = data_utils.arbitrary_string(size=len(object_name) * 2,
-                                           base_text=object_name)
+        data = data_utils.random_bytes(size=len(object_name) * 2)
         resp, _ = self.object_client.create_object(src_container_name,
                                                    object_name, data)
         # set object metadata
@@ -865,7 +858,7 @@
         expected = {'x-object-meta-test': '',
                     'x-object-meta-src': 'src_value',
                     'x-copied-from': self.container_name + "/" + src_obj_name}
-        for key, value in six.iteritems(expected):
+        for key, value in expected.items():
             self.assertIn(key, resp)
             self.assertEqual(value, resp[key])
 
@@ -888,7 +881,7 @@
         expected = {'x-object-meta-test': 'value',
                     'x-object-meta-src': 'src_value',
                     'x-copied-from': self.container_name + "/" + src_obj_name}
-        for key, value in six.iteritems(expected):
+        for key, value in expected.items():
             self.assertIn(key, resp)
             self.assertEqual(value, resp[key])
 
@@ -935,7 +928,7 @@
         # downloading the object
         resp, body = self.object_client.get_object(
             self.container_name, object_name)
-        self.assertEqual(''.join(data_segments), body)
+        self.assertEqual(''.join(data_segments), body.decode())
 
     @test.idempotent_id('50d01f12-526f-4360-9ac2-75dd508d7b68')
     def test_get_object_if_different(self):
@@ -960,7 +953,7 @@
 
         # local copy is different, download
         local_data = "something different"
-        md5 = hashlib.md5(local_data).hexdigest()
+        md5 = hashlib.md5(local_data.encode()).hexdigest()
         headers = {'If-None-Match': md5}
         resp, body = self.object_client.get(url, headers=headers)
         self.assertHeaders(resp, 'Object', 'GET')
@@ -1004,8 +997,7 @@
 
         # create object
         object_name = data_utils.rand_name(name='Object')
-        data = data_utils.arbitrary_string(size=len(object_name),
-                                           base_text=object_name)
+        data = data_utils.random_bytes(size=len(object_name))
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertHeaders(resp, 'Object', 'PUT')
@@ -1041,8 +1033,7 @@
 
         # create object
         object_name = data_utils.rand_name(name='Object')
-        data = data_utils.arbitrary_string(size=len(object_name) * 1,
-                                           base_text=object_name)
+        data = data_utils.random_bytes(size=len(object_name))
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
         self.assertHeaders(resp, 'Object', 'PUT')
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index e00bbab..f9c1148 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -56,7 +56,7 @@
         object_name_base_1 = object_name + '_01'
         object_name_base_2 = object_name + '_02'
         data_size = MIN_SEGMENT_SIZE
-        self.content = data_utils.arbitrary_string(data_size)
+        self.content = data_utils.random_bytes(data_size)
         self._create_object(self.container_name,
                             object_name_base_1,
                             self.content)
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 7287a2d..bd0d213 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -75,7 +75,9 @@
             container, object_name)
 
         hmac_body = '%s\n%s\n%s' % (method, expires, path)
-        sig = hmac.new(key, hmac_body, hashlib.sha1).hexdigest()
+        sig = hmac.new(
+            key.encode(), hmac_body.encode(), hashlib.sha1
+        ).hexdigest()
 
         url = "%s/%s?temp_url_sig=%s&temp_url_expires=%s" % (container,
                                                              object_name,
@@ -129,9 +131,7 @@
     @test.idempotent_id('9b08dade-3571-4152-8a4f-a4f2a873a735')
     @test.requires_ext(extension='tempurl', service='object')
     def test_put_object_using_temp_url(self):
-        new_data = data_utils.arbitrary_string(
-            size=len(self.object_name),
-            base_text=data_utils.rand_name(name="random"))
+        new_data = data_utils.random_bytes(size=len(self.object_name))
 
         expires = self._get_expiry_date()
         url = self._get_temp_url(self.container_name,
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index 577f3bd..df7a7f6 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -80,7 +80,9 @@
             container, object_name)
 
         hmac_body = '%s\n%s\n%s' % (method, expires, path)
-        sig = hmac.new(key, hmac_body, hashlib.sha1).hexdigest()
+        sig = hmac.new(
+            key.encode(), hmac_body.encode(), hashlib.sha1
+        ).hexdigest()
 
         url = "%s/%s?temp_url_sig=%s&temp_url_expires=%s" % (container,
                                                              object_name,
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 3f6623b..6d064a2 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -69,22 +69,24 @@
                              vers_container_name)
         object_name = data_utils.rand_name(name='TestObject')
         # create object
+        data_1 = data_utils.random_bytes()
         resp, _ = self.object_client.create_object(base_container_name,
-                                                   object_name, '1')
+                                                   object_name, data_1)
         # create 2nd version of object
+        data_2 = data_utils.random_bytes()
         resp, _ = self.object_client.create_object(base_container_name,
-                                                   object_name, '2')
+                                                   object_name, data_2)
         resp, body = self.object_client.get_object(base_container_name,
                                                    object_name)
-        self.assertEqual(body, '2')
+        self.assertEqual(body, data_2)
         # delete object version 2
         resp, _ = self.object_client.delete_object(base_container_name,
                                                    object_name)
-        self.assertContainer(base_container_name, '1', '1',
+        self.assertContainer(base_container_name, '1', '1024',
                              vers_container_name)
         resp, body = self.object_client.get_object(base_container_name,
                                                    object_name)
-        self.assertEqual(body, '1')
+        self.assertEqual(body, data_1)
         # delete object version 1
         resp, _ = self.object_client.delete_object(base_container_name,
                                                    object_name)
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 6d27502..5d680d2 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -28,8 +28,6 @@
 
     @classmethod
     def skip_checks(cls):
-        msg = "Skipped until Bug: 1547261 is resolved."
-        raise cls.skipException(msg)
         super(NeutronResourcesTestJSON, cls).skip_checks()
         if not CONF.service_available.neutron:
             raise cls.skipException("Neutron support is required")
@@ -44,6 +42,7 @@
         super(NeutronResourcesTestJSON, cls).setup_clients()
         cls.subnets_client = cls.os.subnets_client
         cls.ports_client = cls.os.ports_client
+        cls.routers_client = cls.os.routers_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index c0f1c4b..3672526 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 # Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index b47a5f0..7d8c94d 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -12,7 +12,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
@@ -63,7 +62,7 @@
             **new_quota_set)['quota_set']
 
         cleanup_quota_set = dict(
-            (k, v) for k, v in six.iteritems(default_quota_set)
+            (k, v) for k, v in default_quota_set.items()
             if k in QUOTA_KEYS)
         self.addCleanup(self.admin_quotas_client.update_quota_set,
                         self.demo_tenant_id, **cleanup_quota_set)
diff --git a/tempest/api/volume/admin/test_volume_retype_with_migration.py b/tempest/api/volume/admin/test_volume_retype_with_migration.py
new file mode 100644
index 0000000..8a69ea3
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -0,0 +1,109 @@
+#    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.api.volume import base
+from tempest.common import waiters
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+class VolumeRetypeWithMigrationV2Test(base.BaseVolumeAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeRetypeWithMigrationV2Test, cls).skip_checks()
+
+        if not CONF.volume_feature_enabled.multi_backend:
+            raise cls.skipException("Cinder multi-backend feature disabled.")
+
+        if len(set(CONF.volume.backend_names)) < 2:
+            raise cls.skipException("Requires at least two different "
+                                    "backend names")
+
+    @classmethod
+    def resource_setup(cls):
+        super(VolumeRetypeWithMigrationV2Test, cls).resource_setup()
+        # read backend name from a list.
+        cls.backend_src = CONF.volume.backend_names[0]
+        cls.backend_dst = CONF.volume.backend_names[1]
+
+        extra_specs_src = {"volume_backend_name": cls.backend_src}
+        extra_specs_dst = {"volume_backend_name": cls.backend_dst}
+
+        cls.src_vol_type = cls.create_volume_type(extra_specs=extra_specs_src)
+        cls.dst_vol_type = cls.create_volume_type(extra_specs=extra_specs_dst)
+
+        cls.src_vol = cls.create_volume(volume_type=cls.src_vol_type['name'])
+
+    @classmethod
+    def resource_cleanup(cls):
+        # When retyping a volume, Cinder creates an internal volume in the
+        # target backend. The volume in the source backend is deleted after
+        # the migration, so we need to wait for Cinder delete this volume
+        # before deleting the types we've created.
+
+        # This list should return 2 volumes until the copy and cleanup
+        # process is finished.
+        fetched_list = cls.admin_volume_client.list_volumes(
+            params={'all_tenants': True,
+                    'display_name': cls.src_vol['name']})['volumes']
+
+        for fetched_vol in fetched_list:
+            if fetched_vol['id'] != cls.src_vol['id']:
+                # This is the Cinder internal volume
+                LOG.debug('Waiting for internal volume %s deletion',
+                          fetched_vol['id'])
+                cls.admin_volume_client.wait_for_resource_deletion(
+                    fetched_vol['id'])
+                break
+
+        super(VolumeRetypeWithMigrationV2Test, cls).resource_cleanup()
+
+    @test.idempotent_id('a1a41f3f-9dad-493e-9f09-3ff197d477cd')
+    def test_available_volume_retype_with_migration(self):
+
+        keys_with_no_change = ('id', 'size', 'description', 'name', 'user_id',
+                               'os-vol-tenant-attr:tenant_id')
+        keys_with_change = ('volume_type', 'os-vol-host-attr:host')
+
+        volume_source = self.admin_volume_client.show_volume(
+            self.src_vol['id'])['volume']
+
+        # TODO(erlon): change this to volumes_client client after Bug
+        # #1657806 is fixed
+        self.admin_volume_client.retype_volume(
+            self.src_vol['id'],
+            new_type=self.dst_vol_type['name'],
+            migration_policy='on-demand')
+
+        waiters.wait_for_volume_retype(self.volumes_client, self.src_vol['id'],
+                                       self.dst_vol_type['name'])
+        volume_dest = self.admin_volume_client.show_volume(
+            self.src_vol['id'])['volume']
+
+        # Check the volume information after the migration.
+        self.assertEqual('success',
+                         volume_dest['os-vol-mig-status-attr:migstat'])
+        self.assertEqual('success', volume_dest['migration_status'])
+
+        for key in keys_with_no_change:
+            self.assertEqual(volume_source[key], volume_dest[key])
+
+        for key in keys_with_change:
+            self.assertNotEqual(volume_source[key], volume_dest[key])
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 3098cab..16be463 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -42,7 +42,7 @@
         extra_specs = {"storage_protocol": proto,
                        "vendor_name": vendor}
         # Create two volume_types
-        for i in range(2):
+        for _ in range(2):
             vol_type = self.create_volume_type(
                 extra_specs=extra_specs)
             volume_types.append(vol_type)
@@ -84,7 +84,6 @@
     @test.idempotent_id('4e955c3b-49db-4515-9590-0c99f8e471ad')
     def test_volume_type_create_get_delete(self):
         # Create/get volume type.
-        body = {}
         name = data_utils.rand_name(self.__class__.__name__ + '-volume-type')
         description = data_utils.rand_name("volume-type-description")
         proto = CONF.volume.storage_protocol
@@ -93,7 +92,6 @@
                        "vendor_name": vendor}
         body = self.create_volume_type(description=description, name=name,
                                        extra_specs=extra_specs)
-        self.assertIn('id', body)
         self.assertIn('name', body)
         self.assertEqual(name, body['name'],
                          "The created volume_type name is not equal "
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 857e7d2..5332f1e 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -51,6 +51,14 @@
                           self.admin_volume_types_client.delete_volume_type,
                           data_utils.rand_uuid())
 
+    @test.idempotent_id('8c09f849-f225-4d78-ba87-bffd9a5e0c6f')
+    def test_create_volume_with_private_volume_type(self):
+        # Should not be able to create volume with private volume type.
+        params = {'os-volume-type-access:is_public': False}
+        volume_type = self.create_volume_type(**params)
+        self.assertRaises(lib_exc.NotFound,
+                          self.create_volume, volume_type=volume_type['id'])
+
 
 class VolumeTypesNegativeV1Test(VolumeTypesNegativeV2Test):
     _api_version = 1
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 261e652..a63cbf0 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -14,27 +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 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,11 +31,13 @@
     @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/v2/test_backends_capabilities.py b/tempest/api/volume/admin/v2/test_backends_capabilities.py
index fc9066c..9751845 100644
--- a/tempest/api/volume/admin/v2/test_backends_capabilities.py
+++ b/tempest/api/volume/admin/v2/test_backends_capabilities.py
@@ -72,8 +72,8 @@
         ]
 
         # Returns a tuple of VOLUME_STATS values
-        expected_list = map(operator.itemgetter(*VOLUME_STATS),
-                            cinder_pools)
-        observed_list = map(operator.itemgetter(*VOLUME_STATS),
-                            capabilities)
+        expected_list = list(map(operator.itemgetter(*VOLUME_STATS),
+                             cinder_pools))
+        observed_list = list(map(operator.itemgetter(*VOLUME_STATS),
+                             capabilities))
         self.assertEqual(expected_list, observed_list)
diff --git a/tempest/api/volume/admin/v2/test_snapshot_manage.py b/tempest/api/volume/admin/v2/test_snapshot_manage.py
new file mode 100644
index 0000000..6a3f9ee
--- /dev/null
+++ b/tempest/api/volume/admin/v2/test_snapshot_manage.py
@@ -0,0 +1,73 @@
+# 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.
+
+import testtools
+
+from tempest.api.volume import base
+from tempest.common import waiters
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class SnapshotManageAdminV2Test(base.BaseVolumeAdminTest):
+    """Unmanage & manage snapshots
+
+     This feature provides the ability to import/export volume snapshot
+     from one Cinder to another and to import snapshots that have not been
+     managed by Cinder from a storage back end to Cinder
+    """
+
+    @test.idempotent_id('0132f42d-0147-4b45-8501-cc504bbf7810')
+    @testtools.skipUnless(CONF.volume_feature_enabled.manage_snapshot,
+                          "Manage snapshot tests are disabled")
+    def test_unmanage_manage_snapshot(self):
+        # Create a volume
+        volume = self.create_volume()
+
+        # Create a snapshot
+        snapshot = self.create_snapshot(volume_id=volume['id'])
+
+        # Unmanage the snapshot
+        # Unmanage snapshot function works almost the same as delete snapshot,
+        # but it does not delete the snapshot data
+        self.admin_snapshots_client.unmanage_snapshot(snapshot['id'])
+        self.admin_snapshots_client.wait_for_resource_deletion(snapshot['id'])
+
+        # Fetch snapshot ids
+        snapshot_list = [
+            snap['id'] for snap in
+            self.snapshots_client.list_snapshots()['snapshots']
+        ]
+
+        # Verify snapshot does not exist in snapshot list
+        self.assertNotIn(snapshot['id'], snapshot_list)
+
+        # Manage the snapshot
+        snapshot_ref = '_snapshot-%s' % snapshot['id']
+        new_snapshot = self.admin_snapshot_manage_client.manage_snapshot(
+            volume_id=volume['id'],
+            ref={'source-name': snapshot_ref})['snapshot']
+        self.addCleanup(self.delete_snapshot,
+                        self.admin_snapshots_client, new_snapshot['id'])
+
+        # Wait for the snapshot to be available after manage operation
+        waiters.wait_for_snapshot_status(self.admin_snapshots_client,
+                                         new_snapshot['id'],
+                                         'available')
+
+        # Verify the managed snapshot has the expected parent volume
+        self.assertEqual(new_snapshot['volume_id'], volume['id'])
diff --git a/tempest/api/volume/admin/v2/test_volume_pools.py b/tempest/api/volume/admin/v2/test_volume_pools.py
index e460278..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_scheduler_stats_client.list_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_scheduler_stats_client.\
-            list_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_volumes_list.py b/tempest/api/volume/admin/v2/test_volumes_list.py
index cdd9df9..fd36d0a 100644
--- a/tempest/api/volume/admin/v2/test_volumes_list.py
+++ b/tempest/api/volume/admin/v2/test_volumes_list.py
@@ -32,7 +32,7 @@
         # 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):
+        for _ in range(3):
             volume = cls.create_volume()
             # Fetch volume details
             volume_details = cls.volumes_client.show_volume(
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 7cd72e1..98e050e 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -51,7 +51,7 @@
                 raise cls.skipException(msg)
         else:
             msg = ("Invalid Cinder API version (%s)" % cls._api_version)
-            raise exceptions.InvalidConfiguration(message=msg)
+            raise exceptions.InvalidConfiguration(msg)
 
     @classmethod
     def setup_credentials(cls):
@@ -165,14 +165,20 @@
     # NOTE(afazekas): these create_* and clean_* could be defined
     # only in a single location in the source, and could be more general.
 
-    @classmethod
-    def delete_volume(cls, client, volume_id):
+    @staticmethod
+    def delete_volume(client, volume_id):
         """Delete volume by the given client"""
         client.delete_volume(volume_id)
         client.wait_for_resource_deletion(volume_id)
 
+    @staticmethod
+    def delete_snapshot(client, snapshot_id):
+        """Delete snapshot by the given client"""
+        client.delete_snapshot(snapshot_id)
+        client.wait_for_resource_deletion(snapshot_id)
+
     def attach_volume(self, server_id, volume_id):
-        """Attachs a volume to a server"""
+        """Attach a volume to a server"""
         self.servers_client.attach_volume(
             server_id, volumeId=volume_id,
             device='/dev/%s' % CONF.compute.volume_device_name)
@@ -181,7 +187,7 @@
         self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
                         volume_id, 'available')
         self.addCleanup(self.servers_client.detach_volume, server_id,
-                        self.volume_origin['id'])
+                        volume_id)
 
     @classmethod
     def clear_volumes(cls):
@@ -200,16 +206,13 @@
     @classmethod
     def clear_snapshots(cls):
         for snapshot in cls.snapshots:
-            try:
-                cls.snapshots_client.delete_snapshot(snapshot['id'])
-            except Exception:
-                pass
+            test_utils.call_and_ignore_notfound_exc(
+                cls.snapshots_client.delete_snapshot, snapshot['id'])
 
         for snapshot in cls.snapshots:
-            try:
-                cls.snapshots_client.wait_for_resource_deletion(snapshot['id'])
-            except Exception:
-                pass
+            test_utils.call_and_ignore_notfound_exc(
+                cls.snapshots_client.wait_for_resource_deletion,
+                snapshot['id'])
 
     def create_server(self, **kwargs):
         name = kwargs.pop(
@@ -260,6 +263,8 @@
             cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
             cls.admin_volume_client = cls.os_adm.volumes_v2_client
             cls.admin_hosts_client = cls.os_adm.volume_hosts_v2_client
+            cls.admin_snapshot_manage_client = \
+                cls.os_adm.snapshot_manage_v2_client
             cls.admin_snapshots_client = cls.os_adm.snapshots_v2_client
             cls.admin_backups_client = cls.os_adm.backups_v2_client
             cls.admin_encryption_types_client = \
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index cce9ace..f044124 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -35,7 +35,7 @@
         if len(CONF.volume_feature_enabled.api_extensions) == 0:
             raise self.skipException('There are not any extensions configured')
         extension_list = [extension.get('alias') for extension in extensions]
-        LOG.debug("Cinder extensions: %s" % ','.join(extension_list))
+        LOG.debug("Cinder extensions: %s", ','.join(extension_list))
         ext = CONF.volume_feature_enabled.api_extensions[0]
         if ext == 'all':
             self.assertIn('Hosts', map(lambda x: x['name'], extensions))
diff --git a/tempest/api/volume/test_volume_absolute_limits.py b/tempest/api/volume/test_volume_absolute_limits.py
index bc7694a..35e0d56 100644
--- a/tempest/api/volume/test_volume_absolute_limits.py
+++ b/tempest/api/volume/test_volume_absolute_limits.py
@@ -23,6 +23,9 @@
 
 class AbsoluteLimitsV2Tests(base.BaseVolumeTest):
 
+    # avoid existing volumes of pre-defined tenant
+    force_tenant_isolation = True
+
     @classmethod
     def resource_setup(cls):
         super(AbsoluteLimitsV2Tests, cls).resource_setup()
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 972dd58..6dcde08 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -30,6 +30,22 @@
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
+    def restore_backup(self, backup_id):
+        # Restore a backup
+        restored_volume = self.backups_client.restore_backup(
+            backup_id)['restore']
+
+        # Delete backup
+        self.addCleanup(self.volumes_client.delete_volume,
+                        restored_volume['volume_id'])
+        self.assertEqual(backup_id, restored_volume['backup_id'])
+        waiters.wait_for_backup_status(self.backups_client,
+                                       backup_id, 'available')
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       restored_volume['volume_id'],
+                                       'available')
+        return restored_volume
+
     @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
     def test_volume_backup_create_get_detailed_list_restore_delete(self):
         # Create backup
@@ -38,8 +54,10 @@
                         volume['id'])
         backup_name = data_utils.rand_name(
             self.__class__.__name__ + '-Backup')
+        description = data_utils.rand_name("volume-backup-description")
         backup = self.create_backup(volume_id=volume['id'],
-                                    name=backup_name)
+                                    name=backup_name,
+                                    description=description)
         self.assertEqual(backup_name, backup['name'])
         waiters.wait_for_volume_status(self.volumes_client,
                                        volume['id'], 'available')
@@ -47,6 +65,7 @@
         # 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(
@@ -54,18 +73,7 @@
         self.assertIn((backup['name'], backup['id']),
                       [(m['name'], m['id']) for m in backups])
 
-        # Restore backup
-        restore = self.backups_client.restore_backup(
-            backup['id'])['restore']
-
-        # Delete backup
-        self.addCleanup(self.volumes_client.delete_volume,
-                        restore['volume_id'])
-        self.assertEqual(backup['id'], restore['backup_id'])
-        waiters.wait_for_backup_status(self.backups_client,
-                                       backup['id'], 'available')
-        waiters.wait_for_volume_status(self.volumes_client,
-                                       restore['volume_id'], 'available')
+        self.restore_backup(backup['id'])
 
     @test.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
     @test.services('compute')
@@ -81,14 +89,7 @@
                         volume['id'])
         server = self.create_server(wait_until='ACTIVE')
         # Attach volume to instance
-        self.servers_client.attach_volume(server['id'],
-                                          volumeId=volume['id'])
-        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'])
+        self.attach_volume(server['id'], volume['id'])
         # Create backup using force flag
         backup_name = data_utils.rand_name(
             self.__class__.__name__ + '-Backup')
@@ -96,6 +97,28 @@
                                     name=backup_name, force=True)
         self.assertEqual(backup_name, backup['name'])
 
+    @test.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
+    def test_bootable_volume_backup_and_restore(self):
+        # Create volume from image
+        img_uuid = CONF.compute.image_ref
+        volume = self.create_volume(imageRef=img_uuid)
+
+        volume_details = self.volumes_client.show_volume(
+            volume['id'])['volume']
+        self.assertEqual('true', volume_details['bootable'])
+
+        # Create a backup
+        backup = self.create_backup(volume_id=volume['id'])
+
+        # Restore the backup
+        restored_volume_id = self.restore_backup(backup['id'])['volume_id']
+
+        # Verify the restored backup volume is bootable
+        restored_volume_info = self.volumes_client.show_volume(
+            restored_volume_id)['volume']
+
+        self.assertEqual('true', restored_volume_info['bootable'])
+
 
 class VolumesBackupsV1Test(VolumesBackupsV2Test):
     _api_version = 1
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 030ea6c..5e3f49f 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -61,7 +61,7 @@
         # Create 3 test volumes
         cls.volume_list = []
         cls.metadata = {'Type': 'work'}
-        for i in range(3):
+        for _ in range(3):
             volume = cls.create_volume(metadata=cls.metadata)
             volume = cls.volumes_client.show_volume(volume['id'])['volume']
             cls.volume_list.append(volume)
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index c45ace6..bcdbd22 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -133,7 +133,8 @@
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'work'}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id='#$%%&^&^', display_name=v_name,
+                          volume_id=data_utils.rand_name('invalid'),
+                          display_name=v_name,
                           metadata=metadata)
 
     @test.attr(type=['negative'])
@@ -150,7 +151,7 @@
     def test_get_invalid_volume_id(self):
         # Should not be able to get volume with invalid id
         self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
-                          '#$%%&^&^')
+                          data_utils.rand_name('invalid'))
 
     @test.attr(type=['negative'])
     @test.idempotent_id('c6c3db06-29ad-4e91-beb0-2ab195fe49e3')
@@ -164,7 +165,7 @@
     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.volumes_client.delete_volume,
-                          '!@#$%^&*()')
+                          data_utils.rand_name('invalid'))
 
     @test.attr(type=['negative'])
     @test.idempotent_id('441a1550-5d44-4b30-af0f-a6d402f52026')
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 3c7a2c8..6f85891 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -140,6 +140,14 @@
         # Destination volume bigger than source snapshot
         dst_vol = self.create_volume(snapshot_id=src_snap['id'],
                                      size=src_size + 1)
+        # NOTE(zhufl): dst_vol is created based on snapshot, so dst_vol
+        # should be deleted before deleting snapshot, otherwise deleting
+        # snapshot will end with status 'error-deleting'. This depends on
+        # the implementation mechanism of vendors, generally speaking,
+        # some verdors will use "virtual disk clone" which will promote
+        # disk clone speed, and in this situation the "disk clone"
+        # is just a relationship between volume and snapshot.
+        self.addCleanup(self.delete_volume, self.volumes_client, dst_vol['id'])
 
         volume = self.volumes_client.show_volume(dst_vol['id'])['volume']
         # Should allow
diff --git a/tempest/api/volume/test_volumes_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
index 4416bef..b831252 100644
--- a/tempest/api/volume/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -105,12 +105,6 @@
         # List returns zero elements
         self._list_snapshots_by_param_limit(limit=0, expected_elements=0)
 
-    def cleanup_snapshot(self, snapshot):
-        # Delete the snapshot
-        self.snapshots_client.delete_snapshot(snapshot['id'])
-        self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
-        self.snapshots.remove(snapshot)
-
 
 class VolumesV1SnapshotLimitTestJSON(VolumesV2SnapshotListTestJSON):
     _api_version = 1
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index fb8c65d..28ba941 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -42,7 +42,7 @@
         # may have volumes other than those created below.
         existing_volumes = cls.volumes_client.list_volumes()['volumes']
         cls.volume_id_list = [vol['id'] for vol in existing_volumes]
-        for i in range(3):
+        for _ in range(3):
             volume = cls.create_volume(metadata=cls.metadata)
             cls.volume_id_list.append(volume['id'])
 
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_list.py b/tempest/api/volume/v2/test_volumes_snapshots_list.py
new file mode 100644
index 0000000..f389b59
--- /dev/null
+++ b/tempest/api/volume/v2/test_volumes_snapshots_list.py
@@ -0,0 +1,94 @@
+# 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 tempest.api.volume import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+        if not CONF.volume_feature_enabled.snapshot:
+            raise cls.skipException("Cinder volume snapshots are disabled")
+
+    @classmethod
+    def resource_setup(cls):
+        super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
+        cls.snapshot_id_list = []
+        # Create a volume
+        cls.volume_origin = cls.create_volume()
+        cls.name_field = cls.special_fields['name_field']
+        # Create 3 snapshots
+        for _ in range(3):
+            snapshot = cls.create_snapshot(cls.volume_origin['id'])
+            cls.snapshot_id_list.append(snapshot['id'])
+
+    def _list_snapshots_param_sort(self, sort_key, sort_dir):
+        """list snapshots by sort param"""
+        snap_list = self.snapshots_client.list_snapshots(
+            sort_key=sort_key, sort_dir=sort_dir)['snapshots']
+        self.assertNotEmpty(snap_list)
+        if sort_key is 'display_name':
+            sort_key = 'name'
+        # Note: On Cinder V2 API, 'display_name' works as a sort key
+        # on a request, a volume name appears as 'name' on the response.
+        # So Tempest needs to change the key name here for this inconsistent
+        # API behavior.
+        sorted_list = [snapshot[sort_key] for snapshot in snap_list]
+        msg = 'The list of snapshots was not sorted correctly.'
+        self.assertEqual(sorted(sorted_list, reverse=(sort_dir == 'desc')),
+                         sorted_list, msg)
+
+    @test.idempotent_id('c5513ada-64c1-4d28-83b9-af3307ec1388')
+    def test_snapshot_list_param_sort_id_asc(self):
+        self._list_snapshots_param_sort(sort_key='id', sort_dir='asc')
+
+    @test.idempotent_id('8a7fe058-0b41-402a-8afd-2dbc5a4a718b')
+    def test_snapshot_list_param_sort_id_desc(self):
+        self._list_snapshots_param_sort(sort_key='id', sort_dir='desc')
+
+    @test.idempotent_id('4052c3a0-2415-440a-a8cc-305a875331b0')
+    def test_snapshot_list_param_sort_created_at_asc(self):
+        self._list_snapshots_param_sort(sort_key='created_at', sort_dir='asc')
+
+    @test.idempotent_id('dcbbe24a-f3c0-4ec8-9274-55d48db8d1cf')
+    def test_snapshot_list_param_sort_created_at_desc(self):
+        self._list_snapshots_param_sort(sort_key='created_at', sort_dir='desc')
+
+    @test.idempotent_id('d58b5fed-0c37-42d3-8c5d-39014ac13c00')
+    def test_snapshot_list_param_sort_name_asc(self):
+        self._list_snapshots_param_sort(sort_key='display_name',
+                                        sort_dir='asc')
+
+    @test.idempotent_id('96ba6f4d-1f18-47e1-b4bc-76edc6c21250')
+    def test_snapshot_list_param_sort_name_desc(self):
+        self._list_snapshots_param_sort(sort_key='display_name',
+                                        sort_dir='desc')
+
+    @test.idempotent_id('05489dde-44bc-4961-a1f5-3ce7ee7824f7')
+    def test_snapshot_list_param_marker(self):
+        # The list of snapshots should end before the provided marker
+        params = {'marker': self.snapshot_id_list[1]}
+        snap_list = self.snapshots_client.list_snapshots(**params)['snapshots']
+        fetched_list_id = [snap['id'] for snap in snap_list]
+        # Verify the list of snapshots ends before the provided
+        # marker(second snapshot), therefore only the first snapshot
+        # should displayed.
+        self.assertEqual(self.snapshot_id_list[:1], fetched_list_id)
diff --git a/tempest/clients.py b/tempest/clients.py
index 4a30f6f..cdd6925 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -13,16 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import copy
-
 from oslo_log import log as logging
 
 from tempest import config
 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
 
@@ -35,20 +31,11 @@
 
     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'):
+    def __init__(self, credentials, scope='project'):
         """Initialization of Manager class.
 
         Setup all services clients and make them available for tests cases.
         :param credentials: type Credentials or TestResources
-        :param service: Service name
         :param scope: default scope for tokens produced by the auth provider
         """
         _, identity_uri = get_auth_provider_class(credentials)
@@ -66,12 +53,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,
@@ -106,7 +87,7 @@
                         config.service_client_config(service_for_config))
             except lib_exc.UnknownServiceClient:
                 LOG.warning(
-                    'Could not load configuration for service %s' % service)
+                    'Could not load configuration for service %s', service)
 
         return configuration
 
@@ -137,9 +118,13 @@
             self.image_member_client_v2 = self.image_v2.ImageMembersClient()
             self.namespaces_client = self.image_v2.NamespacesClient()
             self.resource_types_client = self.image_v2.ResourceTypesClient()
+            self.namespace_objects_client = \
+                self.image_v2.NamespaceObjectsClient()
             self.schemas_client = self.image_v2.SchemasClient()
             self.namespace_properties_client = \
                 self.image_v2.NamespacePropertiesClient()
+            self.namespace_tags_client = \
+                self.image_v2.NamespaceTagsClient()
 
     def _set_compute_clients(self):
         self.agents_client = self.compute.AgentsClient()
@@ -172,12 +157,12 @@
         self.aggregates_client = self.compute.AggregatesClient()
         self.services_client = self.compute.ServicesClient()
         self.tenant_usages_client = self.compute.TenantUsagesClient()
+        self.baremetal_nodes_client = self.compute.BaremetalNodesClient()
         self.hosts_client = self.compute.HostsClient()
         self.hypervisor_client = self.compute.HypervisorClient()
         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.
@@ -194,82 +179,67 @@
             **params_volume)
 
     def _set_identity_clients(self):
-        params = self.parameters['identity']
-
         # Clients below use the admin endpoint type of Keystone API v2
-        params_v2_admin = copy.copy(params)
-        params_v2_admin['endpoint_type'] = CONF.identity.v2_admin_endpoint_type
-        self.endpoints_client = identity.v2.EndpointsClient(self.auth_provider,
-                                                            **params_v2_admin)
-        self.identity_client = identity.v2.IdentityClient(self.auth_provider,
-                                                          **params_v2_admin)
-        self.tenants_client = identity.v2.TenantsClient(self.auth_provider,
-                                                        **params_v2_admin)
-        self.roles_client = identity.v2.RolesClient(self.auth_provider,
-                                                    **params_v2_admin)
-        self.users_client = identity.v2.UsersClient(self.auth_provider,
-                                                    **params_v2_admin)
-        self.identity_services_client = identity.v2.ServicesClient(
-            self.auth_provider, **params_v2_admin)
+        params_v2_admin = {
+            'endpoint_type': CONF.identity.v2_admin_endpoint_type}
+        self.endpoints_client = self.identity_v2.EndpointsClient(
+            **params_v2_admin)
+        self.identity_client = self.identity_v2.IdentityClient(
+            **params_v2_admin)
+        self.tenants_client = self.identity_v2.TenantsClient(
+            **params_v2_admin)
+        self.roles_client = self.identity_v2.RolesClient(**params_v2_admin)
+        self.users_client = self.identity_v2.UsersClient(**params_v2_admin)
+        self.identity_services_client = self.identity_v2.ServicesClient(
+            **params_v2_admin)
 
         # Clients below use the public endpoint type of Keystone API v2
-        params_v2_public = copy.copy(params)
-        params_v2_public['endpoint_type'] = (
-            CONF.identity.v2_public_endpoint_type)
-        self.identity_public_client = identity.v2.IdentityClient(
-            self.auth_provider, **params_v2_public)
-        self.tenants_public_client = identity.v2.TenantsClient(
-            self.auth_provider, **params_v2_public)
-        self.users_public_client = identity.v2.UsersClient(
-            self.auth_provider, **params_v2_public)
+        params_v2_public = {
+            'endpoint_type': CONF.identity.v2_public_endpoint_type}
+        self.identity_public_client = self.identity_v2.IdentityClient(
+            **params_v2_public)
+        self.tenants_public_client = self.identity_v2.TenantsClient(
+            **params_v2_public)
+        self.users_public_client = self.identity_v2.UsersClient(
+            **params_v2_public)
 
         # Clients below use the endpoint type of Keystone API v3, which is set
         # in endpoint_type
-        params_v3 = copy.copy(params)
-        params_v3['endpoint_type'] = CONF.identity.v3_endpoint_type
-        self.domains_client = identity.v3.DomainsClient(self.auth_provider,
-                                                        **params_v3)
-        self.identity_v3_client = identity.v3.IdentityClient(
-            self.auth_provider, **params_v3)
-        self.trusts_client = identity.v3.TrustsClient(self.auth_provider,
-                                                      **params_v3)
-        self.users_v3_client = identity.v3.UsersClient(self.auth_provider,
-                                                       **params_v3)
-        self.endpoints_v3_client = identity.v3.EndPointsClient(
-            self.auth_provider, **params_v3)
-        self.roles_v3_client = identity.v3.RolesClient(self.auth_provider,
-                                                       **params_v3)
-        self.inherited_roles_client = identity.v3.InheritedRolesClient(
-            self.auth_provider, **params_v3)
-        self.role_assignments_client = identity.v3.RoleAssignmentsClient(
-            self.auth_provider, **params_v3)
-        self.identity_services_v3_client = identity.v3.ServicesClient(
-            self.auth_provider, **params_v3)
-        self.policies_client = identity.v3.PoliciesClient(self.auth_provider,
-                                                          **params_v3)
-        self.projects_client = identity.v3.ProjectsClient(self.auth_provider,
-                                                          **params_v3)
-        self.regions_client = identity.v3.RegionsClient(self.auth_provider,
-                                                        **params_v3)
-        self.credentials_client = identity.v3.CredentialsClient(
-            self.auth_provider, **params_v3)
-        self.groups_client = identity.v3.GroupsClient(self.auth_provider,
-                                                      **params_v3)
+        params_v3 = {'endpoint_type': CONF.identity.v3_endpoint_type}
+        self.domains_client = self.identity_v3.DomainsClient(**params_v3)
+        self.identity_v3_client = self.identity_v3.IdentityClient(**params_v3)
+        self.trusts_client = self.identity_v3.TrustsClient(**params_v3)
+        self.users_v3_client = self.identity_v3.UsersClient(**params_v3)
+        self.endpoints_v3_client = self.identity_v3.EndPointsClient(
+            **params_v3)
+        self.roles_v3_client = self.identity_v3.RolesClient(**params_v3)
+        self.inherited_roles_client = self.identity_v3.InheritedRolesClient(
+            **params_v3)
+        self.role_assignments_client = self.identity_v3.RoleAssignmentsClient(
+            **params_v3)
+        self.identity_services_v3_client = self.identity_v3.ServicesClient(
+            **params_v3)
+        self.policies_client = self.identity_v3.PoliciesClient(**params_v3)
+        self.projects_client = self.identity_v3.ProjectsClient(**params_v3)
+        self.regions_client = self.identity_v3.RegionsClient(**params_v3)
+        self.credentials_client = self.identity_v3.CredentialsClient(
+            **params_v3)
+        self.groups_client = self.identity_v3.GroupsClient(**params_v3)
 
         # Token clients do not use the catalog. They only need default_params.
         # They read auth_url, so they should only be set if the corresponding
         # API version is marked as enabled
         if CONF.identity_feature_enabled.api_v2:
             if CONF.identity.uri:
-                self.token_client = identity.v2.TokenClient(
-                    CONF.identity.uri, **self.default_params)
+                self.token_client = self.identity_v2.TokenClient(
+                    auth_url=CONF.identity.uri)
             else:
                 msg = 'Identity v2 API enabled, but no identity.uri set'
                 raise lib_exc.InvalidConfiguration(msg)
         if CONF.identity_feature_enabled.api_v3:
             if CONF.identity.uri_v3:
-                self.token_v3_client = identity.v3.V3TokenClient(
-                    CONF.identity.uri_v3, **self.default_params)
+                self.token_v3_client = self.identity_v3.V3TokenClient(
+                    auth_url=CONF.identity.uri_v3)
             else:
                 msg = 'Identity v3 API enabled, but no identity.uri_v3 set'
                 raise lib_exc.InvalidConfiguration(msg)
@@ -285,6 +255,7 @@
         self.encryption_types_client = self.volume_v1.EncryptionTypesClient()
         self.encryption_types_v2_client = \
             self.volume_v2.EncryptionTypesClient()
+        self.snapshot_manage_v2_client = self.volume_v2.SnapshotManageClient()
         self.snapshots_client = self.volume_v1.SnapshotsClient()
         self.snapshots_v2_client = self.volume_v2.SnapshotsClient()
         self.volumes_client = self.volume_v1.VolumesClient()
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 3d38e25..172d9e1 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -205,7 +205,7 @@
         os.rename(account_file, '.'.join((account_file, 'bak')))
     with open(account_file, 'w') as f:
         yaml.safe_dump(accounts, f, default_flow_style=False)
-    LOG.info('%s generated successfully!' % account_file)
+    LOG.info('%s generated successfully!', account_file)
 
 
 def _parser_add_args(parser):
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index af86fe3..ec76103 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -149,8 +149,8 @@
 
     def _remove_admin_user_roles(self):
         tenant_ids = self.admin_role_added
-        LOG.debug("Removing admin user roles where needed for tenants: %s"
-                  % tenant_ids)
+        LOG.debug("Removing admin user roles where needed for tenants: %s",
+                  tenant_ids)
         for tenant_id in tenant_ids:
             self._remove_admin_role(tenant_id)
 
@@ -236,13 +236,13 @@
                 needs_role = False
                 LOG.debug("User already had admin privilege for this tenant")
         if needs_role:
-            LOG.debug("Adding admin privilege for : %s" % tenant_id)
+            LOG.debug("Adding admin privilege for : %s", tenant_id)
             rl_cl.create_user_role_on_project(tenant_id, self.admin_id,
                                               self.admin_role_id)
             self.admin_role_added.append(tenant_id)
 
     def _remove_admin_role(self, tenant_id):
-        LOG.debug("Remove admin user role for tenant: %s" % tenant_id)
+        LOG.debug("Remove admin user role for tenant: %s", tenant_id)
         # Must initialize AdminManager for each user role
         # Otherwise authentication exception is thrown, weird
         id_cl = credentials.AdminManager().identity_client
@@ -253,16 +253,16 @@
                                                        self.admin_role_id)
             except Exception as ex:
                 LOG.exception("Failed removing role from tenant which still"
-                              "exists, exception: %s" % ex)
+                              "exists, exception: %s", ex)
 
     def _tenant_exists(self, tenant_id):
         tn_cl = self.admin_mgr.tenants_client
         try:
             t = tn_cl.show_tenant(tenant_id)
-            LOG.debug("Tenant is: %s" % str(t))
+            LOG.debug("Tenant is: %s", str(t))
             return True
         except Exception as ex:
-            LOG.debug("Tenant no longer exists? %s" % ex)
+            LOG.debug("Tenant no longer exists? %s", ex)
             return False
 
     def _init_state(self):
@@ -290,8 +290,8 @@
         except IOError as ex:
             LOG.exception("Failed loading saved state, please be sure you"
                           " have first run cleanup with --init-saved-state "
-                          "flag prior to running tempest. Exception: %s" % ex)
+                          "flag prior to running tempest. Exception: %s", ex)
             sys.exit(ex)
         except Exception as ex:
-            LOG.exception("Exception parsing saved state json : %s" % ex)
+            LOG.exception("Exception parsing saved state json : %s", ex)
             sys.exit(ex)
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 32b0ebb..a632726 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -144,7 +144,7 @@
     def list(self):
         client = self.client
         snaps = client.list_snapshots()['snapshots']
-        LOG.debug("List count, %s Snapshots" % len(snaps))
+        LOG.debug("List count, %s Snapshots", len(snaps))
         return snaps
 
     def delete(self):
@@ -171,7 +171,7 @@
         client = self.client
         servers_body = client.list_servers()
         servers = servers_body['servers']
-        LOG.debug("List count, %s Servers" % len(servers))
+        LOG.debug("List count, %s Servers", len(servers))
         return servers
 
     def delete(self):
@@ -193,7 +193,7 @@
     def list(self):
         client = self.server_groups_client
         sgs = client.list_server_groups()['server_groups']
-        LOG.debug("List count, %s Server Groups" % len(sgs))
+        LOG.debug("List count, %s Server Groups", len(sgs))
         return sgs
 
     def delete(self):
@@ -218,7 +218,7 @@
     def list(self):
         client = self.client
         stacks = client.list_stacks()['stacks']
-        LOG.debug("List count, %s Stacks" % len(stacks))
+        LOG.debug("List count, %s Stacks", len(stacks))
         return stacks
 
     def delete(self):
@@ -243,7 +243,7 @@
     def list(self):
         client = self.client
         keypairs = client.list_keypairs()['keypairs']
-        LOG.debug("List count, %s Keypairs" % len(keypairs))
+        LOG.debug("List count, %s Keypairs", len(keypairs))
         return keypairs
 
     def delete(self):
@@ -270,7 +270,7 @@
         client = self.client
         secgrps = client.list_security_groups()['security_groups']
         secgrp_del = [grp for grp in secgrps if grp['name'] != 'default']
-        LOG.debug("List count, %s Security Groups" % len(secgrp_del))
+        LOG.debug("List count, %s Security Groups", len(secgrp_del))
         return secgrp_del
 
     def delete(self):
@@ -295,7 +295,7 @@
     def list(self):
         client = self.client
         floating_ips = client.list_floating_ips()['floating_ips']
-        LOG.debug("List count, %s Floating IPs" % len(floating_ips))
+        LOG.debug("List count, %s Floating IPs", len(floating_ips))
         return floating_ips
 
     def delete(self):
@@ -320,7 +320,7 @@
     def list(self):
         client = self.client
         vols = client.list_volumes()['volumes']
-        LOG.debug("List count, %s Volumes" % len(vols))
+        LOG.debug("List count, %s Volumes", len(vols))
         return vols
 
     def delete(self):
@@ -402,7 +402,7 @@
         if self.is_preserve:
             networks = [network for network in networks
                         if network['id'] not in CONF_NETWORKS]
-        LOG.debug("List count, %s Networks" % networks)
+        LOG.debug("List count, %s Networks", networks)
         return networks
 
     def delete(self):
@@ -425,7 +425,7 @@
         client = self.floating_ips_client
         flips = client.list_floatingips(**self.tenant_filter)
         flips = flips['floatingips']
-        LOG.debug("List count, %s Network Floating IPs" % len(flips))
+        LOG.debug("List count, %s Network Floating IPs", len(flips))
         return flips
 
     def delete(self):
@@ -452,7 +452,7 @@
             routers = [router for router in routers
                        if router['id'] != CONF_PUB_ROUTER]
 
-        LOG.debug("List count, %s Routers" % len(routers))
+        LOG.debug("List count, %s Routers", len(routers))
         return routers
 
     def delete(self):
@@ -483,7 +483,7 @@
         hms = client.list_health_monitors()
         hms = hms['health_monitors']
         hms = self._filter_by_tenant_id(hms)
-        LOG.debug("List count, %s Health Monitors" % len(hms))
+        LOG.debug("List count, %s Health Monitors", len(hms))
         return hms
 
     def delete(self):
@@ -507,7 +507,7 @@
         members = client.list_members()
         members = members['members']
         members = self._filter_by_tenant_id(members)
-        LOG.debug("List count, %s Members" % len(members))
+        LOG.debug("List count, %s Members", len(members))
         return members
 
     def delete(self):
@@ -531,7 +531,7 @@
         vips = client.list_vips()
         vips = vips['vips']
         vips = self._filter_by_tenant_id(vips)
-        LOG.debug("List count, %s VIPs" % len(vips))
+        LOG.debug("List count, %s VIPs", len(vips))
         return vips
 
     def delete(self):
@@ -555,7 +555,7 @@
         pools = client.list_pools()
         pools = pools['pools']
         pools = self._filter_by_tenant_id(pools)
-        LOG.debug("List count, %s Pools" % len(pools))
+        LOG.debug("List count, %s Pools", len(pools))
         return pools
 
     def delete(self):
@@ -579,7 +579,7 @@
         rules = client.list_metering_label_rules()
         rules = rules['metering_label_rules']
         rules = self._filter_by_tenant_id(rules)
-        LOG.debug("List count, %s Metering Label Rules" % len(rules))
+        LOG.debug("List count, %s Metering Label Rules", len(rules))
         return rules
 
     def delete(self):
@@ -603,7 +603,7 @@
         labels = client.list_metering_labels()
         labels = labels['metering_labels']
         labels = self._filter_by_tenant_id(labels)
-        LOG.debug("List count, %s Metering Labels" % len(labels))
+        LOG.debug("List count, %s Metering Labels", len(labels))
         return labels
 
     def delete(self):
@@ -632,7 +632,7 @@
         if self.is_preserve:
             ports = self._filter_by_conf_networks(ports)
 
-        LOG.debug("List count, %s Ports" % len(ports))
+        LOG.debug("List count, %s Ports", len(ports))
         return ports
 
     def delete(self):
@@ -660,7 +660,7 @@
 
         if self.is_preserve:
             secgroups = self._filter_by_conf_networks(secgroups)
-        LOG.debug("List count, %s security_groups" % len(secgroups))
+        LOG.debug("List count, %s security_groups", len(secgroups))
         return secgroups
 
     def delete(self):
@@ -685,7 +685,7 @@
         subnets = subnets['subnets']
         if self.is_preserve:
             subnets = self._filter_by_conf_networks(subnets)
-        LOG.debug("List count, %s Subnets" % len(subnets))
+        LOG.debug("List count, %s Subnets", len(subnets))
         return subnets
 
     def delete(self):
@@ -719,7 +719,7 @@
         if self.is_preserve:
             flavors = [flavor for flavor in flavors
                        if flavor['id'] not in CONF_FLAVORS]
-        LOG.debug("List count, %s Flavors after reconcile" % len(flavors))
+        LOG.debug("List count, %s Flavors after reconcile", len(flavors))
         return flavors
 
     def delete(self):
@@ -756,7 +756,7 @@
         if self.is_preserve:
             images = [image for image in images
                       if image['id'] not in CONF_IMAGES]
-        LOG.debug("List count, %s Images after reconcile" % len(images))
+        LOG.debug("List count, %s Images after reconcile", len(images))
         return images
 
     def delete(self):
@@ -806,7 +806,7 @@
             users = [user for user in users if user['name'] !=
                      CONF.auth.admin_username]
 
-        LOG.debug("List count, %s Users after reconcile" % len(users))
+        LOG.debug("List count, %s Users after reconcile", len(users))
         return users
 
     def delete(self):
@@ -843,7 +843,7 @@
                          (role['id'] not in
                           self.saved_state_json['roles'].keys()
                           and role['name'] != CONF.identity.admin_role)]
-                LOG.debug("List count, %s Roles after reconcile" % len(roles))
+                LOG.debug("List count, %s Roles after reconcile", len(roles))
             return roles
         except Exception:
             LOG.exception("Cannot retrieve Roles.")
@@ -885,7 +885,7 @@
             tenants = [tenant for tenant in tenants if tenant['name']
                        not in CONF_TENANTS]
 
-        LOG.debug("List count, %s Tenants after reconcile" % len(tenants))
+        LOG.debug("List count, %s Tenants after reconcile", len(tenants))
         return tenants
 
     def delete(self):
@@ -920,7 +920,7 @@
             domains = [domain for domain in domains if domain['id']
                        not in self.saved_state_json['domains'].keys()]
 
-        LOG.debug("List count, %s Domains after reconcile" % len(domains))
+        LOG.debug("List count, %s Domains after reconcile", len(domains))
         return domains
 
     def delete(self):
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index 99185d2..7634d9e 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -120,7 +120,7 @@
         if os.path.isdir(config_dir):
             shutil.copytree(config_dir, etc_dir)
         else:
-            LOG.warning("Global config dir %s can't be found" % config_dir)
+            LOG.warning("Global config dir %s can't be found", config_dir)
 
     def generate_sample_config(self, local_dir):
         conf_generator = os.path.join(os.path.dirname(__file__),
@@ -131,14 +131,14 @@
                             output_file])
         else:
             LOG.warning("Skipping sample config generation because global "
-                        "config file %s can't be found" % conf_generator)
+                        "config file %s can't be found", conf_generator)
 
     def create_working_dir(self, local_dir, config_dir):
         # make sure we are working with abspath however tempest init is called
         local_dir = os.path.abspath(local_dir)
         # Create local dir if missing
         if not os.path.isdir(local_dir):
-            LOG.debug('Creating local working dir: %s' % local_dir)
+            LOG.debug('Creating local working dir: %s', local_dir)
             os.mkdir(local_dir)
         elif not os.listdir(local_dir) == []:
             raise OSError("Directory you are trying to initialize already "
@@ -151,11 +151,11 @@
         testr_dir = os.path.join(local_dir, '.testrepository')
         # Create lock dir
         if not os.path.isdir(lock_dir):
-            LOG.debug('Creating lock dir: %s' % lock_dir)
+            LOG.debug('Creating lock dir: %s', lock_dir)
             os.mkdir(lock_dir)
         # Create log dir
         if not os.path.isdir(log_dir):
-            LOG.debug('Creating log dir: %s' % log_dir)
+            LOG.debug('Creating log dir: %s', log_dir)
             os.mkdir(log_dir)
         # Create and copy local etc dir
         self.copy_config(etc_dir, config_dir)
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 5fa8b74..54b844a 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -21,7 +21,7 @@
 
  * **--regex/-r**: This is a selection regex like what testr uses. It will run
                    any tests that match on re.match() with the regex
- * **--smoke**: Run all the tests tagged as smoke
+ * **--smoke/-s**: Run all the tests tagged as smoke
 
 There are also the **--blacklist-file** and **--whitelist-file** options that
 let you pass a filepath to tempest run with the file format being a line
@@ -52,7 +52,7 @@
 There are several options to control how the tests are executed. By default
 tempest will run in parallel with a worker for each CPU present on the machine.
 If you want to adjust the number of workers use the **--concurrency** option
-and if you want to run tests serially use **--serial**
+and if you want to run tests serially use **--serial/-t**
 
 Running with Workspaces
 -----------------------
@@ -88,6 +88,7 @@
 from cliff import command
 from os_testr import regex_builder
 from os_testr import subunit_trace
+import six
 from testrepository.commands import run_argv
 
 from tempest.cmd import init
@@ -109,6 +110,12 @@
             return
         else:
             os.environ["TESTR_PDB"] = ""
+        # NOTE(dims): most of our .testr.conf try to test for PYTHON
+        # environment variable and fall back to "python", under python3
+        # if it does not exist. we should set it to the python3 executable
+        # to deal with this situation better for now.
+        if six.PY3 and 'PYTHON' not in os.environ:
+            os.environ['PYTHON'] = sys.executable
 
     def _create_testrepository(self):
         if not os.path.isdir('.testrepository'):
@@ -191,7 +198,7 @@
                             help='Configuration file to run tempest with')
         # test selection args
         regex = parser.add_mutually_exclusive_group()
-        regex.add_argument('--smoke', action='store_true',
+        regex.add_argument('--smoke', '-s', action='store_true',
                            help="Run the smoke tests only")
         regex.add_argument('--regex', '-r', default='',
                            help='A normal testr selection regex used to '
@@ -218,7 +225,7 @@
                               action='store_true',
                               help='Run tests in parallel (this is the'
                                    ' default)')
-        parallel.add_argument('--serial', dest='parallel',
+        parallel.add_argument('--serial', '-t', dest='parallel',
                               action='store_false',
                               help='Run tests serially')
         # output args
diff --git a/tempest/cmd/workspace.py b/tempest/cmd/workspace.py
index 3c58648..d2dc00d 100644
--- a/tempest/cmd/workspace.py
+++ b/tempest/cmd/workspace.py
@@ -151,7 +151,7 @@
         if not os.path.isfile(self.path):
             return
         with open(self.path, 'r') as f:
-            self.workspaces = yaml.load(f) or {}
+            self.workspaces = yaml.safe_load(f) or {}
 
 
 class TempestWorkspace(command.Command):
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 00b3b7e..01de704 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -178,8 +178,8 @@
                             clients.servers_client.delete_server(
                                 server['id'])
                         except Exception:
-                            LOG.exception('Deleting server %s failed'
-                                          % server['id'])
+                            LOG.exception('Deleting server %s failed',
+                                          server['id'])
 
     return body, servers
 
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 5634958..e6b46ed 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:
@@ -233,7 +233,6 @@
 class AdminManager(clients.Manager):
     """Manager that uses admin credentials for its managed client objects"""
 
-    def __init__(self, service=None):
+    def __init__(self):
         super(AdminManager, self).__init__(
-            credentials=get_configured_admin_credentials(),
-            service=service)
+            credentials=get_configured_admin_credentials())
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 8410541..ed11b21 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -14,7 +14,6 @@
 
 import re
 
-import six
 from testtools import helpers
 
 
@@ -217,7 +216,7 @@
     """
 
     def match(self, actual):
-        for key, value in six.iteritems(actual):
+        for key, value in actual.items():
             if key in ('content-length', 'x-account-bytes-used',
                        'x-account-container-count', 'x-account-object-count',
                        'x-container-bytes-used', 'x-container-object-count')\
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index 2763d16..632a876 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -254,7 +254,7 @@
                 msg = "There was an exception trying to setup network " \
                       "resources for tenant %s, and this error happened " \
                       "trying to clean them up: %s"
-                LOG.warning(msg % (tenant_id, cleanup_exception))
+                LOG.warning(msg, tenant_id, cleanup_exception)
             raise
         return network, subnet, router
 
@@ -316,8 +316,7 @@
                 credentials = self._create_creds(roles=credential_type)
             self._creds[str(credential_type)] = credentials
             # Maintained until tests are ported
-            LOG.info("Acquired dynamic creds:\n credentials: %s"
-                     % credentials)
+            LOG.info("Acquired dynamic creds:\n credentials: %s", credentials)
             if (self.neutron_available and
                 self.create_networks):
                 network, subnet, router = self._create_network_resources(
@@ -325,7 +324,7 @@
                 credentials.set_resources(network=network, subnet=subnet,
                                           router=router)
                 LOG.info("Created isolated network resources for : \n"
-                         + " credentials: %s" % credentials)
+                         + " credentials: %s", credentials)
         return credentials
 
     def get_primary_creds(self):
@@ -356,7 +355,7 @@
         try:
             client.delete_router(router_id)
         except lib_exc.NotFound:
-            LOG.warning('router with name: %s not found for delete' %
+            LOG.warning('router with name: %s not found for delete',
                         router_name)
 
     def _clear_isolated_subnet(self, subnet_id, subnet_name):
@@ -364,7 +363,7 @@
         try:
             client.delete_subnet(subnet_id)
         except lib_exc.NotFound:
-            LOG.warning('subnet with name: %s not found for delete' %
+            LOG.warning('subnet with name: %s not found for delete',
                         subnet_name)
 
     def _clear_isolated_network(self, network_id, network_name):
@@ -372,7 +371,7 @@
         try:
             net_client.delete_network(network_id)
         except lib_exc.NotFound:
-            LOG.warning('network with name: %s not found for delete' %
+            LOG.warning('network with name: %s not found for delete',
                         network_name)
 
     def _cleanup_default_secgroup(self, tenant):
@@ -384,8 +383,8 @@
             try:
                 nsg_client.delete_security_group(secgroup['id'])
             except lib_exc.NotFound:
-                LOG.warning('Security group %s, id %s not found for clean-up' %
-                            (secgroup['name'], secgroup['id']))
+                LOG.warning('Security group %s, id %s not found for clean-up',
+                            secgroup['name'], secgroup['id'])
 
     def _clear_isolated_net_resources(self):
         client = self.routers_admin_client
@@ -405,7 +404,7 @@
                         creds.router['id'],
                         subnet_id=creds.subnet['id'])
                 except lib_exc.NotFound:
-                    LOG.warning('router with name: %s not found for delete' %
+                    LOG.warning('router with name: %s not found for delete',
                                 creds.router['name'])
                 self._clear_isolated_router(creds.router['id'],
                                             creds.router['name'])
@@ -426,7 +425,7 @@
             try:
                 self.creds_client.delete_user(creds.user_id)
             except lib_exc.NotFound:
-                LOG.warning("user with name: %s not found for delete" %
+                LOG.warning("user with name: %s not found for delete",
                             creds.username)
             # NOTE(zhufl): Only when neutron's security_group ext is
             # enabled, _cleanup_default_secgroup will not raise error. But
@@ -437,12 +436,12 @@
                 if self.neutron_available:
                     self._cleanup_default_secgroup(creds.tenant_id)
             except lib_exc.NotFound:
-                LOG.warning("failed to cleanup tenant %s's secgroup" %
+                LOG.warning("failed to cleanup tenant %s's secgroup",
                             creds.tenant_name)
             try:
                 self.creds_client.delete_project(creds.tenant_id)
             except lib_exc.NotFound:
-                LOG.warning("tenant with name: %s not found for delete" %
+                LOG.warning("tenant with name: %s not found for delete",
                             creds.tenant_name)
         self._creds = {}
 
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index f57c18a..f50edbd 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -122,5 +122,5 @@
             params.update({"networks": [{'uuid': network['id']}]})
         else:
             LOG.warning('The provided network dict: %s was invalid and did '
-                        'not contain an id' % network)
+                        'not contain an id', network)
     return params
diff --git a/tempest/common/image.py b/tempest/common/image.py
index 95a7d1a..3618f7e 100644
--- a/tempest/common/image.py
+++ b/tempest/common/image.py
@@ -15,8 +15,6 @@
 
 import copy
 
-import six
-
 
 def get_image_meta_from_headers(resp):
     meta = {'properties': {}}
@@ -55,13 +53,13 @@
     if copy_from is not None:
         headers['x-glance-api-copy-from'] = copy_from
 
-    for key, value in six.iteritems(fields_copy.pop('properties', {})):
+    for key, value in fields_copy.pop('properties', {}).items():
         headers['x-image-meta-property-%s' % key] = str(value)
 
-    for key, value in six.iteritems(fields_copy.pop('api', {})):
+    for key, value in fields_copy.pop('api', {}).items():
         headers['x-glance-api-property-%s' % key] = str(value)
 
-    for key, value in six.iteritems(fields_copy):
+    for key, value in fields_copy.items():
         headers['x-image-meta-%s' % key] = str(value)
 
     return headers
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index 3f68ae8..a92d16a 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -33,7 +33,7 @@
 def read_accounts_yaml(path):
     try:
         with open(path, 'r') as yaml_file:
-            accounts = yaml.load(yaml_file)
+            accounts = yaml.safe_load(yaml_file)
     except IOError:
         raise lib_exc.InvalidConfiguration(
             'The path for the test accounts file: %s '
@@ -120,7 +120,7 @@
             if 'resources' in account:
                 resources = account.pop('resources')
             temp_hash = hashlib.md5()
-            account_for_hash = dict((k, v) for (k, v) in six.iteritems(account)
+            account_for_hash = dict((k, v) for (k, v) in account.items()
                                     if k in cls.HASH_CRED_FIELDS)
             temp_hash.update(six.text_type(account_for_hash).encode('utf-8'))
             temp_hash_key = temp_hash.hexdigest()
@@ -158,8 +158,10 @@
                 if resource == 'network':
                     hash_dict['networks'][temp_hash_key] = resources[resource]
                 else:
-                    LOG.warning('Unknown resource type %s, ignoring this field'
-                                % resource)
+                    LOG.warning(
+                        'Unknown resource type %s, ignoring this field',
+                        resource
+                    )
         return hash_dict
 
     def is_multi_user(self):
@@ -245,7 +247,7 @@
         free_hash = self._get_free_hash(useable_hashes)
         clean_creds = self._sanitize_creds(
             self.hash_dict['creds'][free_hash])
-        LOG.info('%s allocated creds:\n%s' % (self.name, clean_creds))
+        LOG.info('%s allocated creds:\n%s', self.name, clean_creds)
         return self._wrap_creds_with_network(free_hash)
 
     @lockutils.synchronized('test_accounts_io', external=True)
@@ -253,7 +255,7 @@
         hash_path = os.path.join(self.accounts_dir, hash_string)
         if not os.path.isfile(hash_path):
             LOG.warning('Expected an account lock file %s to remove, but '
-                        'one did not exist' % hash_path)
+                        'one did not exist', hash_path)
         else:
             os.remove(hash_path)
             if not os.listdir(self.accounts_dir):
@@ -278,7 +280,7 @@
         _hash = self.get_hash(creds)
         clean_creds = self._sanitize_creds(self.hash_dict['creds'][_hash])
         self.remove_hash(_hash)
-        LOG.info("%s returned allocated creds:\n%s" % (self.name, clean_creds))
+        LOG.info("%s returned allocated creds:\n%s", self.name, clean_creds)
 
     def get_primary_creds(self):
         if self._creds.get('primary'):
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 9ec217f..009812e 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -87,7 +87,7 @@
         # Shell options below add more clearness on failures,
         # path is extended for some non-cirros guest oses (centos7)
         cmd = CONF.validation.ssh_shell_prologue + " " + cmd
-        LOG.debug("Remote command: %s" % cmd)
+        LOG.debug("Remote command: %s", cmd)
         return self.ssh_client.exec_command(cmd)
 
     @debug_ssh
@@ -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'
@@ -237,5 +248,5 @@
         except tempest.lib.exceptions.SSHExecCommandFailed:
             LOG.error("Couldn't mke2fs")
             cmd_why = 'sudo ls -lR /dev'
-            LOG.info("Contents of /dev: %s" % self.exec_command(cmd_why))
+            LOG.info("Contents of /dev: %s", self.exec_command(cmd_why))
             raise
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index a55ee32..88697c4 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -60,8 +60,7 @@
                 parent_group_id=security_group['id'], ip_protocol='icmp',
                 from_port=-1, to_port=-1)
     LOG.debug("SSH Validation resource security group with tcp and icmp "
-              "rules %s created"
-              % sg_name)
+              "rules %s created", sg_name)
     return security_group
 
 
@@ -73,7 +72,7 @@
             keypair_name = data_utils.rand_name('keypair')
             validation_data.update(os.keypairs_client.create_keypair(
                 name=keypair_name))
-            LOG.debug("Validation resource key %s created" % keypair_name)
+            LOG.debug("Validation resource key %s created", keypair_name)
         add_rule = False
         if validation_resources['security_group']:
             if validation_resources['security_group_rules']:
@@ -98,11 +97,13 @@
             try:
                 keypair_client.delete_keypair(keypair_name)
             except lib_exc.NotFound:
-                LOG.warning("Keypair %s is not found when attempting to delete"
-                            % keypair_name)
+                LOG.warning(
+                    "Keypair %s is not found when attempting to delete",
+                    keypair_name
+                )
             except Exception as exc:
-                LOG.exception('Exception raised while deleting key %s'
-                              % keypair_name)
+                LOG.exception('Exception raised while deleting key %s',
+                              keypair_name)
                 if not has_exception:
                     has_exception = exc
         if 'security_group' in validation_data:
@@ -113,15 +114,15 @@
                 security_group_client.wait_for_resource_deletion(sec_id)
             except lib_exc.NotFound:
                 LOG.warning("Security group %s is not found when attempting "
-                            "to delete" % sec_id)
+                            "to delete", sec_id)
             except lib_exc.Conflict as exc:
                 LOG.exception('Conflict while deleting security '
-                              'group %s VM might not be deleted ' % sec_id)
+                              'group %s VM might not be deleted', sec_id)
                 if not has_exception:
                     has_exception = exc
             except Exception as exc:
                 LOG.exception('Exception raised while deleting security '
-                              'group %s ' % sec_id)
+                              'group %s', sec_id)
                 if not has_exception:
                     has_exception = exc
         if 'floating_ip' in validation_data:
@@ -131,10 +132,9 @@
                 floating_client.delete_floating_ip(fip_id)
             except lib_exc.NotFound:
                 LOG.warning('Floating ip %s not found while attempting to '
-                            'delete' % fip_id)
+                            'delete', fip_id)
             except Exception as exc:
-                LOG.exception('Exception raised while deleting ip %s '
-                              % fip_id)
+                LOG.exception('Exception raised while deleting ip %s', fip_id)
                 if not has_exception:
                     has_exception = exc
     if has_exception:
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 981a922..8303caf 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -189,6 +189,25 @@
             raise lib_exc.TimeoutException(message)
 
 
+def wait_for_volume_retype(client, volume_id, new_volume_type):
+    """Waits for a Volume to have a new volume type."""
+    body = client.show_volume(volume_id)['volume']
+    current_volume_type = body['volume_type']
+    start = int(time.time())
+
+    while current_volume_type != new_volume_type:
+        time.sleep(client.build_interval)
+        body = client.show_volume(volume_id)['volume']
+        current_volume_type = body['volume_type']
+
+        if int(time.time()) - start >= client.build_timeout:
+            message = ('Volume %s failed to reach %s volume type (current %s) '
+                       'within the required time (%s s).' %
+                       (volume_id, new_volume_type, current_volume_type,
+                        client.build_timeout))
+            raise exceptions.TimeoutException(message)
+
+
 def wait_for_snapshot_status(client, snapshot_id, status):
     """Waits for a Snapshot to reach a given status."""
     body = client.show_snapshot(snapshot_id)['snapshot']
@@ -231,35 +250,6 @@
             raise lib_exc.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 lib_exc.TimeoutException(message)
-
-
 def wait_for_qos_operations(client, qos_id, operation, args=None):
     """Waits for a qos operations to be completed.
 
diff --git a/tempest/config.py b/tempest/config.py
index 47eb427..fe8c175 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -16,7 +16,6 @@
 from __future__ import print_function
 
 import functools
-import logging as std_logging
 import os
 import tempfile
 
@@ -171,7 +170,20 @@
     cfg.BoolOpt('admin_domain_scope',
                 default=False,
                 help="Whether keystone identity v3 policy required "
-                     "a domain scoped token to use admin APIs")
+                     "a domain scoped token to use admin APIs"),
+    # Security Compliance (PCI-DSS)
+    cfg.IntOpt('user_lockout_failure_attempts',
+               default=2,
+               help="The number of unsuccessful login attempts the user is "
+                    "allowed before having the account locked."),
+    cfg.IntOpt('user_lockout_duration',
+               default=5,
+               help="The number of seconds a user account will remain "
+                    "locked."),
+    cfg.IntOpt('user_unique_last_password_count',
+               default=2,
+               help="The number of passwords for a user that must be unique "
+                    "before an old password can be reused."),
 ]
 
 service_clients_group = cfg.OptGroup(name='service-clients',
@@ -207,8 +219,15 @@
     # TODO(rodrigods): Remove the reseller flag when Kilo and Liberty is end
     # of life.
     cfg.BoolOpt('reseller',
+                default=True,
+                help='Does the environment support reseller?',
+                deprecated_for_removal=True,
+                deprecated_reason="All supported version of OpenStack now "
+                                  "supports the 'reseller' feature"),
+    cfg.BoolOpt('security_compliance',
                 default=False,
-                help='Does the environment support reseller?')
+                help='Does the environment have the security compliance '
+                     'settings enabled?')
 ]
 
 compute_group = cfg.OptGroup(name='compute',
@@ -312,9 +331,12 @@
     # NOTE(mriedem): This is a feature toggle for bug 1175464 which is fixed in
     # mitaka and newton. This option can be removed after liberty-eol.
     cfg.BoolOpt('allow_port_security_disabled',
-                default=False,
+                default=True,
                 help='Does the test environment support creating ports in a '
-                     'network where port security is disabled?'),
+                     'network where port security is disabled?',
+                deprecated_for_removal=True,
+                deprecated_reason='This config switch was added for Liberty '
+                                  'which is not supported anymore.'),
     cfg.BoolOpt('disk_config',
                 default=True,
                 help="If false, skip disk config tests"),
@@ -422,10 +444,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 '
@@ -565,6 +593,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,
@@ -774,6 +806,9 @@
     cfg.BoolOpt('clone',
                 default=True,
                 help='Runs Cinder volume clone test'),
+    cfg.BoolOpt('manage_snapshot',
+                default=False,
+                help='Runs Cinder manage snapshot tests'),
     cfg.ListOpt('api_extensions',
                 default=['all'],
                 help='A list of enabled volume extensions with a special '
@@ -790,8 +825,11 @@
                 help="Is the v3 volume API enabled"),
     # TODO(ynesenenko): Remove volume_services once liberty-eol happens.
     cfg.BoolOpt('volume_services',
-                default=False,
-                help='Extract correct host info from host@backend')
+                default=True,
+                help='Extract correct host info from host@backend',
+                deprecated_for_removal=True,
+                deprecated_reason='This config switch was added for Liberty '
+                                  'which is not supported anymore.')
 ]
 
 
@@ -969,9 +1007,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",
@@ -1026,56 +1061,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.")
-]
-
-
 DefaultGroup = [
     cfg.StrOpt('resources_prefix',
                default='tempest',
@@ -1105,7 +1090,6 @@
     (scenario_group, ScenarioGroup),
     (service_available_group, ServiceAvailableGroup),
     (debug_group, DebugGroup),
-    (baremetal_group, BaremetalGroup),
     (input_scenario_group, InputScenarioGroup),
     (None, DefaultGroup)
 ]
@@ -1168,7 +1152,6 @@
         self.scenario = _CONF.scenario
         self.service_available = _CONF.service_available
         self.debug = _CONF.debug
-        self.baremetal = _CONF.baremetal
         self.input_scenario = _CONF['input-scenario']
         logging.tempest_set_log_file('tempest.log')
 
@@ -1211,11 +1194,11 @@
 
         logging.setup(_CONF, 'tempest')
         LOG = logging.getLogger('tempest')
-        LOG.info("Using tempest config file %s" % path)
+        LOG.info("Using tempest config file %s", path)
         register_opts()
         self._set_attrs()
         if parse_conf:
-            _CONF.log_opt_values(LOG, std_logging.DEBUG)
+            _CONF.log_opt_values(LOG, logging.DEBUG)
 
 
 class TempestConfigProxy(object):
@@ -1223,14 +1206,14 @@
     _path = None
 
     _extra_log_defaults = [
-        ('paramiko.transport', std_logging.INFO),
-        ('requests.packages.urllib3.connectionpool', std_logging.WARN),
+        ('paramiko.transport', logging.INFO),
+        ('requests.packages.urllib3.connectionpool', logging.WARN),
     ]
 
     def _fix_log_levels(self):
         """Tweak the oslo log defaults."""
         for name, level in self._extra_log_defaults:
-            std_logging.getLogger(name).setLevel(level)
+            logging.getLogger(name).logger.setLevel(level)
 
     def __getattr__(self, attr):
         if not self._config:
diff --git a/tempest/lib/api_schema/response/compute/v2_1/aggregates.py b/tempest/lib/api_schema/response/compute/v2_1/aggregates.py
index 1a9fe41..3289a34 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/aggregates.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/aggregates.py
@@ -14,17 +14,19 @@
 
 import copy
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 # create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
 aggregate_for_create = {
     'type': 'object',
     'properties': {
         'availability_zone': {'type': ['string', 'null']},
-        'created_at': {'type': 'string'},
+        'created_at': parameter_types.date_time,
         'deleted': {'type': 'boolean'},
-        'deleted_at': {'type': ['string', 'null']},
+        'deleted_at': parameter_types.date_time_or_null,
         'id': {'type': 'integer'},
         'name': {'type': 'string'},
-        'updated_at': {'type': ['string', 'null']}
+        'updated_at': parameter_types.date_time_or_null
     },
     'additionalProperties': False,
     'required': ['availability_zone', 'created_at', 'deleted',
@@ -69,9 +71,7 @@
 # The 'updated_at' attribute of 'update_aggregate' can't be null.
 update_aggregate = copy.deepcopy(get_aggregate)
 update_aggregate['response_body']['properties']['aggregate']['properties'][
-    'updated_at'] = {
-        'type': 'string'
-    }
+    'updated_at'] = parameter_types.date_time
 
 delete_aggregate = {
     'status_code': [200]
diff --git a/tempest/lib/api_schema/response/compute/v2_1/availability_zone.py b/tempest/lib/api_schema/response/compute/v2_1/availability_zone.py
index d9aebce..f7b77a1 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/availability_zone.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/availability_zone.py
@@ -14,6 +14,8 @@
 
 import copy
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 
 base = {
     'status_code': [200],
@@ -61,7 +63,7 @@
                     'properties': {
                         'available': {'type': 'boolean'},
                         'active': {'type': 'boolean'},
-                        'updated_at': {'type': ['string', 'null']}
+                        'updated_at': parameter_types.date_time_or_null
                     },
                     'additionalProperties': False,
                     'required': ['available', 'active', 'updated_at']
diff --git a/tempest/lib/api_schema/response/compute/v2_1/extensions.py b/tempest/lib/api_schema/response/compute/v2_1/extensions.py
index a6a455c..b5962d7 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/extensions.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/extensions.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 list_extensions = {
     'status_code': [200],
     'response_body': {
@@ -22,10 +24,7 @@
                 'items': {
                     'type': 'object',
                     'properties': {
-                        'updated': {
-                            'type': 'string',
-                            'format': 'data-time'
-                        },
+                        'updated': parameter_types.date_time,
                         'name': {'type': 'string'},
                         'links': {'type': 'array'},
                         'namespace': {
diff --git a/tempest/lib/api_schema/response/compute/v2_1/hosts.py b/tempest/lib/api_schema/response/compute/v2_1/hosts.py
index ae70ff1..cae3435 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/hosts.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/hosts.py
@@ -111,6 +111,9 @@
             'status': {'enum': ['enabled', 'disabled']}
         },
         'additionalProperties': False,
-        'required': ['host', 'maintenance_mode', 'status']
+        'anyOf': [
+            {'required': ['host', 'status']},
+            {'required': ['host', 'maintenance_mode']}
+        ]
     }
 }
diff --git a/tempest/lib/api_schema/response/compute/v2_1/images.py b/tempest/lib/api_schema/response/compute/v2_1/images.py
index f65b9d8..156ff4a 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/images.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/images.py
@@ -26,10 +26,10 @@
     'properties': {
         'id': {'type': 'string'},
         'status': {'enum': image_status_enums},
-        'updated': {'type': 'string'},
+        'updated': parameter_types.date_time,
         'links': image_links,
         'name': {'type': ['string', 'null']},
-        'created': {'type': 'string'},
+        'created': parameter_types.date_time,
         'minDisk': {'type': 'integer'},
         'minRam': {'type': 'integer'},
         'progress': {'type': 'integer'},
diff --git a/tempest/lib/api_schema/response/compute/v2_1/keypairs.py b/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
index 9c04c79..2828097 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 get_keypair = {
     'status_code': [200],
     'response_body': {
@@ -25,9 +27,9 @@
                     'fingerprint': {'type': 'string'},
                     'user_id': {'type': 'string'},
                     'deleted': {'type': 'boolean'},
-                    'created_at': {'type': 'string'},
-                    'updated_at': {'type': ['string', 'null']},
-                    'deleted_at': {'type': ['string', 'null']},
+                    'created_at': parameter_types.date_time,
+                    'updated_at': parameter_types.date_time_or_null,
+                    'deleted_at': parameter_types.date_time_or_null,
                     'id': {'type': 'integer'}
 
                 },
diff --git a/tempest/lib/api_schema/response/compute/v2_1/migrations.py b/tempest/lib/api_schema/response/compute/v2_1/migrations.py
index b7d66ea..c50286d 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/migrations.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/migrations.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 list_migrations = {
     'status_code': [200],
     'response_body': {
@@ -32,8 +34,8 @@
                         'dest_host': {'type': ['string', 'null']},
                         'old_instance_type_id': {'type': ['integer', 'null']},
                         'new_instance_type_id': {'type': ['integer', 'null']},
-                        'created_at': {'type': 'string'},
-                        'updated_at': {'type': ['string', 'null']}
+                        'created_at': parameter_types.date_time,
+                        'updated_at': parameter_types.date_time_or_null
                     },
                     'additionalProperties': False,
                     'required': [
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 3cc5ca4..a3c9099 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
@@ -81,6 +81,16 @@
     }
 }
 
+date_time = {
+    'type': 'string',
+    'format': 'iso8601-date-time'
+}
+
+date_time_or_null = {
+    'type': ['string', 'null'],
+    'format': 'iso8601-date-time'
+}
+
 response_header = {
     'connection': {'type': 'string'},
     'content-length': {'type': 'string'},
@@ -89,9 +99,14 @@
     'x-compute-request-id': {'type': 'string'},
     'vary': {'type': 'string'},
     'x-openstack-nova-api-version': {'type': 'string'},
+    # NOTE(gmann): Validating this as string only as this
+    # date in header is returned in different format than
+    # ISO 8601 date time format which is not consistent with
+    # other date-time format in nova.
+    # This API is already deprecated so not worth to fix
+    # on nova side.
     'date': {
-        'type': 'string',
-        'format': 'data-time'
+        'type': 'string'
     }
 }
 
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 63e8467..4ccca6f 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -118,8 +118,8 @@
         },
         'user_id': {'type': 'string'},
         'tenant_id': {'type': 'string'},
-        'created': {'type': 'string'},
-        'updated': {'type': 'string'},
+        'created': parameter_types.date_time,
+        'updated': parameter_types.date_time,
         'progress': {'type': 'integer'},
         'metadata': {'type': 'object'},
         'links': parameter_types.links,
@@ -238,14 +238,17 @@
     'status_code': [200],
     'response_body': {
         'type': 'object',
-        'properties': {
-            'adminPass': {'type': 'string'}
-        },
         'additionalProperties': False,
-        'required': ['adminPass']
     }
 }
 
+rescue_server_with_admin_pass = copy.deepcopy(rescue_server)
+rescue_server_with_admin_pass['response_body'].update(
+    {'properties': {'adminPass': {'type': 'string'}}})
+rescue_server_with_admin_pass['response_body'].update(
+    {'required': ['adminPass']})
+
+
 list_virtual_interfaces = {
     'status_code': [200],
     'response_body': {
@@ -399,7 +402,7 @@
         'request_id': {'type': 'string'},
         'user_id': {'type': 'string'},
         'project_id': {'type': 'string'},
-        'start_time': {'type': 'string'},
+        'start_time': parameter_types.date_time,
         'message': {'type': ['string', 'null']},
         'instance_uuid': {'type': 'string'}
     },
@@ -414,8 +417,8 @@
         'type': 'object',
         'properties': {
             'event': {'type': 'string'},
-            'start_time': {'type': 'string'},
-            'finish_time': {'type': 'string'},
+            'start_time': parameter_types.date_time,
+            'finish_time': parameter_types.date_time,
             'result': {'type': 'string'},
             'traceback': {'type': ['string', 'null']}
         },
diff --git a/tempest/lib/api_schema/response/compute/v2_1/services.py b/tempest/lib/api_schema/response/compute/v2_1/services.py
index ddef7b2..6949f86 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/services.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/services.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 list_services = {
     'status_code': [200],
     'response_body': {
@@ -29,7 +31,7 @@
                         'state': {'type': 'string'},
                         'binary': {'type': 'string'},
                         'status': {'type': 'string'},
-                        'updated_at': {'type': ['string', 'null']},
+                        'updated_at': parameter_types.date_time_or_null,
                         'disabled_reason': {'type': ['string', 'null']}
                     },
                     'additionalProperties': False,
diff --git a/tempest/lib/api_schema/response/compute/v2_1/snapshots.py b/tempest/lib/api_schema/response/compute/v2_1/snapshots.py
index 01a524b..826f854 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/snapshots.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/snapshots.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 common_snapshot_info = {
     'type': 'object',
     'properties': {
@@ -20,7 +22,7 @@
         'volumeId': {'type': 'string'},
         'status': {'type': 'string'},
         'size': {'type': 'integer'},
-        'createdAt': {'type': 'string'},
+        'createdAt': parameter_types.date_time,
         'displayName': {'type': ['string', 'null']},
         'displayDescription': {'type': ['string', 'null']}
     },
diff --git a/tempest/lib/api_schema/response/compute/v2_1/tenant_usages.py b/tempest/lib/api_schema/response/compute/v2_1/tenant_usages.py
index d51ef12..b531d2e 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/tenant_usages.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/tenant_usages.py
@@ -14,24 +14,21 @@
 
 import copy
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 _server_usages = {
     'type': 'array',
     'items': {
         'type': 'object',
         'properties': {
-            'ended_at': {
-                'oneOf': [
-                    {'type': 'string'},
-                    {'type': 'null'}
-                ]
-            },
+            'ended_at': parameter_types.date_time_or_null,
             'flavor': {'type': 'string'},
             'hours': {'type': 'number'},
             'instance_id': {'type': 'string'},
             'local_gb': {'type': 'integer'},
             'memory_mb': {'type': 'integer'},
             'name': {'type': 'string'},
-            'started_at': {'type': 'string'},
+            'started_at': parameter_types.date_time,
             'state': {'type': 'string'},
             'tenant_id': {'type': 'string'},
             'uptime': {'type': 'integer'},
@@ -47,8 +44,8 @@
     'type': 'object',
     'properties': {
         'server_usages': _server_usages,
-        'start': {'type': 'string'},
-        'stop': {'type': 'string'},
+        'start': parameter_types.date_time,
+        'stop': parameter_types.date_time,
         'tenant_id': {'type': 'string'},
         'total_hours': {'type': 'number'},
         'total_local_gb_usage': {'type': 'number'},
diff --git a/tempest/lib/api_schema/response/compute/v2_1/versions.py b/tempest/lib/api_schema/response/compute/v2_1/versions.py
index 08a9fab..7f56239 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/versions.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/versions.py
@@ -14,6 +14,8 @@
 
 import copy
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 
 _version = {
     'type': 'object',
@@ -33,7 +35,7 @@
             }
         },
         'status': {'type': 'string'},
-        'updated': {'type': 'string', 'format': 'date-time'},
+        'updated': parameter_types.date_time,
         'version': {'type': 'string'},
         'min_version': {'type': 'string'},
         'media-types': {
diff --git a/tempest/lib/api_schema/response/compute/v2_1/volumes.py b/tempest/lib/api_schema/response/compute/v2_1/volumes.py
index bb34acb..c35dae9 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/volumes.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/volumes.py
@@ -12,6 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+
 create_get_volume = {
     'status_code': [200],
     'response_body': {
@@ -24,7 +26,7 @@
                     'status': {'type': 'string'},
                     'displayName': {'type': ['string', 'null']},
                     'availabilityZone': {'type': 'string'},
-                    'createdAt': {'type': 'string'},
+                    'createdAt': parameter_types.date_time,
                     'displayDescription': {'type': ['string', 'null']},
                     'volumeType': {'type': ['string', 'null']},
                     'snapshotId': {'type': ['string', 'null']},
@@ -75,7 +77,7 @@
                         'status': {'type': 'string'},
                         'displayName': {'type': ['string', 'null']},
                         'availabilityZone': {'type': 'string'},
-                        'createdAt': {'type': 'string'},
+                        'createdAt': parameter_types.date_time,
                         'displayDescription': {'type': ['string', 'null']},
                         'volumeType': {'type': ['string', 'null']},
                         'snapshotId': {'type': ['string', 'null']},
diff --git a/tempest/lib/cli/base.py b/tempest/lib/cli/base.py
index 72a15b5..5468a7b 100644
--- a/tempest/lib/cli/base.py
+++ b/tempest/lib/cli/base.py
@@ -13,11 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
 import os
 import shlex
 import subprocess
 
+from oslo_log import log as logging
 import six
 
 from tempest.lib import base
@@ -54,7 +54,7 @@
     cmd = ' '.join([prefix, os.path.join(cli_dir, cmd),
                     flags, action, params])
     cmd = cmd.strip()
-    LOG.info("running: '%s'" % cmd)
+    LOG.info("running: '%s'", cmd)
     if six.PY2:
         cmd = cmd.encode('utf-8')
     cmd = shlex.split(cmd)
diff --git a/tempest/lib/cli/output_parser.py b/tempest/lib/cli/output_parser.py
index 0313505..716f374 100644
--- a/tempest/lib/cli/output_parser.py
+++ b/tempest/lib/cli/output_parser.py
@@ -15,9 +15,10 @@
 
 """Collection of utilities for parsing CLI clients output."""
 
-import logging
 import re
 
+from oslo_log import log as logging
+
 from tempest.lib import exceptions
 
 
@@ -112,7 +113,7 @@
             if label is None:
                 label = line
             else:
-                LOG.warning('Invalid line between tables: %s' % line)
+                LOG.warning('Invalid line between tables: %s', line)
     if len(table_) > 0:
         LOG.warning('Missing end of table')
 
@@ -140,7 +141,7 @@
             columns = _table_columns(line)
             continue
         if '|' not in line:
-            LOG.warning('skipping invalid table line: %s' % line)
+            LOG.warning('skipping invalid table line: %s', line)
             continue
         row = []
         for col in columns:
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index 88ce775..2fe957b 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -26,7 +26,10 @@
 from oslo_utils import uuidutils
 import six.moves.urllib.parse as urlparse
 
-DECORATOR_MODULE = 'test'
+# TODO(oomichi): Need to remove this after switching all modules to decorators
+OLD_DECORATOR_MODULE = 'test'
+
+DECORATOR_MODULE = 'decorators'
 DECORATOR_NAME = 'idempotent_id'
 DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
 IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
@@ -124,7 +127,8 @@
                 hasattr(decorator.func, 'attr') and
                 decorator.func.attr == DECORATOR_NAME and
                 hasattr(decorator.func, 'value') and
-                decorator.func.value.id == DECORATOR_MODULE):
+                (decorator.func.value.id == DECORATOR_MODULE or
+                 decorator.func.value.id == OLD_DECORATOR_MODULE)):
                 for arg in decorator.args:
                     idempotent_id = ast.literal_eval(arg)
         return idempotent_id
diff --git a/tempest/lib/cmd/skip_tracker.py b/tempest/lib/cmd/skip_tracker.py
index d95aa46..07b811d 100755
--- a/tempest/lib/cmd/skip_tracker.py
+++ b/tempest/lib/cmd/skip_tracker.py
@@ -21,16 +21,18 @@
 """
 
 import argparse
-import logging
 import os
 import re
 
+from oslo_log import log as logging
+
 try:
     from launchpadlib import launchpad
 except ImportError:
     launchpad = None
 
 LPCACHEDIR = os.path.expanduser('~/.launchpadlib/cache')
+LOG = logging.getLogger(__name__)
 
 
 def parse_args():
@@ -40,11 +42,11 @@
 
 
 def info(msg, *args, **kwargs):
-    logging.info(msg, *args, **kwargs)
+    LOG.info(msg, *args, **kwargs)
 
 
 def debug(msg, *args, **kwargs):
-    logging.debug(msg, *args, **kwargs)
+    LOG.debug(msg, *args, **kwargs)
 
 
 def find_skips(start):
@@ -110,8 +112,6 @@
 
 
 def main():
-    logging.basicConfig(format='%(levelname)s: %(message)s',
-                        level=logging.INFO)
     parser = parse_args()
     results = find_skips(parser.test_path)
     unique_bugs = sorted(set([bug for (method, bug) in get_results(results)]))
diff --git a/tempest/lib/common/cred_client.py b/tempest/lib/common/cred_client.py
index 3f10dee..ea06011 100644
--- a/tempest/lib/common/cred_client.py
+++ b/tempest/lib/common/cred_client.py
@@ -78,8 +78,8 @@
                                                           user['id'],
                                                           role['id'])
         except lib_exc.Conflict:
-            LOG.debug("Role %s already assigned on project %s for user %s" % (
-                role['id'], project['id'], user['id']))
+            LOG.debug("Role %s already assigned on project %s for user %s",
+                      role['id'], project['id'], user['id'])
 
     @abc.abstractmethod
     def get_credentials(self, user, project, password):
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index 86ea26e..8a47d44 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 import urllib3
 
 
@@ -39,7 +40,9 @@
         class Response(dict):
             def __init__(self, info):
                 for key, value in info.getheaders().items():
-                    self[key.lower()] = value
+                    # We assume HTTP header name to be string, not random
+                    # bytes, thus ensure we have string keys.
+                    self[six.u(key).lower()] = value
                 self.status = info.status
                 self['status'] = str(self.status)
                 self.reason = info.reason
diff --git a/tempest/lib/common/jsonschema_validator.py b/tempest/lib/common/jsonschema_validator.py
new file mode 100644
index 0000000..bbdf382
--- /dev/null
+++ b/tempest/lib/common/jsonschema_validator.py
@@ -0,0 +1,39 @@
+# 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.
+
+import jsonschema
+from oslo_utils import timeutils
+
+# JSON Schema validator and format checker used for JSON Schema validation
+JSONSCHEMA_VALIDATOR = jsonschema.Draft4Validator
+FORMAT_CHECKER = jsonschema.draft4_format_checker
+
+
+# NOTE(gmann): Add customized format checker for 'date-time' format because:
+# 1. jsonschema needs strict_rfc3339 or isodate module to be installed
+#    for proper date-time checking as per rfc3339.
+# 2. Nova or other OpenStack components handle the date time format as
+#    ISO 8601 which is defined in oslo_utils.timeutils
+# so this checker will validate the date-time as defined in
+# oslo_utils.timeutils
+@FORMAT_CHECKER.checks('iso8601-date-time')
+def _validate_datetime_format(instance):
+    try:
+        if isinstance(instance, jsonschema.compat.str_types):
+            timeutils.parse_isotime(instance)
+    except ValueError:
+        return False
+    else:
+        return True
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 2d2771f..d0e21ff 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -16,7 +16,6 @@
 
 import collections
 import email.utils
-import logging as real_logging
 import re
 import time
 
@@ -26,6 +25,7 @@
 import six
 
 from tempest.lib.common import http
+from tempest.lib.common import jsonschema_validator
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 
@@ -39,8 +39,8 @@
 HTTP_REDIRECTION = (300, 301, 302, 303, 304, 305, 306, 307)
 
 # JSON Schema validator and format checker used for JSON Schema validation
-JSONSCHEMA_VALIDATOR = jsonschema.Draft4Validator
-FORMAT_CHECKER = jsonschema.draft4_format_checker
+JSONSCHEMA_VALIDATOR = jsonschema_validator.JSONSCHEMA_VALIDATOR
+FORMAT_CHECKER = jsonschema_validator.FORMAT_CHECKER
 
 
 class RestClient(object):
@@ -248,8 +248,8 @@
         # NOTE(afazekas): the http status code above 400 is processed by
         # the _error_checker method
         if read_code < 400:
-            pattern = """Unexpected http success status code {0},
-                         The expected status code is {1}"""
+            pattern = ("Unexpected http success status code {0}, "
+                       "The expected status code is {1}")
             if ((not isinstance(expected_code, list) and
                  (read_code != expected_code)) or
                 (isinstance(expected_code, list) and
@@ -406,8 +406,8 @@
     def _log_request_start(self, method, req_url):
         caller_name = test_utils.find_test_caller()
         if self.trace_requests and re.search(self.trace_requests, caller_name):
-            self.LOG.debug('Starting Request (%s): %s %s' %
-                           (caller_name, method, req_url))
+            self.LOG.debug('Starting Request (%s): %s %s', caller_name,
+                           method, req_url)
 
     def _log_request_full(self, resp, req_headers=None, req_body=None,
                           resp_body=None, extra=None):
@@ -423,11 +423,11 @@
         Body: %s"""
 
         self.LOG.debug(
-            log_fmt % (
-                str(req_headers),
-                self._safe_body(req_body),
-                str(resp_log),
-                self._safe_body(resp_body)),
+            log_fmt,
+            str(req_headers),
+            self._safe_body(req_body),
+            str(resp_log),
+            self._safe_body(resp_body),
             extra=extra)
 
     def _log_request(self, method, req_url, resp,
@@ -445,17 +445,17 @@
         if secs:
             secs = " %.3fs" % secs
         self.LOG.info(
-            'Request (%s): %s %s %s%s' % (
-                caller_name,
-                resp['status'],
-                method,
-                req_url,
-                secs),
+            'Request (%s): %s %s %s%s',
+            caller_name,
+            resp['status'],
+            method,
+            req_url,
+            secs,
             extra=extra)
 
         # Also look everything at DEBUG if you want to filter this
         # out, don't run at debug.
-        if self.LOG.isEnabledFor(real_logging.DEBUG):
+        if self.LOG.isEnabledFor(logging.DEBUG):
             self._log_request_full(resp, req_headers, req_body,
                                    resp_body, extra)
 
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index 4226cd6..5e65bee 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -37,7 +37,30 @@
 
     def __init__(self, host, username, password=None, timeout=300, pkey=None,
                  channel_timeout=10, look_for_keys=False, key_filename=None,
-                 port=22):
+                 port=22, proxy_client=None):
+        """SSH client.
+
+        Many of parameters are just passed to the underlying implementation
+        as it is.  See the paramiko documentation for more details.
+        http://docs.paramiko.org/en/2.1/api/client.html#paramiko.client.SSHClient.connect
+
+        :param host: Host to login.
+        :param username: SSH username.
+        :param password: SSH password, or a password to unlock private key.
+        :param timeout: Timeout in seconds, including retries.
+            Default is 300 seconds.
+        :param pkey: Private key.
+        :param channel_timeout: Channel timeout in seconds, passed to the
+            paramiko.  Default is 10 seconds.
+        :param look_for_keys: Whether or not to search for private keys
+            in ``~/.ssh``.  Default is False.
+        :param key_filename: Filename for private key to use.
+        :param port: SSH port number.
+        :param proxy_client: Another SSH client to provide a transport
+            for ssh-over-ssh.  The default is None, which means
+            not to use ssh-over-ssh.
+        :type proxy_client: ``tempest.lib.common.ssh.Client`` object
+        """
         self.host = host
         self.username = username
         self.port = port
@@ -51,6 +74,8 @@
         self.timeout = int(timeout)
         self.channel_timeout = float(channel_timeout)
         self.buf_size = 1024
+        self.proxy_client = proxy_client
+        self._proxy_conn = None
 
     def _get_ssh_connection(self, sleep=1.5, backoff=1):
         """Returns an ssh connection to the specified host."""
@@ -59,6 +84,10 @@
         ssh.set_missing_host_key_policy(
             paramiko.AutoAddPolicy())
         _start_time = time.time()
+        if self.proxy_client is not None:
+            proxy_chan = self._get_proxy_channel()
+        else:
+            proxy_chan = None
         if self.pkey is not None:
             LOG.info("Creating ssh connection to '%s:%d' as '%s'"
                      " with public key authentication",
@@ -74,7 +103,8 @@
                             password=self.password,
                             look_for_keys=self.look_for_keys,
                             key_filename=self.key_filename,
-                            timeout=self.channel_timeout, pkey=self.pkey)
+                            timeout=self.channel_timeout, pkey=self.pkey,
+                            sock=proxy_chan)
                 LOG.info("ssh connection to %s@%s successfully created",
                          self.username, self.host)
                 return ssh
@@ -175,3 +205,14 @@
         """Raises an exception when we can not connect to server via ssh."""
         connection = self._get_ssh_connection()
         connection.close()
+
+    def _get_proxy_channel(self):
+        conn = self.proxy_client._get_ssh_connection()
+        # Keep a reference to avoid g/c
+        # https://github.com/paramiko/paramiko/issues/440
+        self._proxy_conn = conn
+        transport = conn.get_transport()
+        chan = transport.open_session()
+        cmd = 'nc %s %s' % (self.host, self.port)
+        chan.exec_command(cmd)
+        return chan
diff --git a/tempest/lib/common/utils/test_utils.py b/tempest/lib/common/utils/test_utils.py
index 3b28701..bd0db7c 100644
--- a/tempest/lib/common/utils/test_utils.py
+++ b/tempest/lib/common/utils/test_utils.py
@@ -74,7 +74,7 @@
     # prevents frame leaks
     del frame
     if caller_name is None:
-        LOG.debug("Sane call name not found in %s" % names)
+        LOG.debug("Sane call name not found in %s", names)
     return caller_name
 
 
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index 0e8e3c6..445e8bd 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -17,7 +17,8 @@
 import copy
 import importlib
 import inspect
-import logging
+
+from oslo_log import log as logging
 
 from tempest.lib import auth
 from tempest.lib.common.utils import misc
@@ -41,6 +42,7 @@
     return {
         'compute': compute,
         'identity.v2': identity.v2,
+        'identity.v3': identity.v3,
         'image.v1': image.v1,
         'image.v2': image.v2,
         'network': network,
@@ -55,7 +57,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.v3', 'object-storage'])
+    return set(['object-storage'])
 
 
 def available_modules():
@@ -278,7 +280,7 @@
         a dictionary ready to be injected in kwargs.
 
         Exceptions are:
-        - Token clients for 'identity' have a very different interface
+        - Token clients for 'identity' must be given an 'auth_url' parameter
         - Volume client for 'volume' accepts 'default_volume_size'
         - Servers client from 'compute' accepts 'enable_instance_password'
 
@@ -373,7 +375,7 @@
                 except Exception:
                     LOG.exception(
                         'Failed to register service client from plugin %s '
-                        'with parameters %s' % (plugin, service_client))
+                        'with parameters %s', plugin, service_client)
                     raise
 
     def register_service_client_module(self, name, service_version,
diff --git a/tempest/lib/services/compute/flavors_client.py b/tempest/lib/services/compute/flavors_client.py
index 4d1044b..a83c68b 100644
--- a/tempest/lib/services/compute/flavors_client.py
+++ b/tempest/lib/services/compute/flavors_client.py
@@ -67,9 +67,9 @@
         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})
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index 24557d8..50ce32e 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -100,7 +100,7 @@
         any changes.
         :param disk_config: The name is changed to OS-DCF:diskConfig
         """
-        if kwargs.get('disk_config'):
+        if 'disk_config' in kwargs:
             kwargs['OS-DCF:diskConfig'] = kwargs.pop('disk_config')
 
         post_body = json.dumps({'server': kwargs})
@@ -616,7 +616,11 @@
         API reference:
         http://developer.openstack.org/api-ref-compute-v2.1.html#rescue
         """
-        return self.action(server_id, 'rescue', schema.rescue_server, **kwargs)
+        if self.enable_instance_password:
+            rescue_schema = schema.rescue_server_with_admin_pass
+        else:
+            rescue_schema = schema.rescue_server
+        return self.action(server_id, 'rescue', rescue_schema, **kwargs)
 
     def unrescue_server(self, server_id):
         """Unrescue the provided server.
diff --git a/tempest/lib/services/identity/__init__.py b/tempest/lib/services/identity/__init__.py
index e69de29..941a10e 100644
--- a/tempest/lib/services/identity/__init__.py
+++ b/tempest/lib/services/identity/__init__.py
@@ -0,0 +1,18 @@
+# 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.identity import v2
+from tempest.lib.services.identity import v3
+
+__all__ = ['v2', 'v3']
diff --git a/tempest/lib/services/identity/v2/token_client.py b/tempest/lib/services/identity/v2/token_client.py
index a5d7c86..458c862 100644
--- a/tempest/lib/services/identity/v2/token_client.py
+++ b/tempest/lib/services/identity/v2/token_client.py
@@ -23,7 +23,22 @@
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
                  ca_certs=None, trace_requests=None, **kwargs):
+        """Initialises the Token client
+
+        :param auth_url: URL to which the token request is sent
+        :param disable_ssl_certificate_validation: pass-through to rest client
+        :param ca_certs: pass-through to rest client
+        :param trace_requests: pass-through to rest client
+        :param kwargs: any extra parameter to pass through the rest client.
+               region, service and auth_provider will be ignored, if passed,
+               as they are not meaningful for token client
+        """
         dscv = disable_ssl_certificate_validation
+        # NOTE(andreaf) region, service and auth_provider are passed
+        # positionally with None. Having them in kwargs would raise a
+        # "multiple values for keyword arguments" error
+        for unwanted_kwargs in ['region', 'service', 'auth_provider']:
+            kwargs.pop(unwanted_kwargs, None)
         super(TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
             ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
@@ -117,8 +132,8 @@
     LOG = logging.getLogger(__name__)
 
     def _warn(self):
-        self.LOG.warning("%s class was deprecated and renamed to %s" %
-                         (self.__class__.__name__, 'TokenClient'))
+        self.LOG.warning("%s class was deprecated and renamed to %s",
+                         self.__class__.__name__, 'TokenClient')
 
     def __init__(self, *args, **kwargs):
         self._warn()
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index e69de29..8058d51 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -0,0 +1,38 @@
+# 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.identity.v3.credentials_client import \
+    CredentialsClient
+from tempest.lib.services.identity.v3.domains_client import DomainsClient
+from tempest.lib.services.identity.v3.endpoints_client import EndPointsClient
+from tempest.lib.services.identity.v3.groups_client import GroupsClient
+from tempest.lib.services.identity.v3.identity_client import IdentityClient
+from tempest.lib.services.identity.v3.inherited_roles_client import \
+    InheritedRolesClient
+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
+
+__all__ = ['CredentialsClient', 'DomainsClient', 'EndPointsClient',
+           'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
+           'PoliciesClient', 'ProjectsClient', 'RegionsClient',
+           'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
+           'V3TokenClient', 'TrustsClient', 'UsersClient', ]
diff --git a/tempest/services/identity/v3/json/domains_client.py b/tempest/lib/services/identity/v3/domains_client.py
similarity index 100%
rename from tempest/services/identity/v3/json/domains_client.py
rename to tempest/lib/services/identity/v3/domains_client.py
diff --git a/tempest/lib/services/identity/v3/token_client.py b/tempest/lib/services/identity/v3/token_client.py
index c1f7e7b..33f6f16 100644
--- a/tempest/lib/services/identity/v3/token_client.py
+++ b/tempest/lib/services/identity/v3/token_client.py
@@ -23,7 +23,19 @@
 
     def __init__(self, auth_url, disable_ssl_certificate_validation=None,
                  ca_certs=None, trace_requests=None, **kwargs):
+        """Initialises the Token client
+
+        :param auth_url: URL to which the token request is sent
+        :param disable_ssl_certificate_validation: pass-through to rest client
+        :param ca_certs: pass-through to rest client
+        :param trace_requests: pass-through to rest client
+        :param kwargs: any extra parameter to pass through the rest client.
+               Three kwargs are forbidden: region, service and auth_provider
+               as they are not meaningful for token client
+        """
         dscv = disable_ssl_certificate_validation
+        for unwanted_kwargs in ['region', 'service', 'auth_provider']:
+            kwargs.pop(unwanted_kwargs, None)
         super(V3TokenClient, self).__init__(
             None, None, None, disable_ssl_certificate_validation=dscv,
             ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
@@ -179,8 +191,8 @@
     LOG = logging.getLogger(__name__)
 
     def _warn(self):
-        self.LOG.warning("%s class was deprecated and renamed to %s" %
-                         (self.__class__.__name__, 'V3TokenClient'))
+        self.LOG.warning("%s class was deprecated and renamed to %s",
+                         self.__class__.__name__, 'V3TokenClient')
 
     def __init__(self, *args, **kwargs):
         self._warn()
diff --git a/tempest/lib/services/image/v1/images_client.py b/tempest/lib/services/image/v1/images_client.py
index e67a547..03f4c4b 100644
--- a/tempest/lib/services/image/v1/images_client.py
+++ b/tempest/lib/services/image/v1/images_client.py
@@ -115,7 +115,7 @@
         if detail:
             url += '/detail'
 
-        if kwargs.get('changes_since'):
+        if 'changes_since' in kwargs:
             kwargs['changes-since'] = kwargs.pop('changes_since')
 
         if len(kwargs) > 0:
diff --git a/tempest/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index d359d4b..7d973e5 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -15,12 +15,17 @@
 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_objects_client import \
+    NamespaceObjectsClient
 from tempest.lib.services.image.v2.namespace_properties_client import \
     NamespacePropertiesClient
+from tempest.lib.services.image.v2.namespace_tags_client import \
+    NamespaceTagsClient
 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', 'NamespacePropertiesClient',
+__all__ = ['ImageMembersClient', 'ImagesClient', 'NamespaceObjectsClient',
+           'NamespacePropertiesClient', 'NamespaceTagsClient',
            'NamespacesClient', 'ResourceTypesClient', 'SchemasClient']
diff --git a/tempest/lib/services/image/v2/namespace_objects_client.py b/tempest/lib/services/image/v2/namespace_objects_client.py
new file mode 100644
index 0000000..ac2e63e
--- /dev/null
+++ b/tempest/lib/services/image/v2/namespace_objects_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 six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class NamespaceObjectsClient(rest_client.RestClient):
+    api_version = "v2"
+
+    def list_namespace_objects(self, namespace, **kwargs):
+        """Lists all namespace objects.
+
+        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-objects
+        """
+        url = 'metadefs/namespaces/%s/objects' % namespace
+        if kwargs:
+            url += '?%s' % urllib.urlencode(kwargs)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def create_namespace_object(self, namespace, **kwargs):
+        """Create a namespace object
+
+        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-object
+        """
+        url = 'metadefs/namespaces/%s/objects' % 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 update_namespace_object(self, namespace, object_name, **kwargs):
+        """Update a namespace object
+
+        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-object
+        """
+        url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_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 show_namespace_object(self, namespace, object_name):
+        """Show a namespace object
+
+        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-object
+        """
+        url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_name)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_namespace_object(self, namespace, object_name):
+        """Delete a namespace object
+
+        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#delete-object
+        """
+        url = 'metadefs/namespaces/%s/objects/%s' % (namespace, object_name)
+        resp, _ = self.delete(url)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/image/v2/namespace_tags_client.py b/tempest/lib/services/image/v2/namespace_tags_client.py
new file mode 100644
index 0000000..ac8b569
--- /dev/null
+++ b/tempest/lib/services/image/v2/namespace_tags_client.py
@@ -0,0 +1,119 @@
+# 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 six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class NamespaceTagsClient(rest_client.RestClient):
+    api_version = "v2"
+
+    def create_namespace_tag(self, namespace, tag_name):
+        """Adds a tag to the list of namespace tag definitions.
+
+        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-tag-definition
+        """
+        url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+                                                  tag_name)
+        resp, body = self.post(url, None)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_namespace_tag(self, namespace, tag_name):
+        """Gets a definition for a tag.
+
+        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#get_tag_definition
+        """
+        url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+                                                  tag_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_tag(self, namespace, tag_name, **kwargs):
+        """Renames a tag 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-tag-definition
+        """
+        url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
+                                                  tag_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_tag(self, namespace, tag_name):
+        """Deletes a tag definition within 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#delete-tag-definition
+        """
+        url = 'metadefs/namespaces/%s/tags/%s' % (namespace, tag_name)
+        resp, _ = self.delete(url)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp)
+
+    def create_namespace_tags(self, namespace, **kwargs):
+        """Creates one or more tag 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#create-tags
+        """
+        url = 'metadefs/namespaces/%s/tags' % 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 list_namespace_tags(self, namespace, **params):
+        """Lists the tag definitions within 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-tags
+        """
+        url = 'metadefs/namespaces/%s/tags' % namespace
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_namespace_tags(self, namespace):
+        """Deletes all tag definitions within 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#delete-all-tag-definitions
+        """
+        url = 'metadefs/namespaces/%s/tags' % namespace
+        resp, _ = self.delete(url)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/volume/v2/__init__.py b/tempest/lib/services/volume/v2/__init__.py
index 837b4f6..8acad0f 100644
--- a/tempest/lib/services/volume/v2/__init__.py
+++ b/tempest/lib/services/volume/v2/__init__.py
@@ -27,6 +27,8 @@
 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.snapshot_manage_client import \
+    SnapshotManageClient
 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
@@ -34,4 +36,5 @@
 __all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
            'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
            'ServicesClient', 'SnapshotsClient', 'TypesClient', 'VolumesClient',
-           'LimitsClient', 'CapabilitiesClient', 'SchedulerStatsClient']
+           'LimitsClient', 'CapabilitiesClient', 'SchedulerStatsClient',
+           'SnapshotManageClient']
diff --git a/tempest/lib/services/volume/v2/snapshot_manage_client.py b/tempest/lib/services/volume/v2/snapshot_manage_client.py
new file mode 100644
index 0000000..aecd30b
--- /dev/null
+++ b/tempest/lib/services/volume/v2/snapshot_manage_client.py
@@ -0,0 +1,33 @@
+# 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 SnapshotManageClient(rest_client.RestClient):
+    """Snapshot manage V2 client."""
+
+    api_version = "v2"
+
+    def manage_snapshot(self, **kwargs):
+        """Manage a snapshot."""
+        post_body = json.dumps({'snapshot': kwargs})
+        url = 'os-snapshot-manage'
+        resp, body = self.post(url, post_body)
+        self.expected_success(202, resp.status)
+        body = json.loads(body)
+        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 6f51b51..2bdf1b1 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -184,3 +184,11 @@
         resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def unmanage_snapshot(self, snapshot_id):
+        """Unmanage a snapshot."""
+        post_body = json.dumps({'os-unmanage': {}})
+        url = 'snapshots/%s/action' % (snapshot_id)
+        resp, body = self.post(url, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 73544d9..8c930c3 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -20,7 +20,6 @@
 from oslo_log import log
 from oslo_serialization import jsonutils as json
 from oslo_utils import netutils
-import six
 
 from tempest.common import compute
 from tempest.common import image as common_image
@@ -157,7 +156,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'])
@@ -249,6 +248,27 @@
         volume = self.volumes_client.show_volume(volume['id'])['volume']
         return volume
 
+    def create_volume_type(self, client=None, name=None, backend_name=None):
+        if not client:
+            client = self.admin_volume_types_client
+        if not name:
+            class_name = self.__class__.__name__
+            name = data_utils.rand_name(class_name + '-volume-type')
+        randomized_name = data_utils.rand_name('scenario-type-' + name)
+
+        LOG.debug("Creating a volume type: %s on backend %s",
+                  randomized_name, backend_name)
+        extra_specs = {}
+        if backend_name:
+            extra_specs = {"volume_backend_name": backend_name}
+
+        body = client.create_volume_type(name=randomized_name,
+                                         extra_specs=extra_specs)
+        volume_type = body['volume_type']
+        self.assertIn('id', volume_type)
+        self.addCleanup(client.delete_volume_type, volume_type['id'])
+        return volume_type
+
     def _create_loginable_secgroup_rule(self, secgroup_id=None):
         _client = self.compute_security_groups_client
         _client_rules = self.compute_security_group_rules_client
@@ -380,9 +400,9 @@
         img_disk_format = CONF.scenario.img_disk_format
         img_properties = CONF.scenario.img_properties
         LOG.debug("paths: img: %s, container_format: %s, disk_format: %s, "
-                  "properties: %s, ami: %s, ari: %s, aki: %s" %
-                  (img_path, img_container_format, img_disk_format,
-                   img_properties, ami_img_path, ari_img_path, aki_img_path))
+                  "properties: %s, ami: %s, ari: %s, aki: %s",
+                  img_path, img_container_format, img_disk_format,
+                  img_properties, ami_img_path, ari_img_path, aki_img_path)
         try:
             image = self._image_create('scenario-img',
                                        img_container_format,
@@ -397,7 +417,7 @@
             image = self._image_create('scenario-ami', 'ami',
                                        path=ami_img_path,
                                        properties=properties)
-        LOG.debug("image:%s" % image)
+        LOG.debug("image:%s", image)
 
         return image
 
@@ -530,14 +550,14 @@
 
         caller = test_utils.find_test_caller()
         LOG.debug('%(caller)s begins to ping %(ip)s in %(timeout)s sec and the'
-                  ' expected result is %(should_succeed)s' % {
+                  ' expected result is %(should_succeed)s', {
                       'caller': caller, 'ip': ip_address, 'timeout': timeout,
                       'should_succeed':
                       'reachable' if should_succeed else 'unreachable'
                   })
         result = test_utils.call_until_true(ping, timeout, 1)
         LOG.debug('%(caller)s finishes ping %(ip)s in %(timeout)s sec and the '
-                  'ping result is %(result)s' % {
+                  'ping result is %(result)s', {
                       'caller': caller, 'ip': ip_address, 'timeout': timeout,
                       'result': 'expected' if result else 'unexpected'
                   })
@@ -578,8 +598,8 @@
                                           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' %
-                  (ip_address, username))
+        LOG.debug('checking network connections to IP %s with user: %s',
+                  ip_address, username)
         try:
             self.check_vm_connectivity(ip_address,
                                        username,
@@ -817,7 +837,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
@@ -920,7 +940,7 @@
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         try:
-            for net_name, ip_addresses in six.iteritems(server['addresses']):
+            for net_name, ip_addresses in server['addresses'].items():
                 for ip_address in ip_addresses:
                     self.check_vm_connectivity(ip_address['addr'],
                                                username,
@@ -948,7 +968,7 @@
                 source.ping_host(dest, nic=nic)
             except lib_exc.SSHExecCommandFailed:
                 LOG.warning('Failed to ping IP: %s via a ssh connection '
-                            'from: %s.' % (dest, source.ssh_client.host))
+                            'from: %s.', dest, source.ssh_client.host)
                 return not should_succeed
             return should_succeed
 
@@ -1189,7 +1209,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
@@ -1230,151 +1250,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 lib_exc.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 lib_exc.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"""
 
@@ -1392,19 +1267,6 @@
             cls.admin_encryption_types_client =\
                 cls.os_adm.encryption_types_client
 
-    def create_volume_type(self, client=None, name=None):
-        if not client:
-            client = self.admin_volume_types_client
-        if not name:
-            name = 'generic'
-        randomized_name = data_utils.rand_name('scenario-type-' + name)
-        LOG.debug("Creating a volume type: %s", randomized_name)
-        body = client.create_volume_type(
-            name=randomized_name)['volume_type']
-        self.assertIn('id', body)
-        self.addCleanup(client.delete_volume_type, body['id'])
-        return body
-
     def create_encryption_type(self, client=None, type_id=None, provider=None,
                                key_size=None, cipher=None,
                                control_location=None):
@@ -1460,7 +1322,7 @@
         self.container_client.create_container(name)
         # look for the container to assure it is created
         self.list_and_check_container_objects(name)
-        LOG.debug('Container %s created' % (name))
+        LOG.debug('Container %s created', name)
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.container_client.delete_container,
                         name)
@@ -1468,11 +1330,11 @@
 
     def delete_container(self, container_name):
         self.container_client.delete_container(container_name)
-        LOG.debug('Container %s deleted' % (container_name))
+        LOG.debug('Container %s deleted', container_name)
 
     def upload_object_to_container(self, container_name, obj_name=None):
         obj_name = obj_name or data_utils.rand_name('swift-scenario-object')
-        obj_data = data_utils.arbitrary_string()
+        obj_data = data_utils.random_bytes()
         self.object_client.create_object(container_name, obj_name, obj_data)
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.object_client.delete_object,
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 f2f17d2..c454ae2 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -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 0605902..1279484 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -198,12 +198,11 @@
     @test.idempotent_id('a4858f6c-401e-4155-9a49-d5cd053d1a2f')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
                           'Cold migration is not available.')
+    @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
+                          'Less than 2 compute nodes, skipping multinode '
+                          'tests.')
     @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)
@@ -220,3 +219,28 @@
         dst_host = self._get_host_for_server(server['id'])
 
         self.assertNotEqual(src_host, dst_host)
+
+    @test.idempotent_id('25b188d7-0183-4b1e-a11d-15840c8e2fd6')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration is not available.')
+    @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
+                          'Less than 2 compute nodes, skipping multinode '
+                          'tests.')
+    @test.services('compute', 'network')
+    def test_server_connectivity_cold_migration_revert(self):
+        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.revert_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.assertEqual(src_host, dst_host)
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 4a076e4..f9aa3e7 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -417,8 +417,9 @@
             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):
@@ -492,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
@@ -524,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')
@@ -607,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")
@@ -617,29 +615,44 @@
     def test_update_instance_port_admin_state(self):
         """Test to update admin_state_up attribute of instance port
 
-        1. Check public connectivity before updating
+        1. Check public and project connectivity before updating
                 admin_state_up attribute of instance port to False
-        2. Check public connectivity after updating
+        2. Check public and project connectivity after updating
                 admin_state_up attribute of instance port to False
-        3. Check public connectivity after updating
+        3. Check public and project connectivity after updating
                 admin_state_up attribute of instance port to True
         """
         self._setup_network_and_servers()
         floating_ip, server = self.floating_ip_tuple
         server_id = server['id']
         port_id = self._list_ports(device_id=server_id)[0]['id']
+        server_pip = server['addresses'][self.network['name']][0]['addr']
+
+        server2 = self._create_server(self.network)
+        server2_fip = self.create_floating_ip(server2)
+
+        private_key = self._get_server_key(server2)
+        ssh_client = self.get_remote_client(server2_fip['floating_ip_address'],
+                                            private_key=private_key)
+
         self.check_public_network_connectivity(
             should_connect=True, msg="before updating "
             "admin_state_up of instance port to False")
+        self._check_remote_connectivity(ssh_client, dest=server_pip,
+                                        should_succeed=True)
         self.ports_client.update_port(port_id, admin_state_up=False)
         self.check_public_network_connectivity(
             should_connect=False, msg="after updating "
             "admin_state_up of instance port to False",
             should_check_floating_ip_status=False)
+        self._check_remote_connectivity(ssh_client, dest=server_pip,
+                                        should_succeed=False)
         self.ports_client.update_port(port_id, admin_state_up=True)
         self.check_public_network_connectivity(
             should_connect=True, msg="after updating "
             "admin_state_up of instance port to True")
+        self._check_remote_connectivity(ssh_client, dest=server_pip,
+                                        should_succeed=True)
 
     @test.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
     @test.services('compute', 'network')
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 6700236..7acf107 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -14,8 +14,6 @@
 #    under the License.
 import functools
 
-import six
-
 from tempest import config
 from tempest.lib.common.utils import test_utils
 from tempest.scenario import manager
@@ -50,8 +48,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
@@ -112,7 +110,7 @@
     @staticmethod
     def define_server_ips(srv):
         ips = {'4': None, '6': []}
-        for net_name, nics in six.iteritems(srv['addresses']):
+        for net_name, nics in srv['addresses'].items():
             for nic in nics:
                 if nic['version'] == 6:
                     ips['6'].append(nic['addr'])
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 1360b09..f8c5c0a 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -130,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')
@@ -145,6 +142,10 @@
         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):
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 2d2f7df..4a938f9 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -18,6 +18,7 @@
 
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 from tempest.scenario import manager
@@ -79,6 +80,14 @@
                                                   'verify metadata on server. '
                                                   '%s is empty.' % md_url)
 
+            # Also, test a POST
+            md_url = 'http://169.254.169.254/openstack/2013-10-17/password'
+            data = data_utils.arbitrary_string(100)
+            cmd = 'curl -X POST -d ' + data + ' ' + md_url
+            self.ssh_client.exec_command(cmd)
+            result = self.servers_client.show_password(self.instance['id'])
+            self.assertEqual(data, result['password'])
+
     def _mount_config_drive(self):
         cmd_blkid = 'blkid | grep -i config-2'
         result = self.ssh_client.exec_command(cmd_blkid)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 0f2c78c..b10be11 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -85,9 +85,9 @@
         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,
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 46aebfe..2c8b618 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -118,36 +118,36 @@
         volume_origin = self._create_volume_from_image()
         instance_1st = self._boot_instance_from_volume(volume_origin['id'],
                                                        keypair, security_group)
-        LOG.info("Booted first instance: %s" % instance_1st)
+        LOG.info("Booted first instance: %s", instance_1st)
 
         # write content to volume on instance
-        LOG.info("Setting timestamp in instance %s" % instance_1st)
+        LOG.info("Setting timestamp in instance %s", instance_1st)
         ip_instance_1st = self.get_server_ip(instance_1st)
         timestamp = self.create_timestamp(ip_instance_1st,
                                           private_key=keypair['private_key'])
 
         # delete instance
-        LOG.info("Deleting first instance: %s" % instance_1st)
+        LOG.info("Deleting first instance: %s", instance_1st)
         self._delete_server(instance_1st)
 
         # create a 2nd instance from volume
         instance_2nd = self._boot_instance_from_volume(volume_origin['id'],
                                                        keypair, security_group)
-        LOG.info("Booted second instance %s" % instance_2nd)
+        LOG.info("Booted second instance %s", instance_2nd)
 
         # check the content of written file
-        LOG.info("Getting timestamp in instance %s" % instance_2nd)
+        LOG.info("Getting timestamp in instance %s", instance_2nd)
         ip_instance_2nd = self.get_server_ip(instance_2nd)
         timestamp2 = self.get_timestamp(ip_instance_2nd,
                                         private_key=keypair['private_key'])
         self.assertEqual(timestamp, timestamp2)
 
         # snapshot a volume
-        LOG.info("Creating snapshot from volume: %s" % volume_origin['id'])
+        LOG.info("Creating snapshot from volume: %s", volume_origin['id'])
         snapshot = self._create_snapshot_from_volume(volume_origin['id'])
 
         # create a 3rd instance from snapshot
-        LOG.info("Creating third instance from snapshot: %s" % snapshot['id'])
+        LOG.info("Creating third instance from snapshot: %s", snapshot['id'])
         volume = self.create_volume(snapshot_id=snapshot['id'],
                                     size=snapshot['size'])
         LOG.info("Booting third instance from snapshot")
@@ -157,7 +157,7 @@
         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" %
+        LOG.info("Logging into third instance to get timestamp: %s",
                  server_from_snapshot)
         server_from_snapshot_ip = self.get_server_ip(server_from_snapshot)
         timestamp3 = self.get_timestamp(server_from_snapshot_ip,
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
new file mode 100644
index 0000000..dfda18d
--- /dev/null
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -0,0 +1,128 @@
+#    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.common import waiters
+from tempest import config
+from tempest.scenario import manager
+from tempest import test
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class TestVolumeMigrateRetypeAttached(manager.ScenarioTest):
+
+    """This test case attempts to reproduce the following steps:
+
+     * Create 2 volume types representing 2 different backends
+     * Create in Cinder some bootable volume importing a Glance image using
+     *   volume_type_1
+     * Boot an instance from the bootable volume
+     * Write to the volume
+     * Perform a cinder retype --on-demand of the volume to type of backend #2
+     * Check written content of migrated volume
+    """
+
+    credentials = ['primary', 'admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(TestVolumeMigrateRetypeAttached, cls).setup_clients()
+        if CONF.volume_feature_enabled.api_v1:
+            cls.admin_volume_types_client = cls.os_adm.volume_types_client
+        else:
+            cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+
+    @classmethod
+    def skip_checks(cls):
+        super(TestVolumeMigrateRetypeAttached, cls).skip_checks()
+        if not CONF.volume_feature_enabled.multi_backend:
+            raise cls.skipException("Cinder multi-backend feature disabled")
+
+        if len(set(CONF.volume.backend_names)) < 2:
+            raise cls.skipException("Requires at least two different "
+                                    "backend names")
+
+    def _boot_instance_from_volume(self, vol_id, keypair, security_group):
+
+        key_name = keypair['name']
+        security_groups = [{'name': security_group['name']}]
+        block_device_mapping = [{'device_name': 'vda', 'volume_id': vol_id,
+                                 'delete_on_termination': False}]
+
+        return self.create_server(image_id='', wait_until='ACTIVE',
+                                  key_name=key_name,
+                                  security_groups=security_groups,
+                                  block_device_mapping=block_device_mapping)
+
+    def _create_volume_types(self):
+        backend_names = CONF.volume.backend_names
+
+        backend_source = backend_names[0]
+        backend_dest = backend_names[1]
+
+        source_body = self.create_volume_type(backend_name=backend_source)
+        dest_body = self.create_volume_type(backend_name=backend_dest)
+
+        LOG.info("Created Volume types: %(src)s -> %(src_backend)s, %(dst)s "
+                 "-> %(dst_backend)s", {'src': source_body['name'],
+                                        'src_backend': backend_source,
+                                        'dst': dest_body['name'],
+                                        'dst_backend': backend_dest})
+        return source_body['name'], dest_body['name']
+
+    def _volume_retype_with_migration(self, volume_id, new_volume_type):
+        migration_policy = 'on-demand'
+        self.volumes_client.retype_volume(
+            volume_id, new_type=new_volume_type,
+            migration_policy=migration_policy)
+        waiters.wait_for_volume_retype(self.volumes_client,
+                                       volume_id, new_volume_type)
+
+    @test.idempotent_id('deadd2c2-beef-4dce-98be-f86765ff311b')
+    @test.services('compute', 'volume')
+    def test_volume_migrate_attached(self):
+        LOG.info("Creating keypair and security group")
+        keypair = self.create_keypair()
+        security_group = self._create_security_group()
+
+        # create volume types
+        LOG.info("Creating Volume types")
+        source_type, dest_type = self._create_volume_types()
+
+        # create an instance from volume
+        LOG.info("Booting instance from volume")
+        volume_origin = self.create_volume(imageRef=CONF.compute.image_ref,
+                                           volume_type=source_type)
+
+        instance = self._boot_instance_from_volume(volume_origin['id'],
+                                                   keypair, security_group)
+
+        # write content to volume on instance
+        LOG.info("Setting timestamp in instance %s", instance['id'])
+        ip_instance = self.get_server_ip(instance)
+        timestamp = self.create_timestamp(ip_instance,
+                                          private_key=keypair['private_key'])
+
+        # retype volume with migration from backend #1 to backend #2
+        LOG.info("Retyping Volume %s to new type %s", volume_origin['id'],
+                 dest_type)
+        self._volume_retype_with_migration(volume_origin['id'], dest_type)
+
+        # check the content of written file
+        LOG.info("Getting timestamp in postmigrated instance %s",
+                 instance['id'])
+        timestamp2 = self.get_timestamp(ip_instance,
+                                        private_key=keypair['private_key'])
+        self.assertEqual(timestamp, timestamp2)
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/__init__.py b/tempest/services/identity/__init__.py
deleted file mode 100644
index 53c223f..0000000
--- a/tempest/services/identity/__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.lib.services.identity import v2
-from tempest.services.identity import v3
-
-__all__ = ['v2', 'v3']
diff --git a/tempest/services/identity/v3/__init__.py b/tempest/services/identity/v3/__init__.py
deleted file mode 100644
index 6e64a7d..0000000
--- a/tempest/services/identity/v3/__init__.py
+++ /dev/null
@@ -1,38 +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.identity.v3.credentials_client import \
-    CredentialsClient
-from tempest.lib.services.identity.v3.endpoints_client import EndPointsClient
-from tempest.lib.services.identity.v3.groups_client import GroupsClient
-from tempest.lib.services.identity.v3.identity_client import IdentityClient
-from tempest.lib.services.identity.v3.inherited_roles_client import \
-    InheritedRolesClient
-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
-
-__all__ = ['CredentialsClient', 'EndPointsClient', 'GroupsClient',
-           'IdentityClient', 'InheritedRolesClient', 'PoliciesClient',
-           'ProjectsClient', 'RegionsClient', 'RoleAssignmentsClient',
-           'RolesClient', 'ServicesClient', 'V3TokenClient', 'TrustsClient',
-           'UsersClient', 'DomainsClient', ]
diff --git a/tempest/services/identity/v3/json/__init__.py b/tempest/services/identity/v3/json/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/services/identity/v3/json/__init__.py
+++ /dev/null
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index 2509156..afedd36 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -140,5 +140,11 @@
             body = json.loads(body)
         elif params and params.get('format') == 'xml':
             body = etree.fromstring(body)
+        # Else the content-type is plain/text
+        else:
+            body = [
+                obj_name for obj_name in body.decode().split('\n') if obj_name
+            ]
+
         self.expected_success([200, 204], resp.status)
         return resp, body
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 9445e34..6d656ec 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import six
 from six.moves import http_client as httplib
 from six.moves.urllib import parse as urlparse
 
@@ -189,7 +188,7 @@
         # Send the PUT request and the headers including the "Expect" header
         conn.putrequest('PUT', path)
 
-        for header, value in six.iteritems(headers):
+        for header, value in headers.items():
             conn.putheader(header, value)
         conn.endheaders()
 
diff --git a/tempest/test.py b/tempest/test.py
index 51f0a6a..039afa1 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -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,
@@ -157,14 +156,22 @@
                 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))
+                              '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:
@@ -212,7 +219,6 @@
     """
 
     setUpClassCalled = False
-    _service = None
 
     # NOTE(andreaf) credentials holds a list of the credentials to be allocated
     # at class setup time. Credential types can be 'primary', 'alt', 'admin' or
@@ -256,8 +262,8 @@
             cls.resource_setup()
         except Exception:
             etype, value, trace = sys.exc_info()
-            LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass." % (
-                     etype, cls.__name__))
+            LOG.info("%s raised in %s.setUpClass. Invoking tearDownClass.",
+                     etype, cls.__name__)
             cls.tearDownClass()
             try:
                 six.reraise(etype, value, trace)
@@ -289,9 +295,9 @@
                 # resources that were successfully setup in resource_cleanup,
                 # log AttributeError as info instead of exception.
                 if tetype is AttributeError and name == 'resources':
-                    LOG.info("tearDownClass of %s failed: %s" % (name, te))
+                    LOG.info("tearDownClass of %s failed: %s", name, te)
                 else:
-                    LOG.exception("teardown of %s failed: %s" % (name, te))
+                    LOG.exception("teardown of %s failed: %s", name, te)
                 if not etype:
                     etype, value, trace = sys_exec_info
         # If exceptions were raised during teardown, and not before, re-raise
@@ -526,8 +532,7 @@
             else:
                 raise lib_exc.InvalidCredentials(
                     "Invalid credentials type %s" % credential_type)
-        manager = cls.client_manager(credentials=creds.credentials,
-                                     service=cls._service)
+        manager = cls.client_manager(credentials=creds.credentials)
         # 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()
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index f8d5d9d..abe2b73 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -13,8 +13,8 @@
 # under the License.
 
 import abc
-import logging
 
+from oslo_log import log as logging
 import six
 import stevedore
 
@@ -143,7 +143,7 @@
                 plug.obj.register_opts(conf)
             except Exception:
                 LOG.exception('Plugin %s raised an exception trying to run '
-                              'register_opts' % plug.name)
+                              'register_opts', plug.name)
 
     def get_plugin_options_list(self):
         plugin_options = []
@@ -163,4 +163,4 @@
                         plug.name, service_clients)
             except Exception:
                 LOG.exception('Plugin %s raised an exception trying to run '
-                              'get_service_clients' % plug.name)
+                              'get_service_clients', plug.name)
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index b08954f..6773b2f 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -75,7 +75,7 @@
         fake_domain_list = {'domains': [{'id': 'fake_domain',
                                          'name': 'Fake_Domain'}]}
         self.useFixture(fixtures.MockPatch(''.join([
-            'tempest.services.identity.v3.json.domains_client.'
+            'tempest.lib.services.identity.v3.domains_client.'
             'DomainsClient.list_domains']),
             return_value=fake_domain_list))
         self.useFixture(fixtures.MockPatch(
@@ -121,7 +121,7 @@
         super(TestAccountGeneratorV3, self).setUp()
         fake_domain_list = {'domains': [{'id': 'fake_domain'}]}
         self.useFixture(fixtures.MockPatch(''.join([
-            'tempest.services.identity.v3.json.domains_client.'
+            'tempest.lib.services.identity.v3.domains_client.'
             'DomainsClient.list_domains']),
             return_value=fake_domain_list))
 
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index a90ca8a..b4fbd50 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -27,6 +27,7 @@
     v2_tenants_client
 from tempest.lib.services.identity.v2 import token_client as v2_token_client
 from tempest.lib.services.identity.v2 import users_client as v2_users_client
+from tempest.lib.services.identity.v3 import domains_client
 from tempest.lib.services.identity.v3 import identity_client as v3_iden_client
 from tempest.lib.services.identity.v3 import projects_client as \
     v3_projects_client
@@ -35,7 +36,6 @@
 from tempest.lib.services.identity.v3 import users_client as \
     v3_users_client
 from tempest.lib.services.network import routers_client
-from tempest.services.identity.v3.json import domains_client
 from tempest.tests import base
 from tempest.tests import fake_config
 from tempest.tests.lib import fake_http
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index f824b6c..1c9982c 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -101,7 +101,7 @@
             preprov_creds.PreProvisionedCredentialProvider.HASH_CRED_FIELDS)
         for account in accounts_list:
             hash = hashlib.md5()
-            account_for_hash = dict((k, v) for (k, v) in six.iteritems(account)
+            account_for_hash = dict((k, v) for (k, v) in account.items()
                                     if k in hash_fields)
             hash.update(six.text_type(account_for_hash).encode('utf-8'))
             temp_hash = hash.hexdigest()
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/lib/common/test_jsonschema_validator.py b/tempest/tests/lib/common/test_jsonschema_validator.py
new file mode 100644
index 0000000..8694f3d
--- /dev/null
+++ b/tempest/tests/lib/common/test_jsonschema_validator.py
@@ -0,0 +1,83 @@
+# 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.api_schema.response.compute.v2_1 import parameter_types
+from tempest.lib.common import rest_client
+from tempest.lib import exceptions
+from tempest.tests import base
+from tempest.tests.lib import fake_http
+
+
+class TestJSONSchemaDateTimeFormat(base.TestCase):
+    date_time_schema = [
+        {
+            'status_code': [200],
+            'response_body': {
+                'type': 'object',
+                'properties': {
+                    'date-time': parameter_types.date_time
+                }
+            }
+        },
+        {
+            'status_code': [200],
+            'response_body': {
+                'type': 'object',
+                'properties': {
+                    'date-time': parameter_types.date_time_or_null
+                }
+            }
+        }
+    ]
+
+    def test_valid_date_time_format(self):
+        valid_instances = ['2016-10-02T10:00:00-05:00',
+                           '2016-10-02T10:00:00+09:00',
+                           '2016-10-02T15:00:00Z',
+                           '2016-10-02T15:00:00.05Z']
+        resp = fake_http.fake_http_response('', status=200)
+        for instance in valid_instances:
+            body = {'date-time': instance}
+            for schema in self.date_time_schema:
+                rest_client.RestClient.validate_response(schema, resp, body)
+
+    def test_invalid_date_time_format(self):
+        invalid_instances = ['2016-10-02 T10:00:00-05:00',
+                             '2016-10-02T 15:00:00',
+                             '2016-10-02T15:00:00.05 Z',
+                             '2016-10-02:15:00:00.05Z',
+                             'T15:00:00.05Z',
+                             '2016:10:02T15:00:00',
+                             '2016-10-02T15-00-00',
+                             '2016-10-02T15.05Z',
+                             '09MAR2015 11:15',
+                             '13 Oct 2015 05:55:36 GMT',
+                             '']
+        resp = fake_http.fake_http_response('', status=200)
+        for instance in invalid_instances:
+            body = {'date-time': instance}
+            for schema in self.date_time_schema:
+                self.assertRaises(exceptions.InvalidHTTPResponseBody,
+                                  rest_client.RestClient.validate_response,
+                                  schema, resp, body)
+
+    def test_date_time_or_null_format(self):
+        instance = None
+        resp = fake_http.fake_http_response('', status=200)
+        body = {'date-time': instance}
+        rest_client.RestClient.validate_response(self.date_time_schema[1],
+                                                 resp, body)
+        self.assertRaises(exceptions.InvalidHTTPResponseBody,
+                          rest_client.RestClient.validate_response,
+                          self.date_time_schema[0], resp, body)
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/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index 93550fd..adfaaf2 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -154,7 +154,7 @@
         "request_id": "16fb98f-46ca-475e-917e-2563e5a8cd19",
         "user_id": "16fb98f-46ca-475e-917e-2563e5a8cd12",
         "project_id": "16fb98f-46ca-475e-917e-2563e5a8cd34",
-        "start_time": "09MAR2015 11:15",
+        "start_time": "2016-10-02T10:00:00-05:00",
         "message": "fake-msg",
         "instance_uuid": "16fb98f-46ca-475e-917e-2563e5a8cd12"
     }
@@ -166,8 +166,8 @@
 
     FAKE_INSTANCE_ACTION_EVENTS = {
         "event": "fake-event",
-        "start_time": "09MAR2015 11:15",
-        "finish_time": "09MAR2015 11:15",
+        "start_time": "2016-10-02T10:00:00-05:00",
+        "finish_time": "2016-10-02T10:00:00-05:00",
         "result": "fake-result",
         "traceback": "fake-trace-back"
     }
diff --git a/tempest/tests/lib/services/identity/v3/test_domains_client.py b/tempest/tests/lib/services/identity/v3/test_domains_client.py
new file mode 100644
index 0000000..f89ced7
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_domains_client.py
@@ -0,0 +1,138 @@
+# 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 domains_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestDomainsClient(base.BaseServiceTest):
+    FAKE_CREATE_DOMAIN = {
+        "domain": {
+            "description": "Domain description",
+            "enabled": True,
+            "name": "myDomain"
+        }
+    }
+
+    FAKE_DOMAIN_INFO = {
+        "domain": {
+            "description": "Used for swift functional testing",
+            "enabled": True,
+            "id": "5a75994a3",
+            "links": {
+                "self": "http://example.com/identity/v3/domains/5a75994a3"
+            },
+            "name": "swift_test"
+        }
+    }
+
+    FAKE_LIST_DOMAINS = {
+        "domains": [
+            {
+                "description": "Used for swift functional testing",
+                "enabled": True,
+                "id": "5a75994a3",
+                "links": {
+                    "self": "http://example.com/identity/v3/domains/5a75994a3"
+                },
+                "name": "swift_test"
+            },
+            {
+                "description": "Owns users and tenants available on " +
+                               "Identity API",
+                "enabled": True,
+                "id": "default",
+                "links": {
+                    "self": "http://example.com/identity/v3/domains/default"
+                },
+                "name": "Default"
+            }
+        ],
+        "links": {
+            "next": None,
+            "previous": None,
+            "self": "http://example.com/identity/v3/domains"
+        }
+    }
+
+    def setUp(self):
+        super(TestDomainsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = domains_client.DomainsClient(fake_auth,
+                                                   'identity',
+                                                   'regionOne')
+
+    def _test_create_domain(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_domain,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_DOMAIN,
+            bytes_body,
+            status=201)
+
+    def _test_show_domain(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_domain,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_DOMAIN_INFO,
+            bytes_body,
+            domain_id="5a75994a3")
+
+    def _test_list_domains(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_domains,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_DOMAINS,
+            bytes_body)
+
+    def _test_update_domain(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_domain,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_DOMAIN_INFO,
+            bytes_body,
+            domain_id="5a75994a3")
+
+    def test_create_domain_with_str_body(self):
+        self._test_create_domain()
+
+    def test_create_domain_with_bytes_body(self):
+        self._test_create_domain(bytes_body=True)
+
+    def test_show_domain_with_str_body(self):
+        self._test_show_domain()
+
+    def test_show_domain_with_bytes_body(self):
+        self._test_show_domain(bytes_body=True)
+
+    def test_list_domain_with_str_body(self):
+        self._test_list_domains()
+
+    def test_list_domain_with_bytes_body(self):
+        self._test_list_domains(bytes_body=True)
+
+    def test_update_domain_with_str_body(self):
+        self._test_update_domain()
+
+    def test_update_domain_with_bytes_body(self):
+        self._test_update_domain(bytes_body=True)
+
+    def test_delete_domain(self):
+        self.check_service_client_function(
+            self.client.delete_domain,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            domain_id="5a75994a3",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_roles_client.py b/tempest/tests/lib/services/identity/v3/test_roles_client.py
index bad1ef9..4f70b47 100644
--- a/tempest/tests/lib/services/identity/v3/test_roles_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_roles_client.py
@@ -18,32 +18,40 @@
 
 
 class TestRolesClient(base.BaseServiceTest):
+
+    FAKE_ROLE_ID = "1"
+    FAKE_ROLE_NAME = "test"
+    FAKE_DOMAIN_ID = "1"
+
+    FAKE_ROLE_ID_2 = "2"
+    FAKE_ROLE_NAME_2 = "test2"
+
     FAKE_ROLE_INFO = {
         "role": {
-            "domain_id": "1",
-            "id": "1",
-            "name": "test",
-            "links": "example.com"
+            "domain_id": FAKE_DOMAIN_ID,
+            "id": FAKE_ROLE_ID,
+            "name": FAKE_ROLE_NAME,
+            "links": {
+                "self": "http://example.com/identity/v3/roles/%s" % (
+                    FAKE_ROLE_ID)
+            }
         }
     }
 
-    FAKE_LIST_ROLES = {
-        "roles": [
-            {
-                "domain_id": "1",
-                "id": "1",
-                "name": "test",
-                "links": "example.com"
-            },
-            {
-                "domain_id": "2",
-                "id": "2",
-                "name": "test2",
-                "links": "example.com"
+    FAKE_ROLE_INFO_2 = {
+        "role": {
+            "domain_id": FAKE_DOMAIN_ID,
+            "id": FAKE_ROLE_ID_2,
+            "name": FAKE_ROLE_NAME_2,
+            "links": {
+                "self": "http://example.com/identity/v3/roles/%s" % (
+                    FAKE_ROLE_ID_2)
             }
-        ]
+        }
     }
 
+    FAKE_LIST_ROLES = {"roles": [FAKE_ROLE_INFO, FAKE_ROLE_INFO_2]}
+
     def setUp(self):
         super(TestRolesClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -56,8 +64,8 @@
             'tempest.lib.common.rest_client.RestClient.post',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            domain_id="1",
-            name="test",
+            domain_id=self.FAKE_DOMAIN_ID,
+            name=self.FAKE_ROLE_NAME,
             status=201)
 
     def _test_show_role(self, bytes_body=False):
@@ -66,7 +74,7 @@
             'tempest.lib.common.rest_client.RestClient.get',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            role_id="1")
+            role_id=self.FAKE_ROLE_ID)
 
     def _test_list_roles(self, bytes_body=False):
         self.check_service_client_function(
@@ -81,8 +89,8 @@
             'tempest.lib.common.rest_client.RestClient.patch',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            role_id="1",
-            name="test")
+            role_id=self.FAKE_ROLE_ID,
+            name=self.FAKE_ROLE_NAME)
 
     def _test_create_user_role_on_project(self, bytes_body=False):
         self.check_service_client_function(
@@ -193,7 +201,7 @@
             self.client.delete_role,
             'tempest.lib.common.rest_client.RestClient.delete',
             {},
-            role_id="1",
+            role_id=self.FAKE_ROLE_ID,
             status=204)
 
     def test_create_user_role_on_project_with_str_body(self):
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_object_client.py b/tempest/tests/lib/services/image/v2/test_namespace_object_client.py
new file mode 100644
index 0000000..8d29660
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_namespace_object_client.py
@@ -0,0 +1,210 @@
+# 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_objects_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestNamespaceObjectClient(base.BaseServiceTest):
+    FAKE_CREATE_SHOW_OBJECTS = {
+        "created_at": "2016-09-19T18:20:56Z",
+        "description": "You can configure the CPU limits.",
+        "name": "CPU Limits",
+        "properties": {
+            "quota:cpu_period": {
+                "description": "Specifies the enforcement interval",
+                "maximum": 1000000,
+                "minimum": 1000,
+                "title": "Quota: CPU Period",
+                "type": "integer"
+            },
+            "quota:cpu_quota": {
+                "description": "Specifies the maximum allowed bandwidth ",
+                "title": "Quota: CPU Quota",
+                "type": "integer"
+            },
+            "quota:cpu_shares": {
+                "description": "Specifies the proportional weighted share.",
+                "title": "Quota: CPU Shares",
+                "type": "integer"
+            }
+        },
+        "required": [],
+        "schema": "/v2/schemas/metadefs/object",
+        "self": "/v2/metadefs/namespaces/OS::Compute::Quota/objects/CPU",
+        "updated_at": "2016-09-19T18:20:56Z"
+    }
+
+    FAKE_LIST_OBJECTS = {
+        "objects": [
+            {
+                "created_at": "2016-09-18T18:16:35Z",
+                "description": "You can configure the CPU limits.",
+                "name": "CPU Limits",
+                "properties": {
+                    "quota:cpu_period": {
+                        "description": "Specifies the enforcement interval ",
+                        "maximum": 1000000,
+                        "minimum": 1000,
+                        "title": "Quota: CPU Period",
+                        "type": "integer"
+                    },
+                    "quota:cpu_quota": {
+                        "description": "Specifies the maximum.",
+                        "title": "Quota: CPU Quota",
+                        "type": "integer"
+                    },
+                    "quota:cpu_shares": {
+                        "description": " Desc.",
+                        "title": "Quota: CPU Shares",
+                        "type": "integer"
+                    }
+                },
+                "required": [],
+                "schema": "/v2/schemas/metadefs/object",
+                "self":
+                    "/v2/metadefs/namespaces/OS::Compute::Quota/objects/CPU"
+            },
+            {
+                "created_at": "2016-09-18T18:16:35Z",
+                "description": "Using disk I/O quotas.",
+                "name": "Disk QoS",
+                "properties": {
+                    "quota:disk_read_bytes_sec": {
+                        "description": "Sets disk I/O quota.",
+                        "title": "Quota: Disk read bytes / sec",
+                        "type": "integer"
+                    },
+                    "quota:disk_read_iops_sec": {
+                        "description": "Sets disk I/O quota",
+                        "title": "Quota: Disk read IOPS / sec",
+                        "type": "integer"
+                    },
+                    "quota:disk_total_bytes_sec": {
+                        "description": "Sets disk I/O quota.",
+                        "title": "Quota: Disk Total Bytes / sec",
+                        "type": "integer"
+                    },
+                    "quota:disk_total_iops_sec": {
+                        "description": "Sets disk I/O quota.",
+                        "title": "Quota: Disk Total IOPS / sec",
+                        "type": "integer"
+                    },
+                    "quota:disk_write_bytes_sec": {
+                        "description": "Sets disk I/O quota.",
+                        "title": "Quota: Disk Write Bytes / sec",
+                        "type": "integer"
+                    },
+                    "quota:disk_write_iops_sec": {
+                        "description": "Sets disk I/O quota.",
+                        "title": "Quota: Disk Write IOPS / sec",
+                        "type": "integer"
+                    }
+                },
+                "required": [],
+                "schema": "/v2/schemas/metadefs/object",
+                "self":
+                "/v2/metadefs/namespaces/OS::Compute::Quota/objects/Disk QoS"
+            },
+        ],
+        "schema": "v2/schemas/metadefs/objects"
+    }
+
+    FAKE_UPDATE_OBJECTS = {
+        "description": "You can configure the CPU limits.",
+        "name": "CPU",
+        "properties": {
+            "quota:cpu_shares": {
+                "description": "Specify.",
+                "title": "Quota: CPU Shares",
+                "type": "integer"
+            }
+        },
+        "required": []
+    }
+
+    def setUp(self):
+        super(TestNamespaceObjectClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = namespace_objects_client.NamespaceObjectsClient(
+            fake_auth, 'image', 'regionOne')
+
+    def _test_create_namespace_objects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_namespace_object,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SHOW_OBJECTS,
+            bytes_body, status=201,
+            namespace="OS::Compute::Hypervisor",
+            object_name="OS::Glance::Image")
+
+    def _test_list_namespace_objects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_namespace_objects,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_OBJECTS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor")
+
+    def _test_show_namespace_objects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_namespace_object,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CREATE_SHOW_OBJECTS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            object_name="OS::Glance::Image")
+
+    def _test_update_namespace_objects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_namespace_object,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_OBJECTS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            object_name="OS::Glance::Image",
+            name="CPU")
+
+    def test_create_namespace_object_with_str_body(self):
+        self._test_create_namespace_objects()
+
+    def test_create_namespace_object_with_bytes_body(self):
+        self._test_create_namespace_objects(bytes_body=True)
+
+    def test_list_namespace_object_with_str_body(self):
+        self._test_list_namespace_objects()
+
+    def test_list_namespace_object_with_bytes_body(self):
+        self._test_list_namespace_objects(bytes_body=True)
+
+    def test_show_namespace_object_with_str_body(self):
+        self._test_show_namespace_objects()
+
+    def test_show_namespace_object_with_bytes_body(self):
+        self._test_show_namespace_objects(bytes_body=True)
+
+    def test_update_namespace_object_with_str_body(self):
+        self._test_update_namespace_objects()
+
+    def test_update_namespace_object_with_bytes_body(self):
+        self._test_update_namespace_objects(bytes_body=True)
+
+    def test_delete_namespace_objects(self):
+        self.check_service_client_function(
+            self.client.delete_namespace_object,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {}, namespace="OS::Compute::Hypervisor",
+            object_name="OS::Glance::Image",
+            status=204)
diff --git a/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py b/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py
new file mode 100644
index 0000000..2faa5be
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_namespace_tags_client.py
@@ -0,0 +1,126 @@
+# 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_tags_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestNamespaceTagsClient(base.BaseServiceTest):
+    FAKE_CREATE_SHOW_TAGS = {
+        "created_at": "2015-05-09T01:12:31Z",
+        "name": "added-sample-tag",
+        "updated_at": "2015-05-09T01:12:31Z"
+    }
+
+    FAKE_LIST_TAGS = {
+        "tags": [
+            {
+                "name": "sample-tag1"
+            },
+            {
+                "name": "sample-tag2"
+            },
+            {
+                "name": "sample-tag3"
+            }
+        ]
+    }
+
+    FAKE_UPDATE_TAGS = {"name": "new-tag-name"}
+
+    def setUp(self):
+        super(TestNamespaceTagsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = namespace_tags_client.NamespaceTagsClient(
+            fake_auth, 'image', 'regionOne')
+
+    def _test_create_namespace_tags(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_namespace_tags,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SHOW_TAGS,
+            bytes_body, status=201,
+            namespace="OS::Compute::Hypervisor",
+            tags=[{"name": "sample-tag1"},
+                  {"name": "sample-tag2"},
+                  {"name": "sample-tag3"}])
+
+    def _test_list_namespace_tags(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_namespace_tags,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_TAGS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor")
+
+    def _test_create_namespace_tag_definition(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_namespace_tag,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_SHOW_TAGS,
+            bytes_body,
+            status=201,
+            namespace="OS::Compute::Hypervisor",
+            tag_name="added-sample-tag")
+
+    def _test_show_namespace_tag_definition(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_namespace_tag,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CREATE_SHOW_TAGS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            tag_name="added-sample-tag")
+
+    def _test_update_namespace_tag_definition(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_namespace_tag,
+            'tempest.lib.common.rest_client.RestClient.put',
+            self.FAKE_UPDATE_OBJECTS,
+            bytes_body,
+            namespace="OS::Compute::Hypervisor",
+            tag_name="added-sample-tag",
+            name="new-tag-name")
+
+    def test_create_namespace_tags_with_str_body(self):
+        self._test_create_namespace_tags()
+
+    def test_create_namespace_tags_with_bytes_body(self):
+        self._test_create_namespace_tags(bytes_body=True)
+
+    def test_list_namespace_tags_with_str_body(self):
+        self._test_list_namespace_tags()
+
+    def test_list_namespace_tags_with_bytes_body(self):
+        self._test_list_namespace_tags(bytes_body=True)
+
+    def test_create_namespace_tag_with_str_body(self):
+        self._test_create_namespace_tag_definition()
+
+    def test_create_namespace_tag_with_bytes_body(self):
+        self._test_create_namespace_tag_definition(bytes_body=True)
+
+    def test_show_namespace_tag_with_str_body(self):
+        self._test_show_namespace_tag_definition()
+
+    def test_show_namespace_tag_with_bytes_body(self):
+        self._test_show_namespace_tag_definition(bytes_body=True)
+
+    def test_delete_all_namespace_tags(self):
+        self.check_service_client_function(
+            self.client.delete_namespace_tags,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {}, status=200,
+            namespace="OS::Compute::Hypervisor")
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index 8a0a84c..a16da1c 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -75,7 +75,54 @@
             key_filename=None,
             look_for_keys=False,
             timeout=10.0,
-            password=None
+            password=None,
+            sock=None
+        )]
+        self.assertEqual(expected_connect, client_mock.connect.mock_calls)
+        self.assertEqual(0, s_mock.call_count)
+
+    def test_get_ssh_connection_over_ssh(self):
+        c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
+        proxy_client_mock = mock.MagicMock()
+        proxy_client_mock.connect.return_value = True
+        s_mock = self.patch('time.sleep')
+
+        c_mock.side_effect = [client_mock, proxy_client_mock]
+        aa_mock.return_value = mock.sentinel.aa
+
+        proxy_client = ssh.Client('proxy-host', 'proxy-user', timeout=2)
+        client = ssh.Client('localhost', 'root', timeout=2,
+                            proxy_client=proxy_client)
+        client._get_ssh_connection(sleep=1)
+
+        aa_mock.assert_has_calls([mock.call(), mock.call()])
+        proxy_client_mock.set_missing_host_key_policy.assert_called_once_with(
+            mock.sentinel.aa)
+        proxy_expected_connect = [mock.call(
+            'proxy-host',
+            port=22,
+            username='proxy-user',
+            pkey=None,
+            key_filename=None,
+            look_for_keys=False,
+            timeout=10.0,
+            password=None,
+            sock=None
+        )]
+        self.assertEqual(proxy_expected_connect,
+                         proxy_client_mock.connect.mock_calls)
+        client_mock.set_missing_host_key_policy.assert_called_once_with(
+            mock.sentinel.aa)
+        expected_connect = [mock.call(
+            'localhost',
+            port=22,
+            username='root',
+            pkey=None,
+            key_filename=None,
+            look_for_keys=False,
+            timeout=10.0,
+            password=None,
+            sock=proxy_client_mock.get_transport().open_session()
         )]
         self.assertEqual(expected_connect, client_mock.connect.mock_calls)
         self.assertEqual(0, s_mock.call_count)
diff --git a/tempest/tests/lib/test_tempest_lib.py b/tempest/tests/lib/test_tempest_lib.py
index d70e53d..4d9f099 100644
--- a/tempest/tests/lib/test_tempest_lib.py
+++ b/tempest/tests/lib/test_tempest_lib.py
@@ -1,5 +1,3 @@
-# -*- 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
diff --git a/tempest/tests/negative/__init__.py b/tempest/tests/negative/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/tests/negative/__init__.py
+++ /dev/null
diff --git a/tempest/tests/services/object_storage/test_object_client.py b/tempest/tests/services/object_storage/test_object_client.py
index cc1dc1a..748614c 100644
--- a/tempest/tests/services/object_storage/test_object_client.py
+++ b/tempest/tests/services/object_storage/test_object_client.py
@@ -15,7 +15,6 @@
 
 
 import mock
-import six
 
 from tempest.lib import exceptions
 from tempest.services.object_storage import object_client
@@ -85,7 +84,7 @@
         # Verify that headers were written, including "Expect:100-continue"
         calls = []
 
-        for header, value in six.iteritems(expected_hdrs):
+        for header, value in expected_hdrs.items():
             calls.append(mock.call(header, value))
 
         mock_poc.return_value.putheader.assert_has_calls(calls, False)
diff --git a/tools/skip_tracker.py b/tools/skip_tracker.py
index 55f41a6..9735f77 100755
--- a/tools/skip_tracker.py
+++ b/tools/skip_tracker.py
@@ -20,23 +20,25 @@
 is fixed but a skip is still in the Tempest test code
 """
 
-import logging
 import os
 import re
 
 from launchpadlib import launchpad
+from oslo_log import log as logging
 
 BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
 TESTDIR = os.path.join(BASEDIR, 'tempest')
 LPCACHEDIR = os.path.expanduser('~/.launchpadlib/cache')
 
+LOG = logging.getLogger(__name__)
+
 
 def info(msg, *args, **kwargs):
-    logging.info(msg, *args, **kwargs)
+    LOG.info(msg, *args, **kwargs)
 
 
 def debug(msg, *args, **kwargs):
-    logging.debug(msg, *args, **kwargs)
+    LOG.debug(msg, *args, **kwargs)
 
 
 def find_skips(start=TESTDIR):
@@ -102,8 +104,6 @@
 
 
 if __name__ == '__main__':
-    logging.basicConfig(format='%(levelname)s: %(message)s',
-                        level=logging.INFO)
     results = find_skips()
     unique_bugs = sorted(set([bug for (method, bug) in get_results(results)]))
     unskips = []
diff --git a/tox.ini b/tox.ini
index 7a36e84..46823d8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -146,7 +146,7 @@
 ignore = E125,E123,E129
 show-source = True
 exclude = .git,.venv,.tox,dist,doc,*egg
-enable-extensions = H106,H203
+enable-extensions = H106,H203,H904
 
 [testenv:releasenotes]
 commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html