Merge "Improvement in API Microversion testing doc"
diff --git a/HACKING.rst b/HACKING.rst
index 910a977..c0a857c 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -170,7 +170,7 @@
 All negative tests should be based on `API-WG guideline`_ . Such negative
 tests can block any changes from accurate failure code to invalid one.
 
-.. _API-WG guideline: https://github.com/openstack/api-wg/blob/master/guidelines/http.rst#failure-code-clarifications
+.. _API-WG guideline: http://specs.openstack.org/openstack/api-wg/guidelines/http.html#failure-code-clarifications
 
 If facing some gray area which is not clarified on the above guideline, propose
 a new guideline to the API-WG. With a proposal to the API-WG we will be able to
@@ -246,7 +246,7 @@
 to the config variables in tempest/config.py then the sample config file must be
 regenerated. This can be done running::
 
-  tox -egenconfig
+  tox -e genconfig
 
 Unit Tests
 ----------
diff --git a/README.rst b/README.rst
index 3d7c804..ac93992 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,6 @@
 
 .. image:: http://governance.openstack.org/badges/tempest.svg
     :target: http://governance.openstack.org/reference/tags/index.html
-    :remote:
 
 .. Change things from this point on
 
@@ -105,7 +104,7 @@
     $ tempest run
 
    from the Tempest workspace directory. Or you can use the ``--workspace``
-   argument to run in the workspace you created regarless of your current
+   argument to run in the workspace you created regardless of your current
    working directory. For example::
 
     $ tempest run --workspace cloud-01
@@ -173,7 +172,7 @@
 You can generate a new sample tempest.conf file, run the following
 command from the top level of the Tempest directory::
 
-    $ tox -egenconfig
+    $ tox -e genconfig
 
 The most important pieces that are needed are the user ids, openstack
 endpoint, and basic flavors and images needed to run tests.
@@ -259,11 +258,11 @@
 
 Tox also contains several existing job configurations. For example::
 
-    $ tox -efull
+    $ tox -e full
 
 which will run the same set of tests as the OpenStack gate. (it's exactly how
 the gate invokes Tempest) Or::
 
-    $ tox -esmoke
+    $ tox -e smoke
 
 to run the tests tagged as smoke.
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 04ddfdf..cbfcc09 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -1,3 +1,16 @@
+# 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.
+
 # Tempest documentation build configuration file, created by
 # sphinx-quickstart on Tue May 21 17:43:32 2013.
 #
@@ -140,9 +153,8 @@
 git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
    "-n1"]
 try:
-    html_last_updated_fmt = subprocess.Popen(git_cmd,
-                                             stdout=subprocess.PIPE).\
-                                             communicate()[0]
+    html_last_updated_fmt = str(
+        subprocess.Popen(git_cmd, stdout=subprocess.PIPE).communicate()[0])
 except Exception:
     warnings.warn('Cannot get last updated time from git repository. '
                   'Not setting "html_last_updated_fmt".')
@@ -184,123 +196,5 @@
 # This is the file name suffix for HTML files (e.g. ".xhtml").
 #html_file_suffix = None
 
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'Tempestdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
-  ('index', 'Tempest.tex', u'Tempest Documentation',
-   u'OpenStack QA Team', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'tempest', u'Tempest Documentation',
-     [u'OpenStack QA Team'], 1)
-]
-
-# If true, show URL addresses after external links.
-#man_show_urls = False
-
-
-# -- Options for Texinfo output ------------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-  ('index', 'Tempest', u'Tempest Documentation',
-   u'OpenStack QA Team', 'Tempest', 'One line description of project.',
-   'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-
-# -- Options for Epub output ---------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'Tempest'
-epub_author = u'Sean Dague'
-epub_publisher = u'OpenStack QA Team'
-epub_copyright = u'2013, OpenStack QA Team'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True
+# A list of warning types to suppress arbitrary warning messages.
+suppress_warnings = ['image.nonlocal_uri']
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 18269bf..2314222 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -9,6 +9,8 @@
 config file which explains the purpose of each individual option. You can see
 the sample config file here: :ref:`tempest-sampleconf`
 
+.. _tempest_cred_provider_conf:
+
 Test Credentials
 ----------------
 
@@ -232,6 +234,9 @@
 
 Enabling Remote Access to Created Servers
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _tempest_conf_network_allocation:
+
 Network Creation/Usage for Servers
 """"""""""""""""""""""""""""""""""
 When Tempest creates servers for testing, some tests require being able to
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 896cd98..1264ecc 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -67,7 +67,8 @@
    HACKING
    REVIEWING
    microversion_testing
-   test-removal
+   test_removal
+   write_tests
 
 -------
 Plugins
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index 6b30825..b3af92f 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -1,3 +1,5 @@
+.. _tempest_plugin:
+
 =============================
 Tempest Test Plugin Interface
 =============================
diff --git a/doc/source/test-removal.rst b/doc/source/test_removal.rst
similarity index 100%
rename from doc/source/test-removal.rst
rename to doc/source/test_removal.rst
diff --git a/doc/source/write_tests.rst b/doc/source/write_tests.rst
new file mode 100644
index 0000000..8488fb1
--- /dev/null
+++ b/doc/source/write_tests.rst
@@ -0,0 +1,311 @@
+.. _tempest_test_writing:
+
+Tempest Test Writing Guide
+##########################
+
+This guide serves as a starting point for developers working on writing new
+Tempest tests. At a high level tests in Tempest are just tests that conform to
+the standard python `unit test`_ framework. But there are several aspects of
+that are unique to tempest and it's role as an integration test suite running
+against a real cloud.
+
+.. _unit test: https://docs.python.org/3.6/library/unittest.html
+
+.. note:: This guide is for writing tests in the tempest repository. While many
+          parts of this guide are also applicable to tempest plugins, not all
+          the APIs mentioned are considered stable or recommended for use in
+          plugins. Please refer to :ref:`tempest_plugin` for details about
+          writing plugins
+
+
+Adding a New TestCase
+=====================
+
+The base unit of testing in Tempest is the `TestCase`_ (also called the test
+class). Each TestCase contains test methods which are the individual tests that
+will be executed by the test runner. But, the TestCase is the smallest self
+contained unit for tests from the tempest perspective. It's also the level at
+which tempest is parallel safe. In other words, multiple TestCases can be
+executed in parallel, but individual test methods in the same TestCase can not.
+Also, all test methods within a TestCase are assumed to be executed serially. As
+such you can use the test case to store variables that are shared between
+methods.
+
+.. _TestCase: https://docs.python.org/3.6/library/unittest.html#unittest.TestCase
+
+In standard unittest the lifecycle of a TestCase can be described in the
+following phases:
+
+ #. setUpClass
+ #. setUp
+ #. Test Execution
+ #. tearDown
+ #. doCleanups
+ #. tearDownClass
+
+setUpClass
+----------
+
+The setUpClass phase is the first phase executed by the test runner and is used
+to perform any setup required for all the test methods to be executed. In
+Tempest this is a very important step and will automatically do the necessary
+setup for interacting with the configured cloud.
+
+To accomplish this you do **not** define a setUpClass function, instead there
+are a number of predefined phases to setUpClass that are used. The phases are:
+
+ * skip_checks
+ * setup_credentials
+ * setup_clients
+ * resource_setup
+
+which is executed in that order. An example of a TestCase which defines all
+of these would be::
+
+  from tempest import config
+  from tempest import test
+
+  CONF = config.CONF
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+    @classmethod
+    def skip_checks(cls):
+        """This section is used to evaluate config early and skip all test
+           methods based on these checks
+        """
+        super(TestExampleCase, cls).skip_checks()
+        if not CONF.section.foo
+            cls.skip('A helpful message')
+
+    @classmethod
+    def setup_credentials(cls):
+        """This section is used to do any manual credential allocation and also
+           in the case of dynamic credentials to override the default network
+           resource creation/auto allocation
+        """
+        # This call is used to tell the credential allocator to not create any
+        # network resources for this test case. It also enables selective
+        # creation of other neutron resources. NOTE: it must go before the
+        # super call
+        cls.set_network_resources()
+        super(TestExampleCase, cls).setup_credentials()
+
+    @classmethod
+    def setup_clients(cls):
+        """This section is used to setup client aliases from the manager object
+           or to initialize any additional clients. Except in a few very
+           specific situations you should not need to use this.
+        """
+        super(TestExampleCase, cls).setup_clients()
+        cls.servers_client = cls.os.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        """This section is used to create any resources or objects which are
+           going to be used and shared by **all** test methods in the
+           TestCase. Note then anything created in this section must also be
+           destroyed in the corresponding resource_cleanup() method (which will
+           be run during tearDownClass())
+        """
+        super(TestExampleCase, cls).resource_setup()
+        cls.shared_server = cls.servers_client.create_server(...)
+
+.. _credentials:
+
+Allocating Credentials
+''''''''''''''''''''''
+
+Since Tempest tests are all about testing a running cloud, every test will need
+credentials to be able to make API requests against the cloud. Since this is
+critical to operation and, when running in parallel, easy to make a mistake,
+the base TestCase class will automatically allocate a regular user for each
+TestCase during the setup_credentials() phase. During this process it will also
+initialize a client manager object using those credentials, which will be your
+entry point into interacting with the cloud. For more details on how credentials
+are allocated the :ref:`tempest_cred_provider_conf` section of the Tempest
+Configuration Guide provides more details on the operation of this.
+
+There are some cases when you need more than a single set of credentials, or
+credentials with a more specialized set of roles. To accomplish this you have
+to set a class variable ``credentials`` on the TestCase directly. For example::
+
+    from tempest import test
+
+    class TestExampleAdmin(test.BaseTestCase):
+
+        credentials = ['primary', 'admin']
+
+    @classmethod
+    def skip_checks(cls):
+    ...
+
+In this example the ``TestExampleAdmin`` TestCase will allocate 2 sets of
+credentials, one regular user and one admin user. The corresponding manager
+objects will be set as class variables cls.os and cls.os_adm respectively. You
+can also allocate a second user by putting **'alt'** in the list too. A set of
+alt credentials are the same as primary but can be used for tests cases that
+need a second user/project.
+
+You can also specify credentials with specific roles assigned. This is useful
+for cases where there are specific RBAC requirements hard coded into an API.
+The canonical example of this are swift tests which often want to test swift's
+concepts of operator and reseller_admin. An actual example from tempest on how
+to do this is::
+
+    class PublicObjectTest(base.BaseObjectTest):
+
+        credentials = [['operator', CONF.object_storage.operator_role],
+                       ['operator_alt', CONF.object_storage.operator_role]]
+
+        @classmethod
+        def setup_credentials(cls):
+            super(PublicObjectTest, cls).setup_credentials()
+            ...
+
+In this case the manager objects will be set to ``cls.os_roles_operator`` and
+``cls.os_roles_operator_alt`` respectively.
+
+
+There is no limit to how many credentials you can allocate in this manner,
+however in almost every case you should **not** need more than 3 sets of
+credentials per test case.
+
+To figure out the mapping of manager objects set on the TestCase and the
+requested credentials you can reference:
+
++-------------------+---------------------+
+| Credentials Entry | Manager Variable    |
++===================+=====================+
+| primary           | cls.os              |
++-------------------+---------------------+
+| admin             | cls.os_adm          |
++-------------------+---------------------+
+| alt               | cls.os_alt          |
++-------------------+---------------------+
+| [$label, $role]   | cls.os_roles_$label |
++-------------------+---------------------+
+
+By default cls.os is available since it is allocated in the base tempest test
+class (located in tempest/test.py). If your TestCase inherits from a different
+direct parent class (it'll still inherit from the BaseTestCase, just not
+directly) be sure to check if that class overrides allocated credentials.
+
+Dealing with Network Allocation
+'''''''''''''''''''''''''''''''
+
+When neutron is enabled and a testing requires networking this isn't normally
+automatically setup when a tenant is created. Since tempest needs isolated
+tenants to function properly it also needs to handle network allocation. By
+default the base test class will allocate a network, subnet, and router
+automatically (this depends on the configured credential provider, for more
+details see: :ref:`tempest_conf_network_allocation`). However, there are
+situations where you do no need all of these resources allocated (or your
+TestCase inherits from a class that overrides the default in tempest/test.py).
+There is a class level mechanism to override this allocation and specify which
+resources you need. To do this you need to call `cls.set_network_resources()`
+in the `setup_credentials()` method before the `super()`. For example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+  @classmethod
+  def setup_credentials(cls):
+      cls.set_network_resources(network=True, subnet=True, router=False)
+      super(TestExampleCase, cls).setup_credentials()
+
+There are 2 quirks with the usage here. First for the set_network_resources
+function to work properly it **must be called before super()**. This is so
+that children classes' settings are always used instead of a parent classes'.
+The other quirk here is that if you do not want to allocate any network
+resources for your test class simply call `set_network_resources()` without
+any arguments. For example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+  @classmethod
+  def setup_credentials(cls):
+      cls.set_network_resources()
+      super(TestExampleCase, cls).setup_credentials()
+
+This will not allocate any networking resources. This is because by default all
+the arguments default to False.
+
+It's also worth pointing out that it is common for base test classes for
+different services (and scenario tests) to override this setting. When
+inheriting from classes other than the base TestCase in tempest/test.py it is
+worth checking the immediate parent for what is set to determine if your
+class needs to override that setting.
+
+Interacting with Credentials and Clients
+========================================
+
+Once you have your basic TestCase setup you'll want to start writing tests. To
+do that you need to interact with an OpenStack deployment. This section will
+cover how credentials and clients are used inside of Tempest tests.
+
+
+Manager Objects
+---------------
+
+The primary interface with which you interact with both credentials and
+API clients is the client manager object. These objects are created
+automatically by the base test class as part of credential setup (for more
+details see the previous :ref:`credentials` section). Each manager object is
+initialized with a set of credentials and has each client object already setup
+to use that set of credentials for making all the API requests. Each client is
+accessible as a top level attribute on the manager object. So to start making
+API requests you just access the client's method for making that call and the
+credentials are already setup for you. For example if you wanted to make an API
+call to create a server in Nova::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+    def test_example_create_server(self):
+      self.os.servers_client.create_server(...)
+
+is all you need to do. As described previously, in the above example the ``self.os``
+is created automatically because the base test class sets the ``credentials``
+attribute to allocate a primary credential set and initializes the client
+manager as ``self.os``. This same access pattern can be used for all of the
+clients in Tempest.
+
+Credentials Objects
+-------------------
+
+In certain cases you need direct access to the credentials (the most common
+use case would be an API request that takes a user or project id in the request
+body). If you're in a situation where you need to access this you'll need to
+access the ``credentials`` object which is allocated from the configured
+credential provider in the base test class. This is accessible from the manager
+object via the manager's ``credentials`` attribute. For example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+    def test_example_create_server(self):
+      credentials = self.os.credentials
+
+The credentials object provides access to all of the credential information you
+would need to make API requests. For example, building off the previous
+example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+    def test_example_create_server(self):
+      credentials = self.os.credentials
+      username = credentials.username
+      user_id = credentials.user_id
+      password = credentials.password
+      tenant_id = credentials.tenant_id
diff --git a/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml b/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
new file mode 100644
index 0000000..24ec512
--- /dev/null
+++ b/releasenotes/notes/16.0.0-mitaka-eol-88ff8355fff81b55.yaml
@@ -0,0 +1,13 @@
+---
+prelude: >
+    This release indicates end of support for Mitaka in Tempest.
+other:
+  - |
+    OpenStack Releases Supported after this release are **Newton**
+    and **Ocata**
+
+    The release under current development as of this tag is Pike,
+    meaning that every Tempest commit is also tested against master branch
+    during the Pike cycle. However, this does not necessarily mean that
+    using Tempest as of this tag will work against Pike (or future
+    releases) cloud.
diff --git a/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
new file mode 100644
index 0000000..6b45666
--- /dev/null
+++ b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Add a new client to handle the OAUTH consumers feature from the identity API.
diff --git a/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml b/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
new file mode 100644
index 0000000..01136c6
--- /dev/null
+++ b/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Add missing API call, list all role inference rules,
+    to the roles_client library. This feature enables the
+    possibility of listing all role inference rules in the
+    system.
diff --git a/releasenotes/notes/add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml b/releasenotes/notes/add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml
new file mode 100644
index 0000000..6801858
--- /dev/null
+++ b/releasenotes/notes/add-cascade-parameter-to-volumes-client-ff4f7f12795003a4.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Add cascade parameter to volumes_client.
+    This option provides the ability to delete a volume and have Cinder
+    handle deletion of snapshots associated with that volume by passing
+    an additional argument to volume delete, "cascade=True".
diff --git a/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml b/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
new file mode 100644
index 0000000..848a21b
--- /dev/null
+++ b/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
@@ -0,0 +1,3 @@
+---
+features:
+    - Define the compute server evacuate client method in the servers_client library.
diff --git a/releasenotes/notes/add-content-type-without-spaces-b2c9b91b257814f3.yaml b/releasenotes/notes/add-content-type-without-spaces-b2c9b91b257814f3.yaml
new file mode 100644
index 0000000..0075a36
--- /dev/null
+++ b/releasenotes/notes/add-content-type-without-spaces-b2c9b91b257814f3.yaml
@@ -0,0 +1,9 @@
+---
+upgrade:
+  - The ``JSON_ENC`` and ``TXT_ENC`` option in the ``_error_checker``
+    section have been added with additional content-type which are
+    defined in RFC7231 but missing in the currnt rest_client.py file.
+    The lack of these additional content-type will cause defcore test
+    to fail for OpenStack public cloud which uses tomcat module in the
+    api gateway. The additions are ``application/json;charset=utf-8``,
+    ``text/html;charset=utf-8``,``text/plain;charset=utf-8``
\ No newline at end of file
diff --git a/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml b/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml
new file mode 100644
index 0000000..471f8f0
--- /dev/null
+++ b/releasenotes/notes/add-list-auth-project-client-5905076d914a3943.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add the list auth projects API to the identity client library. This feature
+    enables the possibility to list projects that are available to be scoped
+    to based on the X-Auth-Token provided in the request.
diff --git a/releasenotes/notes/add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml b/releasenotes/notes/add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml
new file mode 100644
index 0000000..acc7a41
--- /dev/null
+++ b/releasenotes/notes/add-list-glance-api-versions-ec5fc8081fc8a0ae.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add versions_client module for image service.
+    This new module provides list_versions() method which shows API versions
+    from Image service.
diff --git a/releasenotes/notes/add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml b/releasenotes/notes/add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml
new file mode 100644
index 0000000..233cc28
--- /dev/null
+++ b/releasenotes/notes/add-list-version-to-volume-client-4769dd1bd4ab9c5e.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add versions_client module for volume service.
+    This new module provides list_versions() method which shows API versions
+    from Volume service.
diff --git a/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml b/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
new file mode 100644
index 0000000..06f4fcd
--- /dev/null
+++ b/releasenotes/notes/add-quota-sets-detail-kwarg-74b72183295b3ce7.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Interface show_quota_set of compute quotas_client has been extended to include the
+    argument "detail", which allows for detailed quota set information for a project to be
+    retrieved, if set to True.
diff --git a/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml b/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
new file mode 100644
index 0000000..1b8cda2
--- /dev/null
+++ b/releasenotes/notes/add-tempest-lib-remote-client-adbeb3f42a36910b.yaml
@@ -0,0 +1,11 @@
+---
+features:
+  - |
+    Add remote_client under tempest.lib.
+    This remote_client under tempest.lib is defined as stable
+    interface, and now this module provides the following
+    essential methods.
+
+    - exec_command
+    - validate_authentication
+    - ping_host
diff --git a/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml b/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
new file mode 100644
index 0000000..c95e77c
--- /dev/null
+++ b/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add update encryption type API to the v2 encryption_types_client library.
+    This feature enables the possibility to update an encryption type for an
+    existing volume type.
diff --git a/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml b/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
new file mode 100644
index 0000000..3453050
--- /dev/null
+++ b/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
@@ -0,0 +1,9 @@
+---
+features:
+  - |
+    Add the unmanage volume API service method in v2 volumes_client library.
+    Define v2 volume_manage_client client for the volume service as library
+    interfaces, allowing other projects to use this module as stable libraries
+    without maintenance changes.
+
+    * volume_manage_client(v2)
diff --git a/releasenotes/notes/deprecate-deactivate_image-config-7a282c471937bbcb.yaml b/releasenotes/notes/deprecate-deactivate_image-config-7a282c471937bbcb.yaml
new file mode 100644
index 0000000..69c6bb6
--- /dev/null
+++ b/releasenotes/notes/deprecate-deactivate_image-config-7a282c471937bbcb.yaml
@@ -0,0 +1,6 @@
+---
+deprecations:
+  - |
+    The ``deactivate_image`` configuration switch from the ``config`` module
+    is deprecated. It was added to support the older-than-kilo releases
+    which we don't support anymore.
diff --git a/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml b/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
new file mode 100644
index 0000000..c3e43ee
--- /dev/null
+++ b/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
@@ -0,0 +1,7 @@
+---
+deprecations:
+  - |
+    The ``dvr_extra_resources`` configuration switch from the ``config`` module
+    is deprecated. It was added to support the Liberty Release which we don't
+    support anymore.
+
diff --git a/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml b/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
new file mode 100644
index 0000000..788bc95
--- /dev/null
+++ b/releasenotes/notes/deprecate-glance-api-version-config-options-8370b63aea8e14cf.yaml
@@ -0,0 +1,10 @@
+---
+deprecations:
+  - |
+    Glance v1 APIs are deprecated and v2 are current.
+    Tempest should tests only v2 APIs.
+    Below API version selection config options
+    for glance have been deprecated and will be removed in future.
+
+    * CONF.image_feature_enabled.api_v2
+    * CONF.image_feature_enabled.api_v1
diff --git a/releasenotes/notes/deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml b/releasenotes/notes/deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml
new file mode 100644
index 0000000..0660d9c
--- /dev/null
+++ b/releasenotes/notes/deprecated-cinder-api-v1-option-df7d5a54d93db5cf.yaml
@@ -0,0 +1,12 @@
+---
+deprecations:
+  - |
+    Volume v1 API is deprecated and the v3 are CURRENT.
+    Tempest doesn't need to test the v1 API as the default.
+    The volume config option 'api_v1' has been marked as
+    deprecated.
+upgrade:
+  - |
+    The volume config option 'api_v1' default is changed to
+    ``False`` because the volume v1 API has been deprecated
+    since Juno release.
diff --git a/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml b/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml
new file mode 100644
index 0000000..4081f6a
--- /dev/null
+++ b/releasenotes/notes/dreprecate_client_parameters-cb8d069e62957f7e.yaml
@@ -0,0 +1,6 @@
+---
+deprecations:
+  - |
+    Deprecate the client_parameters argument in
+    `tempest.lib.services.clients.ServiceClients`. The parameter is actually
+    not honoured already - see https://bugs.launchpad.net/tempest/+bug/1680915
diff --git a/releasenotes/notes/fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml b/releasenotes/notes/fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml
new file mode 100644
index 0000000..6d31576
--- /dev/null
+++ b/releasenotes/notes/fix-volume-v2-service-clients-bugfix-1667354-73d2c3c8fedc08bf.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+  - |
+    Fix below volume v2 service clients to make v2 API call: Bug#1667354
+
+    - SchedulerStatsClient
+    - CapabilitiesClient
diff --git a/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml b/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml
new file mode 100644
index 0000000..58d45cc
--- /dev/null
+++ b/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    A new ``attr`` decorator has been added in the ``tempest.lib.decorators``
+    module. For example, use it to tag specific tests, which could be leveraged
+    by test runners to run only a subset of Tempest tests.
diff --git a/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml b/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml
new file mode 100644
index 0000000..8c420c8
--- /dev/null
+++ b/releasenotes/notes/move-related_bug-decorator-to-lib-dbfd5c543bbb2805.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    A new ``related_bug`` decorator has been added to
+    ``tempest.lib.decorators``. Use it to decorate and tag a test that was
+    added in relation to a launchpad bug report.
diff --git a/releasenotes/notes/remove-cinder-v1-api-tests-71e266b8d55d475f.yaml b/releasenotes/notes/remove-cinder-v1-api-tests-71e266b8d55d475f.yaml
new file mode 100644
index 0000000..710ad9e
--- /dev/null
+++ b/releasenotes/notes/remove-cinder-v1-api-tests-71e266b8d55d475f.yaml
@@ -0,0 +1,5 @@
+upgrade:
+  - Remove Cinder v1 API tests.
+    Cinder v1 API has been deprecated since Juno release, and Juno is
+    not supported by current Tempest. Then Cinder v1 API tests are
+    removed from Tempest.
diff --git a/releasenotes/notes/remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml b/releasenotes/notes/remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml
new file mode 100644
index 0000000..9d7102f
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-allow_port_security_disabled-option-d0ffaeb2e7817707.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - |
+    The deprecated config option 'allow_port_security_disabled' from compute_feature_enabled
+    group has been removed.
diff --git a/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml b/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
new file mode 100644
index 0000000..b4e4dd1
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
@@ -0,0 +1,11 @@
+---
+upgrade:
+  - |
+    Below deprecated config options from compute group have been removed.
+    Corresponding config options already been available in validation group.
+
+    - ``compute.image_ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``compute.ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``scenario.ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``compute.network_for_ssh`` (available as ``validation.network_for_ssh``)
+    - ``compute.ping_timeout `` (available as ``validation.ping_timeout``)
diff --git a/releasenotes/notes/remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml b/releasenotes/notes/remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml
new file mode 100644
index 0000000..889e862
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-dvr_extra_resources-option-e8c441c38eab7ddd.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+  - |
+    The deprecated config option 'dvr_extra_resources' from network group has been removed.
+    This option was for extra resources which were provisioned to bind a router to Neutron
+    L3 agent. The extra resources need to be provisioned in Liberty release or older,
+    and are not required since Mitaka release. Current Tempest doesn't support Liberty, so
+    this option has been removed from Tempest.
diff --git a/releasenotes/notes/remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml b/releasenotes/notes/remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml
new file mode 100644
index 0000000..8085694
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-identity-reseller-option-4411c7e3951f1094.yaml
@@ -0,0 +1,4 @@
+---
+upgrade:
+  - |
+    The deprecated config option 'reseller' from identity_feature_enabled group has been removed.
diff --git a/releasenotes/notes/remove-sahara-service-available-44a642aa9c634ab4.yaml b/releasenotes/notes/remove-sahara-service-available-44a642aa9c634ab4.yaml
new file mode 100644
index 0000000..c0dc7d7
--- /dev/null
+++ b/releasenotes/notes/remove-sahara-service-available-44a642aa9c634ab4.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+  - |
+    The 'sahara' config option in the 'service-available' group has been moved to the sahara plugin
+    (openstack/sahara-tests) along with tests and service client during the Ocata timeframe.
+    A 'sahara' config option was left over on Tempest side, and it's removed now.
+    As long as the sahara plugin is installed, this change as no impact on users of sahara tests.
diff --git a/releasenotes/notes/volume-transfers-client-e5ed3f5464c0cdc0.yaml b/releasenotes/notes/volume-transfers-client-e5ed3f5464c0cdc0.yaml
new file mode 100644
index 0000000..e5e479b
--- /dev/null
+++ b/releasenotes/notes/volume-transfers-client-e5ed3f5464c0cdc0.yaml
@@ -0,0 +1,18 @@
+---
+features:
+  - |
+    Define volume transfers service clients as libraries.
+    The following volume transfers service clients are defined as library interface.
+
+    * transfers_client(v2)
+deprecations:
+  - |
+    Deprecate volume v2 transfers resource methods from volumes_client(v2) libraries.
+    Same methods are available in new transfers service client: transfers_client(v2)
+    The following methods of volume v2 volumes_clients have been deprecated:
+
+    * create_volume_transfer (v2.volumes_client)
+    * show_volume_transfer (v2.volumes_client)
+    * list_volume_transfers (v2.volumes_client)
+    * delete_volume_transfer (v2.volumes_client)
+    * accept_volume_transfer (v2.volumes_client)
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index eec42cd..97e3a4d 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -11,7 +11,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# tempest Release Notes documentation build configuration file, created by
+# Tempest Release Notes documentation build configuration file, created by
 # sphinx-quickstart on Tue Nov  3 17:40:50 2015.
 #
 # This file is execfile()d with the current directory set to its
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index cea76b4..adec7a7 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
     :maxdepth: 1
 
     unreleased
+    v16.0.0
     v15.0.0
     v14.0.0
     v13.0.0
diff --git a/releasenotes/source/v16.0.0.rst b/releasenotes/source/v16.0.0.rst
new file mode 100644
index 0000000..ae29599
--- /dev/null
+++ b/releasenotes/source/v16.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v16.0.0 Release Notes
+=====================
+
+.. release-notes:: 16.0.0 Release Notes
+   :version: 16.0.0
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 6962e3e..14c42b3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-pbr>=2.0.0 # Apache-2.0
+pbr!=2.1.0,>=2.0.0 # Apache-2.0
 cliff>=2.3.0 # Apache-2.0
 jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
 testtools>=1.4.0 # MIT
@@ -9,8 +9,8 @@
 netaddr!=0.7.16,>=0.7.13 # BSD
 testrepository>=0.0.18 # Apache-2.0/BSD
 oslo.concurrency>=3.8.0 # Apache-2.0
-oslo.config!=3.18.0,>=3.14.0 # Apache-2.0
-oslo.log>=3.11.0 # Apache-2.0
+oslo.config>=3.22.0 # Apache-2.0
+oslo.log>=3.22.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
 oslo.utils>=3.20.0 # Apache-2.0
 six>=1.9.0 # MIT
diff --git a/setup.cfg b/setup.cfg
index 96313fd..b2035bc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -45,12 +45,10 @@
     tempest.config = tempest.config:list_opts
 
 [build_sphinx]
-all_files = 1
+all-files = 1
+warning-is-error = 1
 build-dir = doc/build
 source-dir = doc/source
 
-[pbr]
-warnerrors = True
-
 [wheel]
 universal = 1
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 118ad60..4ae4372 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -13,7 +13,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 36ce975..2f5382e 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -17,8 +17,8 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 00107cd..69689a7 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -15,10 +15,9 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils import data_utils
+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
 
 
 class AggregatesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -47,7 +46,7 @@
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         return aggregate
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
     def test_aggregate_create_as_user(self):
         # Regular user is not allowed to create an aggregate.
@@ -56,7 +55,7 @@
                           self.user_client.create_aggregate,
                           name=aggregate_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -64,7 +63,7 @@
                           self.client.create_aggregate,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -73,7 +72,7 @@
                           self.client.create_aggregate,
                           name=aggregate_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -82,7 +81,7 @@
                           self.client.create_aggregate,
                           name=aggregate['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
@@ -91,14 +90,14 @@
                           self.user_client.delete_aggregate,
                           aggregate['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -107,21 +106,21 @@
                           self.user_client.show_aggregate,
                           aggregate['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -135,7 +134,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.add_host,
                           aggregate['id'], host=non_exist_host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -144,7 +143,7 @@
                           self.user_client.add_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
     def test_aggregate_add_existent_host(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -157,7 +156,7 @@
         self.assertRaises(lib_exc.Conflict, self.client.add_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -172,7 +171,7 @@
                           self.user_client.remove_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index faeb811..a58c22c 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class AZAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -26,7 +25,7 @@
         super(AZAdminNegativeTestJSON, cls).setup_clients()
         cls.non_adm_client = cls.availability_zone_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
deleted file mode 100644
index 7726ed4..0000000
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2015 NEC Corporation.  All rights reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.api.compute import base
-from tempest import config
-from tempest.lib import decorators
-from tempest import test
-
-CONF = config.CONF
-
-
-class BaremetalNodesAdminTestJSON(base.BaseV2ComputeAdminTest):
-    """Tests Baremetal API"""
-
-    @classmethod
-    def resource_setup(cls):
-        super(BaremetalNodesAdminTestJSON, cls).resource_setup()
-        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'])
-    @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 _ in range(0, 3):
-            _, node = self.ironic_client.create_node()
-            test_nodes.append(node)
-            self.addCleanup(self.ironic_client.delete_node, node['uuid'])
-
-        # List all baremetal nodes and ensure our created test nodes are
-        # listed
-        bm_node_ids = set([n['id'] for n in
-                           self.client.list_baremetal_nodes()['nodes']])
-        test_node_ids = set([n['uuid'] for n in test_nodes])
-        self.assertTrue(test_node_ids.issubset(bm_node_ids))
-
-        # Test getting each individually
-        for node in test_nodes:
-            baremetal_node = self.client.show_baremetal_node(node['uuid'])
-            self.assertEqual(node['uuid'], baremetal_node['node']['id'])
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index 073f152..5134b81 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -49,14 +49,14 @@
             if cls.ip:
                 break
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
     @test.services('network')
     def test_set_reserve_with_non_admin_user(self):
@@ -64,7 +64,7 @@
                           self.non_admin_client.reserve_fixed_ip,
                           self.ip, reserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
     @test.services('network')
     def test_set_unreserve_with_non_admin_user(self):
@@ -72,7 +72,7 @@
                           self.non_admin_client.reserve_fixed_ip,
                           self.ip, unreserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
     @test.services('network')
     def test_set_reserve_with_invalid_ip(self):
@@ -85,7 +85,7 @@
                           self.client.reserve_fixed_ip,
                           "my.invalid.ip", reserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
     @test.services('network')
     def test_fixed_ip_with_invalid_action(self):
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index c3c88a5..3821895 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -16,7 +16,7 @@
 import uuid
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 12e4587..be165cb 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -43,7 +43,7 @@
         cls.vcpus = 1
         cls.disk = 10
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -53,7 +53,7 @@
                           self.admin_flavors_client.list_flavor_access,
                           flavor['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -64,7 +64,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -81,7 +81,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
     def test_add_flavor_access_duplicate(self):
         # Create a new flavor.
@@ -101,7 +101,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
     def test_remove_flavor_access_not_found(self):
         # Create a new flavor.
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index ee1e3a0..4d7abb6 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
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 dab83e5..f39feb9 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -15,7 +15,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
@@ -62,7 +62,7 @@
         cls.admin_flavors_client.wait_for_resource_deletion(cls.flavor['id'])
         super(FlavorsExtraSpecsNegativeTestJSON, cls).resource_cleanup()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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.
@@ -71,7 +71,7 @@
                           self.flavor['id'],
                           key1="value1", key2="value2")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -85,7 +85,7 @@
                           'key1',
                           key1='value1_new')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
     def test_flavor_non_admin_unset_keys(self):
         self.admin_flavors_client.set_flavor_extra_spec(
@@ -96,7 +96,7 @@
                           self.flavor['id'],
                           'key1')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
     def test_flavor_unset_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
@@ -104,7 +104,7 @@
                           self.flavor['id'],
                           'nonexistent_key')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
     def test_flavor_get_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
@@ -112,7 +112,7 @@
                           self.flavor['id'],
                           "nonexistent_key")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -122,7 +122,7 @@
                           "key2",
                           key1="value")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 07ab8c5..684f656 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class HostsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -35,26 +34,26 @@
             raise lib_exc.NotFound("no host found")
         cls.hostname = hosts[0]['host_name']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
     def test_update_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -63,7 +62,7 @@
                           status='enable',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
@@ -73,7 +72,7 @@
                           status='invalid',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'
@@ -83,7 +82,7 @@
                           status='enable',
                           maintenance_mode='invalid')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
@@ -91,7 +90,7 @@
                           self.client.update_host,
                           self.hostname)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
     def test_update_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
@@ -100,42 +99,42 @@
                           status='enable',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
     def test_reboot_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index 4637024..e0e5a29 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -104,7 +104,7 @@
             try:
                 uptime = (self.client.show_hypervisor_uptime(hyper['id'])
                           ['hypervisor'])
-                if len(uptime) > 0:
+                if uptime:
                     has_valid_uptime = True
                     break
             except Exception:
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index 1a37312..2addce9 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
 
 
 class HypervisorAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -34,7 +33,7 @@
         hypers = self.client.list_hypervisors()['hypervisors']
         return hypers
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
     def test_show_nonexistent_hypervisor(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
@@ -44,7 +43,7 @@
             self.client.show_hypervisor,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
     def test_show_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -55,7 +54,7 @@
             self.non_adm_client.show_hypervisor,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
     def test_show_servers_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -66,7 +65,7 @@
             self.non_adm_client.list_servers_on_hypervisor,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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 +75,14 @@
             self.client.list_servers_on_hypervisor,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
     def test_get_nonexistent_hypervisor_uptime(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
@@ -93,7 +92,7 @@
             self.client.show_hypervisor_uptime,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
     def test_get_hypervisor_uptime_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -104,7 +103,7 @@
             self.non_adm_client.show_hypervisor_uptime,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -112,7 +111,7 @@
             lib_exc.Forbidden,
             self.non_adm_client.list_hypervisors)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -120,7 +119,7 @@
             lib_exc.Forbidden,
             self.non_adm_client.list_hypervisors, detail=True)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
     def test_search_nonexistent_hypervisor(self):
         self.assertRaises(
@@ -128,7 +127,7 @@
             self.client.search_hypervisor,
             'nonexistent_hypervisor_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
     def test_search_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
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 16c39c4..92235cc 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
@@ -20,7 +20,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -30,7 +29,7 @@
         super(InstanceUsageAuditLogNegativeTestJSON, cls).setup_clients()
         cls.adm_client = cls.os_adm.instance_usages_audit_log_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -43,7 +42,7 @@
                           show_instance_usage_audit_log,
                           urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8')
     def test_get_instance_usage_audit_logs_with_invalid_time(self):
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/admin/test_keypairs_v210.py b/tempest/api/compute/admin/test_keypairs_v210.py
index 82d3bae..b6c2c3d 100644
--- a/tempest/api/compute/admin/test_keypairs_v210.py
+++ b/tempest/api/compute/admin/test_keypairs_v210.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute.keypairs import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 3ffd238..4d0f12a 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
+from oslo_log import log as logging
 import testtools
 
 from tempest.api.compute import base
@@ -23,6 +23,7 @@
 from tempest import test
 
 CONF = config.CONF
+LOG = logging.getLogger(__name__)
 
 
 class LiveBlockMigrationTestJSON(base.BaseV2ComputeAdminTest):
@@ -80,6 +81,22 @@
             if host != target_host:
                 return target_host
 
+    def _live_migrate(self, server_id, target_host, state,
+                      volume_backed=False):
+        self._migrate_server_to(server_id, target_host, volume_backed)
+        waiters.wait_for_server_status(self.servers_client, server_id, state)
+        migration_list = (self.admin_migration_client.list_migrations()
+                          ['migrations'])
+
+        msg = ("Live Migration failed. Migrations list for Instance "
+               "%s: [" % server_id)
+        for live_migration in migration_list:
+            if (live_migration['instance_uuid'] == server_id):
+                msg += "\n%s" % live_migration
+        msg += "]"
+        self.assertEqual(target_host, self._get_host_for_server(server_id),
+                         msg)
+
     def _test_live_migration(self, state='ACTIVE', volume_backed=False):
         """Tests live migration between two hosts.
 
@@ -94,27 +111,23 @@
         # Live migrate an instance to another host
         server_id = self.create_test_server(wait_until="ACTIVE",
                                             volume_backed=volume_backed)['id']
-        actual_host = self._get_host_for_server(server_id)
-        target_host = self._get_host_other_than(actual_host)
+        source_host = self._get_host_for_server(server_id)
+        destination_host = self._get_host_other_than(source_host)
 
         if state == 'PAUSED':
             self.admin_servers_client.pause_server(server_id)
             waiters.wait_for_server_status(self.admin_servers_client,
                                            server_id, state)
 
-        self._migrate_server_to(server_id, target_host, volume_backed)
-        waiters.wait_for_server_status(self.servers_client, server_id, state)
-        migration_list = (self.admin_migration_client.list_migrations()
-                          ['migrations'])
-
-        msg = ("Live Migration failed. Migrations list for Instance "
-               "%s: [" % server_id)
-        for live_migration in migration_list:
-            if (live_migration['instance_uuid'] == server_id):
-                msg += "\n%s" % live_migration
-        msg += "]"
-        self.assertEqual(target_host, self._get_host_for_server(server_id),
-                         msg)
+        LOG.info("Live migrate from source %s to destination %s",
+                 source_host, destination_host)
+        self._live_migrate(server_id, destination_host, state, volume_backed)
+        if CONF.compute_feature_enabled.live_migrate_back_and_forth:
+            # If live_migrate_back_and_forth is enabled it is a grenade job.
+            # Therefore test should validate whether LM is compatible in both
+            # ways, so live migrate VM back to the source host
+            LOG.info("Live migrate back to source %s", source_host)
+            self._live_migrate(server_id, source_host, state, volume_backed)
 
     @decorators.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
     def test_live_block_migration(self):
@@ -149,11 +162,17 @@
 
         # Attach the volume to the server
         self.attach_volume(server, volume, device='/dev/xvdb')
-
+        server = self.admin_servers_client.show_server(server_id)['server']
+        volume_id1 = server["os-extended-volumes:volumes_attached"][0]["id"]
         self._migrate_server_to(server_id, target_host)
         waiters.wait_for_server_status(self.servers_client,
                                        server_id, 'ACTIVE')
+
+        server = self.admin_servers_client.show_server(server_id)['server']
+        volume_id2 = server["os-extended-volumes:volumes_attached"][0]["id"]
+
         self.assertEqual(target_host, self._get_host_for_server(server_id))
+        self.assertEqual(volume_id1, volume_id2)
 
 
 class LiveAutoBlockMigrationV225TestJSON(LiveBlockMigrationTestJSON):
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 18655cb..df8b175 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -15,9 +15,9 @@
 import testtools
 
 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 data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
 
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 3e9dc79..c9d7722 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -18,7 +18,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.common.utils import data_utils
 from tempest.lib import decorators
 
 LOG = logging.getLogger(__name__)
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index ca8382f..cc4654d 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -13,8 +13,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 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
@@ -51,7 +51,7 @@
         self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
                         **{quota_item: default_quota_value})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
     def test_update_quota_normal_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -61,7 +61,7 @@
 
     # TODO(afazekas): Add dedicated tenant to the skipped quota tests.
     # It can be moved into the setUpClass as well.
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -69,7 +69,7 @@
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -77,7 +77,7 @@
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -87,7 +87,7 @@
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
     @test.services('network')
     def test_security_groups_exceed_limit(self):
@@ -106,7 +106,7 @@
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
     @test.services('network')
     def test_security_groups_rules_exceed_limit(self):
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 2efe755..b4d0f2a 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 9e1c0e9..aff61bf 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -15,10 +15,9 @@
 from tempest.api.compute import base
 from tempest.common import compute
 from tempest.common import fixed_network
-from tempest.common.utils import data_utils
 from tempest.common import waiters
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
@@ -35,14 +34,15 @@
         super(ServersAdminTestJSON, cls).resource_setup()
 
         cls.s1_name = data_utils.rand_name(cls.__name__ + '-server')
-        server = cls.create_test_server(name=cls.s1_name,
-                                        wait_until='ACTIVE')
+        server = cls.create_test_server(name=cls.s1_name)
         cls.s1_id = server['id']
 
         cls.s2_name = data_utils.rand_name(cls.__name__ + '-server')
         server = cls.create_test_server(name=cls.s2_name,
                                         wait_until='ACTIVE')
         cls.s2_id = server['id']
+        waiters.wait_for_server_status(cls.non_admin_client,
+                                       cls.s1_id, 'ACTIVE')
 
     @decorators.idempotent_id('06f960bb-15bb-48dc-873d-f96e89be7870')
     def test_list_servers_filter_by_error_status(self):
@@ -92,7 +92,7 @@
         self.assertIn(self.s1_name, servers_name)
         self.assertIn(self.s2_name, servers_name)
 
-    @test.related_bug('1659811')
+    @decorators.related_bug('1659811')
     @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
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index adb49a5..677972e 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -16,12 +16,11 @@
 
 from tempest.api.compute import base
 from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils import data_utils
 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
 
@@ -47,7 +46,7 @@
     @decorators.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_using_overlimit_ram(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
@@ -69,7 +68,7 @@
     @decorators.idempotent_id('7368a427-2f26-4ad9-9ba9-911a0ec2b0db')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_using_overlimit_vcpus(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
@@ -88,27 +87,27 @@
                           self.servers[0]['id'],
                           flavor_ref['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -116,7 +115,7 @@
                           self.non_adm_client.show_server_diagnostics,
                           self.s1_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('46a4e1ca-87ae-4d28-987a-1b6b136a0221')
     def test_migrate_non_existent_server(self):
         # migrate a non existent server
@@ -129,7 +128,7 @@
                           'Resize not available.')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_migrate_server_invalid_state(self):
         # create server.
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index 9447a09..1edfc89 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ServicesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -27,13 +26,13 @@
         cls.client = cls.os_adm.services_client
         cls.non_admin_client = cls.services_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -42,7 +41,7 @@
                         ['services'])
         self.assertEqual(len(services), len(services_xxx))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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']
@@ -51,7 +50,7 @@
                                              binary='xxx')['services']
         self.assertEqual(0, len(services))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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']
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 35762d6..222d28c 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -18,7 +18,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TenantUsagesNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -41,7 +40,7 @@
         # Returns formatted datetime
         return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -51,7 +50,7 @@
                           self.adm_client.show_tenant_usage,
                           '', **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4079dd2a-9e8d-479f-869d-6fa985ce45b6')
     def test_get_usage_tenant_with_invalid_date(self):
         # Get usage for tenant with invalid date
@@ -61,7 +60,7 @@
                           self.adm_client.show_tenant_usage,
                           self.client.tenant_id, **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 45472df..22a5bc4 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -10,10 +10,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.api.compute import base
 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
@@ -30,6 +33,9 @@
     5. Swap volume from "volume1" to "volume2" as admin.
     6. Check the swap volume is successful and "volume2"
        is attached to "instance1" and "volume1" is in available state.
+    7. Swap volume from "volume2" to "volume1" as admin.
+    8. Check the swap volume is successful and "volume1"
+       is attached to "instance1" and "volume2" is in available state.
     """
 
     @classmethod
@@ -38,6 +44,41 @@
         if not CONF.compute_feature_enabled.swap_volume:
             raise cls.skipException("Swapping volumes is not supported.")
 
+    def _wait_for_server_volume_swap(self, server_id, old_volume_id,
+                                     new_volume_id):
+        """Waits for a server to swap the old volume to a new one."""
+        volume_attachments = self.servers_client.list_volume_attachments(
+            server_id)['volumeAttachments']
+        attached_volume_ids = [attachment['volumeId']
+                               for attachment in volume_attachments]
+        start = int(time.time())
+
+        while (old_volume_id in attached_volume_ids) \
+                or (new_volume_id not in attached_volume_ids):
+            time.sleep(self.servers_client.build_interval)
+            volume_attachments = self.servers_client.list_volume_attachments(
+                server_id)['volumeAttachments']
+            attached_volume_ids = [attachment['volumeId']
+                                   for attachment in volume_attachments]
+
+            if int(time.time()) - start >= self.servers_client.build_timeout:
+                old_vol_bdm_status = 'in BDM' \
+                    if old_volume_id in attached_volume_ids else 'not in BDM'
+                new_vol_bdm_status = 'in BDM' \
+                    if new_volume_id in attached_volume_ids else 'not in BDM'
+                message = ('Failed to swap old volume %(old_volume_id)s '
+                           '(current %(old_vol_bdm_status)s) to new volume '
+                           '%(new_volume_id)s (current %(new_vol_bdm_status)s)'
+                           ' on server %(server_id)s within the required time '
+                           '(%(timeout)s s)' %
+                           {'old_volume_id': old_volume_id,
+                            'old_vol_bdm_status': old_vol_bdm_status,
+                            'new_volume_id': new_volume_id,
+                            'new_vol_bdm_status': new_vol_bdm_status,
+                            'server_id': server_id,
+                            'timeout': self.servers_client.build_timeout})
+                raise lib_exc.TimeoutException(message)
+
     @decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
     @test.services('volume')
     def test_volume_swap(self):
@@ -58,13 +99,25 @@
                                                 volume1['id'], 'available')
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume2['id'], 'in-use')
-        self.addCleanup(self.servers_client.detach_volume,
-                        server['id'], volume2['id'])
+        self._wait_for_server_volume_swap(server['id'], volume1['id'],
+                                          volume2['id'])
         # Verify "volume2" is attached to the server
         vol_attachments = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
         self.assertEqual(1, len(vol_attachments))
         self.assertIn(volume2['id'], vol_attachments[0]['volumeId'])
 
-        # TODO(mriedem): Test swapping back from volume2 to volume1 after
-        # nova bug 1490236 is fixed.
+        # Swap volume from "volume2" to "volume1"
+        self.admin_servers_client.update_attached_volume(
+            server['id'], volume2['id'], volumeId=volume1['id'])
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                volume2['id'], 'available')
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                volume1['id'], 'in-use')
+        self._wait_for_server_volume_swap(server['id'], volume2['id'],
+                                          volume1['id'])
+        # Verify "volume1" is attached to the server
+        vol_attachments = self.servers_client.list_volume_attachments(
+            server['id'])['volumeAttachments']
+        self.assertEqual(1, len(vol_attachments))
+        self.assertIn(volume1['id'], vol_attachments[0]['volumeId'])
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index 905bc3d..4a7f36f 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -13,11 +13,10 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 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
 
@@ -36,7 +35,7 @@
         super(VolumesAdminNegativeTest, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('309b5ecd-0585-4a7e-a36f-d2b2bf55259d')
     def test_update_attached_volume_with_nonexistent_volume_in_uri(self):
         volume = self.create_volume()
@@ -46,8 +45,8 @@
                           self.server['id'], nonexistent_volume,
                           volumeId=volume['id'])
 
-    @test.related_bug('1629110', status_code=400)
-    @test.attr(type=['negative'])
+    @decorators.related_bug('1629110', status_code=400)
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
     def test_update_attached_volume_with_nonexistent_volume_in_body(self):
         volume = self.create_volume()
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 55cc293..1736463 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -19,11 +19,11 @@
 
 from tempest.api.compute import api_microversion_fixture
 from tempest.common import compute
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common import api_version_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
@@ -94,10 +94,7 @@
             cls.os.security_group_default_rules_client)
         cls.versions_client = cls.os.compute_versions_client
 
-        if CONF.volume_feature_enabled.api_v1:
-            cls.volumes_client = cls.os.volumes_client
-        else:
-            cls.volumes_client = cls.os.volumes_v2_client
+        cls.volumes_client = cls.os.volumes_v2_client
 
     @classmethod
     def resource_setup(cls):
@@ -295,20 +292,22 @@
     @classmethod
     def create_image_from_server(cls, server_id, **kwargs):
         """Wrapper utility that returns an image created from the server."""
-        name = data_utils.rand_name(cls.__name__ + "-image")
-        if 'name' in kwargs:
-            name = kwargs.pop('name')
+        name = kwargs.pop('name',
+                          data_utils.rand_name(cls.__name__ + "-image"))
+        wait_until = kwargs.pop('wait_until', None)
+        wait_for_server = kwargs.pop('wait_for_server', True)
 
-        image = cls.compute_images_client.create_image(server_id, name=name)
+        image = cls.compute_images_client.create_image(server_id, name=name,
+                                                       **kwargs)
         image_id = data_utils.parse_image_id(image.response['location'])
         cls.images.append(image_id)
 
-        if 'wait_until' in kwargs:
+        if wait_until is not None:
             try:
                 waiters.wait_for_image_status(cls.compute_images_client,
-                                              image_id, kwargs['wait_until'])
+                                              image_id, wait_until)
             except lib_exc.NotFound:
-                if kwargs['wait_until'].upper() == 'ACTIVE':
+                if wait_until.upper() == 'ACTIVE':
                     # If the image is not found after create_image returned
                     # that means the snapshot failed in nova-compute and nova
                     # deleted the image. There should be a compute fault
@@ -326,8 +325,8 @@
                     raise
             image = cls.compute_images_client.show_image(image_id)['image']
 
-            if kwargs['wait_until'] == 'ACTIVE':
-                if kwargs.get('wait_for_server', True):
+            if wait_until.upper() == 'ACTIVE':
+                if wait_for_server:
                     waiters.wait_for_server_status(cls.servers_client,
                                                    server_id, 'ACTIVE')
         return image
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index 89051c1..bf4c958 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -15,14 +15,13 @@
 
 from tempest.api.compute import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class FlavorsV2TestJSON(base.BaseV2ComputeTest):
     _min_disk = 'minDisk'
     _min_ram = 'minRam'
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
     def test_list_flavors(self):
         # List of all flavors should contain the expected flavor
@@ -39,7 +38,7 @@
         flavor = self.flavors_client.show_flavor(self.flavor_ref)['flavor']
         self.assertIn(flavor, flavors)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
     def test_get_flavor(self):
         # The expected flavor details should be returned
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index b313f44..b2c33e2 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -19,8 +19,8 @@
 
 from tempest.api.compute import base
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 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
@@ -42,7 +42,7 @@
                 'Either api_v1 or api_v2 must be True in '
                 '[image-feature-enabled].')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('image')
     @decorators.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
     def test_boot_with_low_ram(self):
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 5e47d18..cce9856 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
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.compute.floating_ips import base
-from tempest.common.utils import data_utils
 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
@@ -48,7 +48,7 @@
             if cls.non_exist_id not in floating_ip_ids:
                 break
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
     @test.services('network')
     def test_allocate_floating_ip_from_nonexistent_pool(self):
@@ -58,7 +58,7 @@
                           self.client.create_floating_ip,
                           pool="non_exist_pool")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
     @test.services('network')
     def test_delete_nonexistent_floating_ip(self):
@@ -69,7 +69,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_floating_ip,
                           self.non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
     @test.services('network')
     def test_associate_nonexistent_floating_ip(self):
@@ -80,7 +80,7 @@
                           self.client.associate_floating_ip_to_server,
                           "0.0.0.0", self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
     @test.services('network')
     def test_dissociate_nonexistent_floating_ip(self):
@@ -90,7 +90,7 @@
                           self.client.disassociate_floating_ip_from_server,
                           "0.0.0.0", self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
     @test.services('network')
     def test_associate_ip_to_server_without_passing_floating_ip(self):
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 00a4075..9d70bf7 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
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 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
@@ -30,7 +30,7 @@
         super(FloatingIPDetailsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
     @test.services('network')
     def test_get_nonexistent_floating_ip_details(self):
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index f131007..dcc44d8 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -17,9 +17,9 @@
 
 from tempest.api.compute import base
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 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
 
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 0f5b9d8..03d0789 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
 
 
 class ImagesMetadataNegativeTestJSON(base.BaseV2ComputeTest):
@@ -27,7 +26,7 @@
         super(ImagesMetadataNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
     def test_list_nonexistent_image_metadata(self):
         # Negative test: List on nonexistent image
@@ -35,7 +34,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.list_image_metadata,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -44,7 +43,7 @@
                           self.client.update_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -52,7 +51,7 @@
                           self.client.show_image_metadata_item,
                           data_utils.rand_uuid(), 'os_version')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -60,7 +59,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.set_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -71,7 +70,7 @@
                           data_utils.rand_uuid(), 'os_distro',
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index a0c860a..29bd6da 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -13,10 +13,11 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
+import testtools
 
 CONF = config.CONF
 
@@ -64,3 +65,39 @@
                                               wait_for_server=False)
         self.addCleanup(self.client.delete_image, image['id'])
         self.assertEqual(snapshot_name, image['name'])
+
+    @decorators.idempotent_id('71bcb732-0261-11e7-9086-fa163e4fa634')
+    @testtools.skipUnless(CONF.compute_feature_enabled.pause,
+                          'Pause is not available.')
+    def test_create_image_from_paused_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.servers_client.pause_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'PAUSED')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+
+        snapshot_name = data_utils.rand_name('test-snap')
+        image = self.create_image_from_server(server['id'],
+                                              name=snapshot_name,
+                                              wait_until='ACTIVE',
+                                              wait_for_server=False)
+        self.addCleanup(self.client.delete_image, image['id'])
+        self.assertEqual(snapshot_name, image['name'])
+
+    @decorators.idempotent_id('8ca07fec-0262-11e7-907e-fa163e4fa634')
+    @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
+                          'Suspend is not available.')
+    def test_create_image_from_suspended_server(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+        self.servers_client.suspend_server(server['id'])
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'SUSPENDED')
+        self.addCleanup(self.servers_client.delete_server, server['id'])
+
+        snapshot_name = data_utils.rand_name('test-snap')
+        image = self.create_image_from_server(server['id'],
+                                              name=snapshot_name,
+                                              wait_until='ACTIVE',
+                                              wait_for_server=False)
+        self.addCleanup(self.client.delete_image, image['id'])
+        self.assertEqual(snapshot_name, image['name'])
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 10f3c70..e292389 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -13,12 +13,11 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.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
 
@@ -41,7 +40,7 @@
         super(ImagesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -54,18 +53,18 @@
         meta = {'image_type': 'test'}
         self.assertRaises(lib_exc.NotFound,
                           self.create_image_from_server,
-                          server['id'], meta=meta)
+                          server['id'], metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
         meta = {'image_type': 'test'}
         self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
-                          data_utils.rand_name('invalid'), meta=meta)
+                          data_utils.rand_name('invalid'), metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -74,7 +73,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.create_image,
                           test_uuid, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -83,14 +82,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.create_image,
                           test_uuid, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -99,13 +98,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -113,13 +112,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           invalid_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 7fff555..db24174 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -14,10 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
-from tempest.lib.common.utils import test_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
@@ -53,15 +51,11 @@
         # Create a new image
         name = data_utils.rand_name('image')
         meta = {'image_type': 'test'}
-        body = self.client.create_image(server_id, name=name,
-                                        metadata=meta)
-        image_id = data_utils.parse_image_id(body.response['location'])
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.client.delete_image, image_id)
-        waiters.wait_for_image_status(self.client, image_id, 'ACTIVE')
+        image = self.create_image_from_server(server_id, name=name,
+                                              metadata=meta,
+                                              wait_until='ACTIVE')
 
         # Verify the image was created correctly
-        image = self.client.show_image(image_id)['image']
         self.assertEqual(name, image['name'])
         self.assertEqual('test', image['metadata']['image_type'])
 
@@ -76,8 +70,9 @@
                       (str(original_image['minDisk']), str(flavor_disk_size)))
 
         # Verify the image was deleted correctly
-        self.client.delete_image(image_id)
-        self.client.wait_for_resource_deletion(image_id)
+        self.client.delete_image(image['id'])
+        self.images.remove(image['id'])
+        self.client.wait_for_resource_deletion(image['id'])
 
     @decorators.idempotent_id('3b7c6fe4-dfe7-477c-9243-b06359db51e6')
     def test_create_image_specify_multibyte_character_image_name(self):
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 09bbfbe..cf32ba3 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -17,12 +17,11 @@
 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 data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -33,9 +32,6 @@
 
     def tearDown(self):
         """Terminate test instances created after a test is executed."""
-        for image_id in self.image_ids:
-            self.client.delete_image(image_id)
-            self.image_ids.remove(image_id)
         self.server_check_teardown()
         super(ImagesOneServerNegativeTestJSON, self).tearDown()
 
@@ -80,44 +76,40 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-        cls.image_ids = []
-
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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')
         meta = {'': ''}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_image,
-                          self.server_id, name=snapshot_name, metadata=meta)
+        self.assertRaises(lib_exc.BadRequest, self.create_image_from_server,
+                          self.server_id, metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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')
         meta = {'a' * 256: 'b' * 256}
-        self.assertRaises(lib_exc.BadRequest, self.client.create_image,
-                          self.server_id, name=snapshot_name, metadata=meta)
+        self.assertRaises(lib_exc.BadRequest, self.create_image_from_server,
+                          self.server_id, metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
 
         # Create first snapshot
-        snapshot_name = data_utils.rand_name('test-snap')
-        body = self.client.create_image(self.server_id, name=snapshot_name)
-        image_id = data_utils.parse_image_id(body.response['location'])
-        self.image_ids.append(image_id)
+        image = self.create_image_from_server(self.server_id)
         self.addCleanup(self._reset_server)
 
         # Create second snapshot
-        alt_snapshot_name = data_utils.rand_name('test-snap')
-        self.assertRaises(lib_exc.Conflict, self.client.create_image,
-                          self.server_id, name=alt_snapshot_name)
+        self.assertRaises(lib_exc.Conflict, self.create_image_from_server,
+                          self.server_id)
 
-    @test.attr(type=['negative'])
+        image_id = data_utils.parse_image_id(image.response['location'])
+        self.client.delete_image(image_id)
+        self.images.remove(image_id)
+
+    @decorators.attr(type=['negative'])
     @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,19 +118,18 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           self.server_id, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
 
-        snapshot_name = data_utils.rand_name('test-snap')
-        body = self.client.create_image(self.server_id, name=snapshot_name)
-        image_id = data_utils.parse_image_id(body.response['location'])
-        self.image_ids.append(image_id)
+        image = self.create_image_from_server(self.server_id)
+        image_id = data_utils.parse_image_id(image.response['location'])
+
         self.addCleanup(self._reset_server)
 
         # Do not wait, attempt to delete the image, ensure it's successful
         self.client.delete_image(image_id)
-        self.image_ids.remove(image_id)
-
-        self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
+        self.images.remove(image_id)
+        self.assertRaises(lib_exc.NotFound,
+                          self.client.show_image, image_id)
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 9c9b8a1..7168a8c 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -20,9 +20,9 @@
 
 from tempest.api.compute import base
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 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
 
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 e04a57a..d37f8fc 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -13,11 +13,10 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 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
 
@@ -36,7 +35,7 @@
         super(ListImageFiltersNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
     def test_get_nonexistent_image(self):
         # Check raises a NotFound
diff --git a/tempest/api/compute/keypairs/base.py b/tempest/api/compute/keypairs/base.py
index 21f504b..0051810 100644
--- a/tempest/api/compute/keypairs/base.py
+++ b/tempest/api/compute/keypairs/base.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 
 
 class BaseKeypairTest(base.BaseV2ComputeTest):
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index 11e84e8..0b7a967 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute.keypairs import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 863ce0d..205076c 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -15,14 +15,13 @@
 #    under the License.
 
 from tempest.api.compute.keypairs import base
-from tempest.common.utils import data_utils
+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
 
 
 class KeyPairsNegativeTestJSON(base.BaseKeypairTest):
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -30,7 +29,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.create_keypair, pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7cc32e47-4c42-489d-9623-c5e2cb5a2fa5')
     def test_keypair_delete_nonexistent_key(self):
         # Non-existent key deletion should throw a proper error
@@ -38,7 +37,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_keypair,
                           k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -46,7 +45,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -54,7 +53,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0359a7f1-f002-4682-8073-0c91e4011b7c')
     def test_create_keypair_with_duplicate_name(self):
         # Keypairs with duplicate names should not be created
@@ -65,14 +64,14 @@
                           k_name)
         self.client.delete_keypair(k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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,
                           '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -80,7 +79,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/keypairs/test_keypairs_v22.py b/tempest/api/compute/keypairs/test_keypairs_v22.py
index c893a4f..f39bb12 100644
--- a/tempest/api/compute/keypairs/test_keypairs_v22.py
+++ b/tempest/api/compute/keypairs/test_keypairs_v22.py
@@ -13,7 +13,7 @@
 #    under the License.
 
 from tempest.api.compute.keypairs import test_keypairs
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index 21b4b1c..bef4eb5 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -17,7 +17,6 @@
 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
 
 
 class AbsoluteLimitsNegativeTestJSON(base.BaseV2ComputeTest):
@@ -32,7 +31,7 @@
         super(AbsoluteLimitsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.limits_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index cb18775..6148e16 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest import test
 
 CONF = config.CONF
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 b82fa3b..3378ef8 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -14,12 +14,9 @@
 #    under the License.
 
 from tempest.api.compute.security_groups import base
-from tempest import config
 from tempest.lib import decorators
 from tempest import test
 
-CONF = config.CONF
-
 
 class SecurityGroupRulesTestJSON(base.BaseSecurityGroupsTest):
 
@@ -56,7 +53,7 @@
             self.assertEqual(self.expected[key], actual_rule[key],
                              "Miss-matched key is %s" % key)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
     @test.services('network')
     def test_security_group_rules_create(self):
@@ -126,7 +123,7 @@
                                   'name': group_name}
         self._check_expected_response(rule)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
     @test.services('network')
     def test_security_group_rules_list(self):
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 0312736..4efb8b7 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
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute.security_groups import base
-from tempest.common.utils import data_utils
+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
@@ -27,7 +27,7 @@
         super(SecurityGroupRulesNegativeTestJSON, cls).setup_clients()
         cls.rules_client = cls.security_group_rules_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
     @test.services('network')
     def test_create_security_group_rule_with_non_existent_id(self):
@@ -44,7 +44,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_id(self):
@@ -61,7 +61,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
     @test.services('network')
     def test_create_security_group_rule_duplicate(self):
@@ -86,7 +86,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_ip_protocol(self):
@@ -106,7 +106,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_from_port(self):
@@ -125,7 +125,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_to_port(self):
@@ -144,7 +144,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_port_range(self):
@@ -163,7 +163,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
     @test.services('network')
     def test_delete_security_group_rule_with_non_existent_id(self):
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index e90a1fc..930a58e 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.compute.security_groups import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
+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
@@ -28,7 +28,7 @@
         super(SecurityGroupsTestJSON, cls).setup_clients()
         cls.client = cls.security_groups_client
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
     @test.services('network')
     def test_security_groups_create_list_delete(self):
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 48bb1b6..207778a 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -16,8 +16,8 @@
 import testtools
 
 from tempest.api.compute.security_groups import base
-from tempest.common.utils import data_utils
 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
@@ -32,7 +32,7 @@
         super(SecurityGroupsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.security_groups_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
     @test.services('network')
     def test_security_group_get_nonexistent_group(self):
@@ -44,7 +44,7 @@
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
     @test.services('network')
     def test_security_group_create_with_invalid_group_name(self):
@@ -67,7 +67,7 @@
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
@@ -84,7 +84,7 @@
     @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'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_security_group_create_with_duplicate_name(self):
         # Negative test:Security Group with duplicate name should not
@@ -97,7 +97,7 @@
                           self.client.create_security_group,
                           name=s_name, description=s_description)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
     @test.services('network')
     def test_delete_the_default_security_group(self):
@@ -113,7 +113,7 @@
                           self.client.delete_security_group,
                           default_security_group_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
     @test.services('network')
     def test_delete_nonexistent_security_group(self):
@@ -122,7 +122,7 @@
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_security_group, non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
     @test.services('network')
     def test_delete_security_group_without_passing_id(self):
@@ -134,7 +134,7 @@
     @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'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_id(self):
         # Update security_group with invalid sg_id should fail
@@ -149,7 +149,7 @@
     @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'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_name(self):
         # Update security_group with invalid sg_name should fail
@@ -165,7 +165,7 @@
     @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'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_des(self):
         # Update security_group with invalid sg_des should fail
@@ -178,7 +178,7 @@
                           self.client.update_security_group,
                           securitygroup_id, description=s_new_des)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
     @test.services('network')
     def test_update_non_existent_security_group(self):
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index e0c8887..06a47d1 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -219,7 +219,7 @@
         _ifs = self._test_delete_interface(server, ifs)
         self.assertEqual(len(ifs) - 1, len(_ifs))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
     @test.services('network')
     def test_add_remove_fixed_ip(self):
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 38dbb50..d54c3ec 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -17,9 +17,9 @@
 import testtools
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -77,7 +77,7 @@
                         subnet['subnet']['id'])
         return net
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
     def test_verify_server_details(self):
         # Verify the specified server attributes are set correctly
@@ -91,7 +91,7 @@
         self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
         self.assertEqual(self.meta, self.server['metadata'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('9a438d88-10c6-4bcd-8b5b-5b6e25e1346f')
     def test_list_servers(self):
         # The created server should be in the list of all servers
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index 5bcbdac..57aa72e 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -17,9 +17,9 @@
 from oslo_log import log as logging
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 85e3281..1d3a790 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
 
 
 class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
@@ -32,7 +31,7 @@
         super(InstanceActionsNegativeTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -41,7 +40,7 @@
                           self.client.list_instance_actions,
                           non_existent_server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 7b782de..1ad153a 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -16,9 +16,9 @@
 
 from tempest.api.compute import base
 from tempest.common import fixed_network
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
@@ -48,23 +48,25 @@
             cls.fixed_network_name = None
         network_kwargs = fixed_network.set_networks_kwarg(network)
         cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
-        cls.s1 = cls.create_test_server(name=cls.s1_name,
-                                        wait_until='ACTIVE',
-                                        **network_kwargs)
+        cls.s1 = cls.create_test_server(name=cls.s1_name, **network_kwargs)
 
         cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
         # If image_ref_alt is "" or None then we still want to boot a server
         # but we rely on `testtools.skipUnless` decorator to actually skip
         # the irrelevant tests.
         cls.s2 = cls.create_test_server(
-            name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref,
-            wait_until='ACTIVE')
+            name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref)
 
         cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
         cls.s3 = cls.create_test_server(name=cls.s3_name,
                                         flavor=cls.flavor_ref_alt,
                                         wait_until='ACTIVE')
 
+        waiters.wait_for_server_status(cls.client, cls.s1['id'],
+                                       'ACTIVE')
+        waiters.wait_for_server_status(cls.client, cls.s2['id'],
+                                       'ACTIVE')
+
     @decorators.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
     @testtools.skipUnless(CONF.compute.image_ref != CONF.compute.image_ref_alt,
                           "Need distinct images to run this test")
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 3010caf..d89f44c 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -17,7 +17,6 @@
 from tempest.common import waiters
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
@@ -36,15 +35,14 @@
         # servers are cleaned up automatically in the
         # tearDownClass method of the super-class.
         cls.deleted_fixtures = []
-        for _ in range(2):
-            srv = cls.create_test_server(wait_until='ACTIVE')
+        cls.create_test_server(wait_until='ACTIVE', min_count=2)
 
         srv = cls.create_test_server(wait_until='ACTIVE')
         cls.client.delete_server(srv['id'])
         waiters.wait_for_server_termination(cls.client, srv['id'])
         cls.deleted_fixtures.append(srv)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -56,7 +54,7 @@
                   if srv['id'] in deleted_ids]
         self.assertEqual([], actual)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -64,7 +62,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -72,7 +70,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -80,7 +78,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -94,7 +92,7 @@
         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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -104,21 +102,21 @@
         body = self.client.list_servers(limit=limit)
         self.assertEqual(len(full_list), len(body['servers']))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -126,7 +124,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -134,7 +132,7 @@
         body = self.client.list_servers(**changes_since)
         self.assertEqual(0, len(body['servers']))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 7e55b12..7cbb513 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
+from tempest.common import compute
 from tempest.lib import decorators
 
 
@@ -21,13 +22,19 @@
 
     @decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
-        body = self.create_test_server(wait_until='ACTIVE',
-                                       min_count=1,
-                                       max_count=2)
+        tenant_network = self.get_tenant_network()
+        body, servers = compute.create_test_server(
+            self.os,
+            wait_until='ACTIVE',
+            min_count=2,
+            tenant_network=tenant_network)
+        for server in servers:
+            self.addCleanup(self.servers_client.delete_server, server['id'])
         # NOTE(maurosr): do status response check and also make sure that
         # reservation_id is not in the response body when the request send
         # contains return_reservation_id=False
         self.assertNotIn('reservation_id', body)
+        self.assertEqual(2, len(servers))
 
     @decorators.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
     def test_multiple_create_with_reservation_return(self):
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index 675cbee..422510f 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -16,40 +16,39 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('476da616-f1ef-4271-a9b1-b9fc87727cdf')
     def test_max_count_less_than_min_count(self):
         min_count = 3
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 3f6abab..90b0665 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -13,14 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import socket
 import struct
 
 import six
-from six.moves.urllib import parse as urlparse
 import urllib3
 
 from tempest.api.compute import base
+from tempest.common import compute
 from tempest import config
 from tempest.lib import decorators
 
@@ -83,33 +82,52 @@
         """Verify we can connect to novnc and do the websocket connection."""
         # Turn the Socket into a WebSocket to do the communication
         data = self._websocket.receive_frame()
-        self.assertFalse(data is None or len(data) == 0,
+        self.assertFalse(data is None or not data,
                          'Token must be invalid because the connection '
                          'closed.')
         # Parse the RFB version from the data to make sure it is valid
-        # and greater than or equal to 3.3
+        # and belong to the known supported RFB versions.
         version = float("%d.%d" % (int(data[4:7], base=10),
                                    int(data[8:11], base=10)))
-        self.assertTrue(version >= 3.3, 'Bad RFB Version: ' + str(version))
-        # Send our RFB version to the server, which we will just go with 3.3
+        # Add the max RFB versions supported
+        supported_versions = [3.3, 3.8]
+        self.assertIn(version, supported_versions,
+                      'Bad RFB Version: ' + str(version))
+        # Send our RFB version to the server
         self._websocket.send_frame(data)
         # Get the sever authentication type and make sure None is supported
         data = self._websocket.receive_frame()
         self.assertIsNotNone(data, 'Expected authentication type None.')
-        self.assertGreaterEqual(
-            len(data), 2, 'Expected authentication type None.')
-        self.assertIn(
-            1, [ord_func(data[i + 1]) for i in range(ord_func(data[0]))],
-            'Expected authentication type None.')
-        # Send to the server that we only support authentication type None
-        self._websocket.send_frame(six.int2byte(1))
-        # The server should send 4 bytes of 0's if security handshake succeeded
-        data = self._websocket.receive_frame()
-        self.assertEqual(
-            len(data), 4, 'Server did not think security was successful.')
-        self.assertEqual(
-            [ord_func(i) for i in data], [0, 0, 0, 0],
-            'Server did not think security was successful.')
+        data_length = len(data)
+        if version == 3.3:
+            # For RFB 3.3: in the security handshake, rather than a two-way
+            # negotiation, the server decides the security type and sends a
+            # single word(4 bytes).
+            self.assertEqual(
+                data_length, 4, 'Expected authentication type None.')
+            self.assertIn(1, [ord_func(data[i]) for i in (0, 3)],
+                          'Expected authentication type None.')
+        else:
+            self.assertGreaterEqual(
+                len(data), 2, 'Expected authentication type None.')
+            self.assertIn(
+                1,
+                [ord_func(data[i + 1]) for i in range(ord_func(data[0]))],
+                'Expected authentication type None.')
+            # Send to the server that we only support authentication
+            # type None
+            self._websocket.send_frame(six.int2byte(1))
+
+            # The server should send 4 bytes of 0's if security
+            # handshake succeeded
+            data = self._websocket.receive_frame()
+            self.assertEqual(
+                len(data), 4,
+                'Server did not think security was successful.')
+            self.assertEqual(
+                [ord_func(i) for i in data], [0, 0, 0, 0],
+                'Server did not think security was successful.')
+
         # Say to leave the desktop as shared as part of client initialization
         self._websocket.send_frame(six.int2byte(1))
         # Get the server initialization packet back and make sure it is the
@@ -139,14 +157,6 @@
             self._websocket.response.find(b'Server: WebSockify') > 0,
             'Did not get the expected WebSocket HTTP Response.')
 
-    def _create_websocket(self, url):
-        url = urlparse.urlparse(url)
-        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        client_socket.connect((url.hostname, url.port))
-        # Turn the Socket into a WebSocket to do the communication
-        return _WebSocket(client_socket, url)
-
     @decorators.idempotent_id('c640fdff-8ab4-45a4-a5d8-7e6146cbd0dc')
     def test_novnc(self):
         body = self.client.get_vnc_console(self.server['id'],
@@ -155,7 +165,7 @@
         # Do the initial HTTP Request to novncproxy to get the NoVNC JavaScript
         self._validate_novnc_html(body['url'])
         # Do the WebSockify HTTP Request to novncproxy to do the RFB connection
-        self._websocket = self._create_websocket(body['url'])
+        self._websocket = compute.create_websocket(body['url'])
         # Validate that we succesfully connected and upgraded to Web Sockets
         self._validate_websocket_upgrade()
         # Validate the RFB Negotiation to determine if a valid VNC session
@@ -168,84 +178,9 @@
         self.assertEqual('novnc', body['type'])
         # Do the WebSockify HTTP Request to novncproxy with a bad token
         url = body['url'].replace('token=', 'token=bad')
-        self._websocket = self._create_websocket(url)
+        self._websocket = compute.create_websocket(url)
         # Make sure the novncproxy rejected the connection and closed it
         data = self._websocket.receive_frame()
-        self.assertTrue(data is None or len(data) == 0,
+        self.assertTrue(data is None or not data,
                         "The novnc proxy actually sent us some data, but we "
                         "expected it to close the connection.")
-
-
-class _WebSocket(object):
-    def __init__(self, client_socket, url):
-        """Contructor for the WebSocket wrapper to the socket."""
-        self._socket = client_socket
-        # Upgrade the HTTP connection to a WebSocket
-        self._upgrade(url)
-
-    def receive_frame(self):
-        """Wrapper for receiving data to parse the WebSocket frame format"""
-        # We need to loop until we either get some bytes back in the frame
-        # or no data was received (meaning the socket was closed).  This is
-        # done to handle the case where we get back some empty frames
-        while True:
-            header = self._socket.recv(2)
-            # If we didn't receive any data, just return None
-            if len(header) == 0:
-                return None
-            # We will make the assumption that we are only dealing with
-            # frames less than 125 bytes here (for the negotiation) and
-            # that only the 2nd byte contains the length, and since the
-            # server doesn't do masking, we can just read the data length
-            if ord_func(header[1]) & 127 > 0:
-                return self._socket.recv(ord_func(header[1]) & 127)
-
-    def send_frame(self, data):
-        """Wrapper for sending data to add in the WebSocket frame format."""
-        frame_bytes = list()
-        # For the first byte, want to say we are sending binary data (130)
-        frame_bytes.append(130)
-        # Only sending negotiation data so don't need to worry about > 125
-        # We do need to add the bit that says we are masking the data
-        frame_bytes.append(len(data) | 128)
-        # We don't really care about providing a random mask for security
-        # So we will just hard-code a value since a test program
-        mask = [7, 2, 1, 9]
-        for i in range(len(mask)):
-            frame_bytes.append(mask[i])
-        # Mask each of the actual data bytes that we are going to send
-        for i in range(len(data)):
-            frame_bytes.append(ord_func(data[i]) ^ mask[i % 4])
-        # Convert our integer list to a binary array of bytes
-        frame_bytes = struct.pack('!%iB' % len(frame_bytes), * frame_bytes)
-        self._socket.sendall(frame_bytes)
-
-    def close(self):
-        """Helper method to close the connection."""
-        # Close down the real socket connection and exit the test program
-        if self._socket is not None:
-            self._socket.shutdown(1)
-            self._socket.close()
-            self._socket = None
-
-    def _upgrade(self, url):
-        """Upgrade the HTTP connection to a WebSocket and verify."""
-        # The real request goes to the /websockify URI always
-        reqdata = 'GET /websockify HTTP/1.1\r\n'
-        reqdata += 'Host: %s:%s\r\n' % (url.hostname, url.port)
-        # Tell the HTTP Server to Upgrade the connection to a WebSocket
-        reqdata += 'Upgrade: websocket\r\nConnection: Upgrade\r\n'
-        # The token=xxx is sent as a Cookie not in the URI
-        reqdata += 'Cookie: %s\r\n' % url.query
-        # Use a hard-coded WebSocket key since a test program
-        reqdata += 'Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n'
-        reqdata += 'Sec-WebSocket-Version: 13\r\n'
-        # We are choosing to use binary even though browser may do Base64
-        reqdata += 'Sec-WebSocket-Protocol: binary\r\n\r\n'
-        # Send the HTTP GET request and get the response back
-        self._socket.sendall(reqdata.encode('utf8'))
-        self.response = data = self._socket.recv(4096)
-        # Loop through & concatenate all of the data in the response body
-        while len(data) > 0 and self.response.find(b'\r\n\r\n') < 0:
-            data = self._socket.recv(4096)
-            self.response += data
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index b915739..751d33a 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -19,10 +19,10 @@
 
 from tempest.api.compute import base
 from tempest.common import compute
-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.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -133,7 +133,7 @@
             self.assertGreater(new_boot_time, boot_time,
                                '%s > %s' % (new_boot_time, boot_time))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
     def test_reboot_server_hard(self):
         # The server should be power cycled
@@ -145,6 +145,18 @@
         # The server should be signaled to reboot gracefully
         self._test_reboot_server('SOFT')
 
+    @decorators.idempotent_id('1d1c9104-1b0a-11e7-a3d4-fa163e65f5ce')
+    def test_remove_server_all_security_groups(self):
+        server = self.create_test_server(wait_until='ACTIVE')
+
+        # Remove all Security group
+        self.client.remove_security_group(
+            server['id'], name=server['security_groups'][0]['name'])
+
+        # Verify all Security group
+        server = self.client.show_server(server['id'])['server']
+        self.assertNotIn('security_groups', server)
+
     def _rebuild_server_and_check(self, image_ref):
         rebuilt_server = (self.client.rebuild_server(self.server_id, image_ref)
                           ['server'])
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index cf4ed85..92b1ff1 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -37,7 +37,7 @@
 
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
     @test.services('network')
     def test_list_server_addresses(self):
@@ -55,7 +55,7 @@
                 self.assertTrue(address['addr'])
                 self.assertTrue(address['version'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
     @test.services('network')
     def test_list_server_addresses_by_network(self):
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index 1884e4f..76a102b 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -36,7 +36,7 @@
         super(ServerAddressesNegativeTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
     @test.services('network')
     def test_list_server_addresses_invalid_server_id(self):
@@ -44,7 +44,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.list_addresses,
                           '999')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
     @test.services('network')
     def test_list_server_addresses_by_network_neg(self):
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index 6679b58..69d7897 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 92ffa86..482ba09 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+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
 
 
 class ServerMetadataNegativeTestJSON(base.BaseV2ComputeTest):
@@ -33,7 +32,7 @@
         cls.tenant_id = cls.client.tenant_id
         cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -49,7 +48,7 @@
 
         # no teardown - all creates should fail
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('92431555-4d8b-467c-b95b-b17daa5e57ff')
     def test_create_server_metadata_blank_key(self):
         # Blank key should trigger an error.
@@ -58,7 +57,7 @@
                           self.create_test_server,
                           metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -68,7 +67,7 @@
                           non_existent_server_id,
                           'test2')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -77,7 +76,7 @@
                           self.client.list_server_metadata,
                           non_existent_server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -87,7 +86,7 @@
                           self.client.set_server_metadata_item,
                           self.server['id'], 'key', meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -98,7 +97,7 @@
                           non_existent_server_id,
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -109,7 +108,7 @@
                           non_existent_server_id,
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a452f38c-05c2-4b47-bd44-a4f0bf5a5e48')
     def test_update_metadata_with_blank_key(self):
         # Blank key should trigger an error
@@ -118,7 +117,7 @@
                           self.client.update_server_metadata,
                           self.server['id'], meta=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -128,7 +127,7 @@
                           non_existent_server_id,
                           'd')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d8c0a210-a5c3-4664-be04-69d96746b547')
     def test_metadata_items_limit(self):
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
@@ -154,7 +153,7 @@
                           self.client.update_server_metadata,
                           self.server['id'], req_metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
     def test_set_server_metadata_blank_key(self):
         # Raise a bad request error for blank key.
@@ -164,7 +163,7 @@
                           self.client.set_server_metadata,
                           self.server['id'], meta=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 75ba15c..8760af6 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -16,9 +16,9 @@
 import testtools
 
 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 data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index c3a8c36..5fac433 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -16,9 +16,9 @@
 import testtools
 
 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 data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -74,7 +74,7 @@
     @decorators.idempotent_id('cc3a883f-43c0-4fb6-a9bb-5579d64984ed')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescue_paused_instance(self):
         # Rescue a paused server
         self.servers_client.pause_server(self.server_id)
@@ -85,13 +85,13 @@
                           self.servers_client.rescue_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
     def test_rescue_non_existent_server(self):
         # Rescue a non-existing server
@@ -100,7 +100,7 @@
                           self.servers_client.rescue_server,
                           non_existent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('70cdb8a1-89f8-437d-9448-8844fd82bf46')
     def test_rescued_vm_rebuild(self):
         self.assertRaises(lib_exc.Conflict,
@@ -110,7 +110,7 @@
 
     @decorators.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
     @test.services('volume')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescued_vm_attach_volume(self):
         volume = self.create_volume()
 
@@ -130,7 +130,7 @@
 
     @decorators.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
     @test.services('volume')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescued_vm_detach_volume(self):
         volume = self.create_volume()
 
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
index 20e2cee..0370215 100644
--- a/tempest/api/compute/servers/test_server_tags.py
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -16,7 +16,7 @@
 import six
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index b463726..11f236b 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -16,9 +16,9 @@
 import testtools
 
 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 data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 1418b3f..a480a15 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -19,9 +19,9 @@
 
 from tempest.api.compute import base
 from tempest.common import compute
-from tempest.common.utils import data_utils
 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
@@ -54,7 +54,7 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dbbfd247-c40c-449e-8f6c-d2aa7c7da7cf')
     def test_server_name_blank(self):
         # Create a server with name parameter empty
@@ -63,7 +63,7 @@
                           self.create_test_server,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
     @testtools.skipUnless(CONF.compute_feature_enabled.personality,
                           'Nova personality feature disabled')
@@ -78,7 +78,7 @@
                           self.create_test_server,
                           personality=person)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fcba1052-0a50-4cf3-b1ac-fae241edf02f')
     def test_create_with_invalid_image(self):
         # Create a server with an unknown image
@@ -87,7 +87,7 @@
                           self.create_test_server,
                           image_id=-1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('18f5227f-d155-4429-807c-ccb103887537')
     def test_create_with_invalid_flavor(self):
         # Create a server with an unknown flavor
@@ -96,7 +96,7 @@
                           self.create_test_server,
                           flavor=-1,)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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 +105,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.create_test_server, accessIPv4=IPv4)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -118,7 +118,7 @@
     @decorators.idempotent_id('7ea45b3e-e770-46fa-bfcc-9daaf6d987c0')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_nonexistent_server(self):
         # Resize a non-existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -129,7 +129,7 @@
     @decorators.idempotent_id('ced1a1d7-2ab6-45c9-b90f-b27d87b30efd')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_with_non_existent_flavor(self):
         # Resize a server with non-existent flavor
         nonexistent_flavor = data_utils.rand_uuid()
@@ -139,13 +139,13 @@
     @decorators.idempotent_id('45436a7d-a388-4a35-a9d8-3adc5d0d940b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_with_null_flavor(self):
         # Resize a server with null flavor
         self.assertRaises(lib_exc.BadRequest, self.client.resize_server,
                           self.server_id, flavor_ref="")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
     def test_reboot_non_existent_server(self):
         # Reboot a non existent server
@@ -156,7 +156,7 @@
     @decorators.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_pause_paused_server(self):
         # Pause a paused server.
         self.client.pause_server(self.server_id)
@@ -166,7 +166,7 @@
                           self.server_id)
         self.client.unpause_server(self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
     def test_rebuild_deleted_server(self):
         # Rebuild a deleted server
@@ -178,8 +178,8 @@
                           self.client.rebuild_server,
                           server['id'], self.image_ref)
 
-    @test.related_bug('1660878', status_code=409)
-    @test.attr(type=['negative'])
+    @decorators.related_bug('1660878', status_code=409)
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
     def test_reboot_deleted_server(self):
         # Reboot a deleted server
@@ -190,7 +190,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
                           server['id'], type='SOFT')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
     def test_rebuild_non_existent_server(self):
         # Rebuild a non existent server
@@ -200,7 +200,7 @@
                           nonexistent_server,
                           self.image_ref)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
     def test_create_numeric_server_name(self):
         server_name = 12345
@@ -208,7 +208,7 @@
                           self.create_test_server,
                           name=server_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c3e0fb12-07fc-4d76-a22e-37409887afe8')
     def test_create_server_name_length_exceeds_256(self):
         # Create a server with name length exceeding 255 characters
@@ -218,8 +218,9 @@
                           self.create_test_server,
                           name=server_name)
 
-    @test.attr(type=['negative'])
-    @test.related_bug('1651064', status_code=500)
+    @decorators.attr(type=['negative'])
+    @decorators.related_bug('1651064', status_code=500)
+    @test.services('volume')
     @decorators.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
     def test_create_server_invalid_bdm_in_2nd_dict(self):
         volume = self.create_volume()
@@ -238,7 +239,7 @@
                           image_id=self.image_ref,
                           block_device_mapping_v2=bdm)
 
-    @test.attr(type=['negative'])
+    @decorators.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
@@ -249,7 +250,7 @@
                           self.create_test_server,
                           networks=networks)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -259,7 +260,7 @@
                           self.create_test_server,
                           key_name=key_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -269,7 +270,7 @@
                           self.create_test_server,
                           metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
     def test_update_name_of_non_existent_server(self):
         # Update name of a non-existent server
@@ -281,7 +282,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.update_server,
                           nonexistent_server, name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -291,7 +292,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.update_server,
                           self.server_id, name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -302,7 +303,7 @@
                           self.server_id,
                           name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1041b4e6-514b-4855-96a5-e974b60870a3')
     def test_delete_non_existent_server(self):
         # Delete a non existent server
@@ -311,14 +312,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -326,7 +327,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_server,
                           sys.maxsize + 1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
     def test_create_with_nonexistent_security_group(self):
         # Create a server with a nonexistent security group
@@ -336,7 +337,7 @@
                           self.create_test_server,
                           security_groups=security_groups)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3436b02f-1b1e-4f03-881e-c6a602327439')
     def test_get_non_existent_server(self):
         # Get a non existent server details
@@ -344,7 +345,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a31460a9-49e1-42aa-82ee-06e0bb7c2d03')
     def test_stop_non_existent_server(self):
         # Stop a non existent server
@@ -355,7 +356,7 @@
     @decorators.idempotent_id('6a8dc0c6-6cd4-4c0a-9f32-413881828091')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_pause_non_existent_server(self):
         # pause a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -365,7 +366,7 @@
     @decorators.idempotent_id('705b8e3a-e8a7-477c-a19b-6868fc24ac75')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unpause_non_existent_server(self):
         # unpause a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -375,7 +376,7 @@
     @decorators.idempotent_id('c8e639a7-ece8-42dd-a2e0-49615917ba4f')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unpause_server_invalid_state(self):
         # unpause an active server.
         self.assertRaises(lib_exc.Conflict,
@@ -385,7 +386,7 @@
     @decorators.idempotent_id('d1f032d5-7b6e-48aa-b252-d5f16dd994ca')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_suspend_non_existent_server(self):
         # suspend a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -395,7 +396,7 @@
     @decorators.idempotent_id('7f323206-05a9-4bf8-996b-dd5b2036501b')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_suspend_server_invalid_state(self):
         # suspend a suspended server.
         self.client.suspend_server(self.server_id)
@@ -409,7 +410,7 @@
     @decorators.idempotent_id('221cd282-bddb-4837-a683-89c2487389b6')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resume_non_existent_server(self):
         # resume a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -419,14 +420,14 @@
     @decorators.idempotent_id('ccb6294d-c4c9-498f-8a43-554c098bfadb')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resume_server_invalid_state(self):
         # resume an active server.
         self.assertRaises(lib_exc.Conflict,
                           self.client.resume_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -435,7 +436,7 @@
                           self.client.get_console_output,
                           nonexistent_server, length=10)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
     def test_force_delete_nonexistent_server_id(self):
         # force-delete a non existent server
@@ -444,7 +445,7 @@
                           self.client.force_delete_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c6d38cc-fcfb-437a-85b9-7b788af8bf01')
     def test_restore_nonexistent_server_id(self):
         # restore-delete a non existent server
@@ -453,7 +454,7 @@
                           self.client.restore_soft_deleted_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -464,7 +465,7 @@
     @decorators.idempotent_id('abca56e2-a892-48ea-b5e5-e07e69774816')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_shelve_non_existent_server(self):
         # shelve a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -474,7 +475,7 @@
     @decorators.idempotent_id('443e4f9b-e6bf-4389-b601-3a710f15fddd')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_shelve_shelved_server(self):
         # shelve a shelved server.
         compute.shelve_server(self.client, self.server_id)
@@ -495,7 +496,7 @@
     @decorators.idempotent_id('23d23b37-afaf-40d7-aa5d-5726f82d8821')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unshelve_non_existent_server(self):
         # unshelve a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -505,14 +506,14 @@
     @decorators.idempotent_id('8f198ded-1cca-4228-9e65-c6b449c54880')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unshelve_server_invalid_state(self):
         # unshelve an active server.
         self.assertRaises(lib_exc.Conflict,
                           self.client.unshelve_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
     @test.services('volume', 'image')
     def test_create_server_from_non_bootable_volume(self):
@@ -566,7 +567,7 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -576,7 +577,7 @@
                           self.alt_client.update_server, self.server_id,
                           name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index b1374d2..173784a 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -33,7 +33,7 @@
         super(VirtualInterfacesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
     @test.services('network')
     def test_list_virtual_interfaces_invalid_server_id(self):
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index f87bf6d..3b41775 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -31,7 +31,7 @@
     @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:
+        if not CONF.compute_feature_enabled.api_extensions:
             raise self.skipException('There are not any extensions configured')
         extensions = self.extensions_client.list_extensions()['extensions']
         ext = CONF.compute_feature_enabled.api_extensions[0]
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index 01fd9ef..ab63154 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -14,12 +14,11 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.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
 
@@ -37,7 +36,7 @@
             server_id, host=dest_host, block_migration=bmflm,
             disk_over_commit=False)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 0ad2df8..9d83ee1 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -62,8 +62,8 @@
             self.assertIn(quota, quota_set.keys())
 
         # get the quota set using user id
-        quota_set = self.client.show_quota_set(self.tenant_id,
-                                               self.user_id)['quota_set']
+        quota_set = self.client.show_quota_set(
+            self.tenant_id, user_id=self.user_id)['quota_set']
         self.assertEqual(quota_set['id'], self.tenant_id)
         for quota in expected_quota_set:
             self.assertIn(quota, quota_set.keys())
diff --git a/tempest/api/compute/test_versions.py b/tempest/api/compute/test_versions.py
index dcab067..6141553 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -14,13 +14,12 @@
 
 from tempest.api.compute import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestVersions(base.BaseV2ComputeTest):
 
     @decorators.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_api_versions(self):
         """Test that a get of the unversioned url returns the choices doc.
 
@@ -39,7 +38,7 @@
                          "The first listed version should be v2.0")
 
     @decorators.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     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 73c7614..b0a6622 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 import testtools
 
 from tempest.api.compute import base
@@ -25,8 +24,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class AttachVolumeTestJSON(base.BaseV2ComputeTest):
     max_microversion = '2.19'
@@ -65,6 +62,20 @@
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
         server = self._create_server()
+
+        # NOTE(andreaf) Create one remote client used throughout the test.
+        if CONF.validation.run_validation:
+            linux_client = remote_client.RemoteClient(
+                self.get_server_ip(server),
+                self.image_ssh_user,
+                self.image_ssh_password,
+                self.validation_resources['keypair']['private_key'],
+                server=server,
+                servers_client=self.servers_client)
+            # NOTE(andreaf) We need to ensure the ssh key has been
+            # injected in the guest before we power cycle
+            linux_client.validate_authentication()
+
         volume = self.create_volume()
         attachment = self.attach_volume(server, volume,
                                         device=('/dev/%s' % self.device))
@@ -78,14 +89,6 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            linux_client = remote_client.RemoteClient(
-                self.get_server_ip(server),
-                self.image_ssh_user,
-                self.image_ssh_password,
-                self.validation_resources['keypair']['private_key'],
-                server=server,
-                servers_client=self.servers_client)
-
             disks = linux_client.get_disks()
             device_name_to_match = '\n' + self.device + ' '
             self.assertIn(device_name_to_match, disks)
@@ -103,14 +106,6 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            linux_client = remote_client.RemoteClient(
-                self.get_server_ip(server),
-                self.image_ssh_user,
-                self.image_ssh_password,
-                self.validation_resources['keypair']['private_key'],
-                server=server,
-                servers_client=self.servers_client)
-
             disks = linux_client.get_disks()
             self.assertNotIn(device_name_to_match, disks)
 
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index c017690..eabb907 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -16,7 +16,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -30,8 +29,8 @@
             skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
 
-    @test.attr(type=['negative'])
-    @test.related_bug('1630783', status_code=500)
+    @decorators.attr(type=['negative'])
+    @decorators.related_bug('1630783', status_code=500)
     @decorators.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
     def test_delete_attached_volume(self):
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index 4b06867..2f3a06e 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -16,9 +16,9 @@
 import testtools
 
 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 data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index 0eaa359..43c837a 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -16,9 +16,9 @@
 from testtools import matchers
 
 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 data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index 2ad8631..80db1be 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -14,11 +14,10 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 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
 
@@ -37,7 +36,7 @@
         super(VolumesNegativeTest, cls).setup_clients()
         cls.client = cls.volumes_extensions_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -46,7 +45,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -55,7 +54,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -65,7 +64,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -75,7 +74,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
@@ -84,13 +83,13 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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'])
+    @decorators.attr(type=['negative'])
     @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
@@ -99,7 +98,7 @@
                           self.client.delete_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @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
diff --git a/tempest/api/identity/admin/v2/test_endpoints.py b/tempest/api/identity/admin/v2/test_endpoints.py
index 0ea2eb3..db32f5a 100644
--- a/tempest/api/identity/admin/v2/test_endpoints.py
+++ b/tempest/api/identity/admin/v2/test_endpoints.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/identity/admin/v2/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
index 799b653..479663c 100644
--- a/tempest/api/identity/admin/v2/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index b017b44..86d06e2 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -28,14 +27,14 @@
         role = self.setup_test_role()
         return (user, tenant, role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d5d5f1df-f8ca-4de0-b2ef-259c1cc67025')
     def test_list_roles_by_unauthorized_user(self):
         # Non-administrator user should not be able to list roles
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_roles_client.list_roles)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('11a3c7da-df6c-40c2-abc2-badd682edf9f')
     def test_list_roles_request_without_token(self):
         # Request to list roles without a valid token should fail
@@ -44,14 +43,14 @@
         self.assertRaises(lib_exc.Unauthorized, self.roles_client.list_roles)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c0b89e56-accc-4c73-85f8-9c0f866104c1')
     def test_role_create_blank_name(self):
         # Should not be able to create a role with a blank name
         self.assertRaises(lib_exc.BadRequest, self.roles_client.create_role,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('585c8998-a8a4-4641-a5dd-abef7a8ced00')
     def test_create_role_by_unauthorized_user(self):
         # Non-administrator user should not be able to create role
@@ -60,7 +59,7 @@
                           self.non_admin_roles_client.create_role,
                           name=role_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a7edd17a-e34a-4aab-8bb7-fa6f498645b8')
     def test_create_role_request_without_token(self):
         # Request to create role without a valid token should fail
@@ -71,7 +70,7 @@
                           self.roles_client.create_role, name=role_name)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c0cde2c8-81c1-4bb0-8fe2-cf615a3547a8')
     def test_role_create_duplicate(self):
         # Role names should be unique
@@ -82,7 +81,7 @@
         self.assertRaises(lib_exc.Conflict, self.roles_client.create_role,
                           name=role_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('15347635-b5b1-4a87-a280-deb2bd6d865e')
     def test_delete_role_by_unauthorized_user(self):
         # Non-administrator user should not be able to delete role
@@ -93,7 +92,7 @@
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_roles_client.delete_role, role_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('44b60b20-70de-4dac-beaf-a3fc2650a16b')
     def test_delete_role_request_without_token(self):
         # Request to delete role without a valid token should fail
@@ -108,7 +107,7 @@
                           role_id)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('38373691-8551-453a-b074-4260ad8298ef')
     def test_delete_role_non_existent(self):
         # Attempt to delete a non existent role should fail
@@ -116,7 +115,7 @@
         self.assertRaises(lib_exc.NotFound, self.roles_client.delete_role,
                           non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('391df5cf-3ec3-46c9-bbe5-5cb58dd4dc41')
     def test_assign_user_role_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to
@@ -127,7 +126,7 @@
             self.non_admin_roles_client.create_user_role_on_project,
             tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f0d2683c-5603-4aee-95d7-21420e87cfd8')
     def test_assign_user_role_request_without_token(self):
         # Request to assign a role to a user without a valid token
@@ -140,7 +139,7 @@
             user['id'], role['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('99b297f6-2b5d-47c7-97a9-8b6bb4f91042')
     def test_assign_user_role_for_non_existent_role(self):
         # Attempt to assign a non existent role to user should fail
@@ -150,7 +149,7 @@
                           self.roles_client.create_user_role_on_project,
                           tenant['id'], user['id'], non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b2285aaa-9e76-4704-93a9-7a8acd0a6c8f')
     def test_assign_user_role_for_non_existent_tenant(self):
         # Attempt to assign a role on a non existent tenant should fail
@@ -160,7 +159,7 @@
                           self.roles_client.create_user_role_on_project,
                           non_existent_tenant, user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5c3132cd-c4c8-4402-b5ea-71eb44e97793')
     def test_assign_duplicate_user_role(self):
         # Duplicate user role should not get assigned
@@ -172,7 +171,7 @@
                           self.roles_client.create_user_role_on_project,
                           tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d0537987-0977-448f-a435-904c15de7298')
     def test_remove_user_role_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to
@@ -186,7 +185,7 @@
             self.non_admin_roles_client.delete_role_from_user_on_project,
             tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cac81cf4-c1d2-47dc-90d3-f2b7eb572286')
     def test_remove_user_role_request_without_token(self):
         # Request to remove a user's role without a valid token
@@ -201,7 +200,7 @@
                           tenant['id'], user['id'], role['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ab32d759-cd16-41f1-a86e-44405fa9f6d2')
     def test_remove_user_role_non_existent_role(self):
         # Attempt to delete a non existent role from a user should fail
@@ -214,7 +213,7 @@
                           self.roles_client.delete_role_from_user_on_project,
                           tenant['id'], user['id'], non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('67a679ec-03dd-4551-bbfc-d1c93284f023')
     def test_remove_user_role_non_existent_tenant(self):
         # Attempt to remove a role from a non existent tenant should fail
@@ -227,7 +226,7 @@
                           self.roles_client.delete_role_from_user_on_project,
                           non_existent_tenant, user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7391ab4c-06f3-477a-a64a-c8e55ce89837')
     def test_list_user_roles_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to list
@@ -241,7 +240,7 @@
             self.non_admin_roles_client.list_user_roles_on_project,
             tenant['id'], user['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('682adfb2-fd5f-4b0a-a9ca-322e9bebb907')
     def test_list_user_roles_request_without_token(self):
         # Request to list user's roles without a valid token should fail
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 3b0ddbb..634cf21 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class ServicesTestJSON(base.BaseIdentityV2AdminTest):
@@ -78,7 +77,7 @@
         self.assertIn('type', service)
         self.assertEqual(s_type, service['type'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('34ea6489-012d-4a86-9038-1287cadd5eca')
     def test_list_services(self):
         # Create, List, Verify and Delete Services
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index e8c32b9..49bb949 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -14,22 +14,21 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class TenantsNegativeTestJSON(base.BaseIdentityV2AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ca9bb202-63dd-4240-8a07-8ef9c19c04bb')
     def test_list_tenants_by_unauthorized_user(self):
         # Non-administrator user should not be able to list tenants
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.list_tenants)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('df33926c-1c96-4d8d-a762-79cc6b0c3cf4')
     def test_list_tenant_request_without_token(self):
         # Request to list tenants without a valid token should fail
@@ -39,24 +38,20 @@
                           self.tenants_client.list_tenants)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('162ba316-f18b-4987-8c0c-fd9140cd63ed')
     def test_tenant_delete_by_unauthorized_user(self):
         # Non-administrator user should not be able to delete a tenant
-        tenant_name = data_utils.rand_name(name='tenant')
-        tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.delete_tenant,
                           tenant['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e450db62-2e9d-418f-893a-54772d6386b1')
     def test_tenant_delete_request_without_token(self):
         # Request to delete a tenant without a valid token should fail
-        tenant_name = data_utils.rand_name(name='tenant')
-        tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant()
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
         self.assertRaises(lib_exc.Unauthorized,
@@ -64,26 +59,23 @@
                           tenant['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c9a2aed-6e3c-467a-8f5c-89da9d1b516b')
     def test_delete_non_existent_tenant(self):
         # Attempt to delete a non existent tenant should fail
         self.assertRaises(lib_exc.NotFound, self.tenants_client.delete_tenant,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af16f44b-a849-46cb-9f13-a751c388f739')
     def test_tenant_create_duplicate(self):
         # Tenant names should be unique
         tenant_name = data_utils.rand_name(name='tenant')
-        body = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        tenant1_id = body.get('id')
-
-        self.addCleanup(self.tenants_client.delete_tenant, tenant1_id)
+        self.setup_test_tenant(name=tenant_name)
         self.assertRaises(lib_exc.Conflict, self.tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d26b278a-6389-4702-8d6e-5980d80137e0')
     def test_create_tenant_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to create a tenant
@@ -92,7 +84,7 @@
                           self.non_admin_tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a3ee9d7e-6920-4dd5-9321-d4b2b7f0a638')
     def test_create_tenant_request_without_token(self):
         # Create tenant request without a token should not be authorized
@@ -104,7 +96,7 @@
                           name=tenant_name)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5a2e4ca9-b0c0-486c-9c48-64a94fba2395')
     def test_create_tenant_with_empty_name(self):
         # Tenant name should not be empty
@@ -112,7 +104,7 @@
                           self.tenants_client.create_tenant,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2ff18d1e-dfe3-4359-9dc3-abf582c196b9')
     def test_create_tenants_name_length_over_64(self):
         # Tenant name length should not be greater than 64 characters
@@ -121,31 +113,27 @@
                           self.tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bd20dc2a-9557-4db7-b755-f48d952ad706')
     def test_update_non_existent_tenant(self):
         # Attempt to update a non existent tenant should fail
         self.assertRaises(lib_exc.NotFound, self.tenants_client.update_tenant,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41704dc5-c5f7-4f79-abfa-76e6fedc570b')
     def test_tenant_update_by_unauthorized_user(self):
         # Non-administrator user should not be able to update a tenant
-        tenant_name = data_utils.rand_name(name='tenant')
-        tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant()
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.update_tenant,
                           tenant['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7a421573-72c7-4c22-a98e-ce539219c657')
     def test_tenant_update_request_without_token(self):
         # Request to update a tenant without a valid token should fail
-        tenant_name = data_utils.rand_name(name='tenant')
-        tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant()
         token = self.client.auth_provider.get_token()
         self.client.delete_token(token)
         self.assertRaises(lib_exc.Unauthorized,
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index eb51b5a..ad9b983 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -14,8 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
@@ -26,12 +25,7 @@
         # Create several tenants and delete them
         tenants = []
         for _ in range(3):
-            tenant_name = data_utils.rand_name(name='tenant-new')
-            tenant = self.tenants_client.create_tenant(
-                name=tenant_name)['tenant']
-            # Add the tenant to the cleanup list
-            self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                            self.tenants_client.delete_tenant, tenant['id'])
+            tenant = self.setup_test_tenant()
             tenants.append(tenant)
         tenant_ids = [tn['id'] for tn in tenants]
         body = self.tenants_client.list_tenants()['tenants']
@@ -48,14 +42,8 @@
     @decorators.idempotent_id('d25e9f24-1310-4d29-b61b-d91299c21d6d')
     def test_tenant_create_with_description(self):
         # Create tenant with a description
-        tenant_name = data_utils.rand_name(name='tenant')
         tenant_desc = data_utils.rand_name(name='desc')
-        body = self.tenants_client.create_tenant(name=tenant_name,
-                                                 description=tenant_desc)
-        tenant = body['tenant']
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant(description=tenant_desc)
         tenant_id = tenant['id']
         desc1 = tenant['description']
         self.assertEqual(desc1, tenant_desc, 'Description should have '
@@ -69,13 +57,7 @@
     @decorators.idempotent_id('670bdddc-1cd7-41c7-b8e2-751cfb67df50')
     def test_tenant_create_enabled(self):
         # Create a tenant that is enabled
-        tenant_name = data_utils.rand_name(name='tenant')
-        body = self.tenants_client.create_tenant(name=tenant_name,
-                                                 enabled=True)
-        tenant = body['tenant']
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant(enabled=True)
         tenant_id = tenant['id']
         en1 = tenant['enabled']
         self.assertTrue(en1, 'Enable should be True in response')
@@ -87,13 +69,7 @@
     @decorators.idempotent_id('3be22093-b30f-499d-b772-38340e5e16fb')
     def test_tenant_create_not_enabled(self):
         # Create a tenant that is not enabled
-        tenant_name = data_utils.rand_name(name='tenant')
-        body = self.tenants_client.create_tenant(name=tenant_name,
-                                                 enabled=False)
-        tenant = body['tenant']
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant(enabled=False)
         tenant_id = tenant['id']
         en1 = tenant['enabled']
         self.assertEqual('false', str(en1).lower(),
@@ -108,14 +84,9 @@
     def test_tenant_update_name(self):
         # Update name attribute of a tenant
         t_name1 = data_utils.rand_name(name='tenant')
-        body = self.tenants_client.create_tenant(name=t_name1)['tenant']
-        tenant = body
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
-
-        t_id = body['id']
-        resp1_name = body['name']
+        tenant = self.setup_test_tenant(name=t_name1)
+        t_id = tenant['id']
+        resp1_name = tenant['name']
 
         t_name2 = data_utils.rand_name(name='tenant2')
         body = self.tenants_client.update_tenant(t_id, name=t_name2)['tenant']
@@ -134,15 +105,8 @@
     @decorators.idempotent_id('859fcfe1-3a03-41ef-86f9-b19a47d1cd87')
     def test_tenant_update_desc(self):
         # Update description attribute of a tenant
-        t_name = data_utils.rand_name(name='tenant')
         t_desc = data_utils.rand_name(name='desc')
-        body = self.tenants_client.create_tenant(name=t_name,
-                                                 description=t_desc)
-        tenant = body['tenant']
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
-
+        tenant = self.setup_test_tenant(description=t_desc)
         t_id = tenant['id']
         resp1_desc = tenant['description']
 
@@ -164,14 +128,8 @@
     @decorators.idempotent_id('8fc8981f-f12d-4c66-9972-2bdcf2bc2e1a')
     def test_tenant_update_enable(self):
         # Update the enabled attribute of a tenant
-        t_name = data_utils.rand_name(name='tenant')
         t_en = False
-        body = self.tenants_client.create_tenant(name=t_name, enabled=t_en)
-        tenant = body['tenant']
-        # Add the tenant to the cleanup list
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.tenants_client.delete_tenant, tenant['id'])
-
+        tenant = self.setup_test_tenant(enabled=t_en)
         t_id = tenant['id']
         resp1_en = tenant['enabled']
 
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index 7b5e01e..b4c9389 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
@@ -26,17 +26,12 @@
         user_name = data_utils.rand_name(name='user')
         user_password = data_utils.rand_password()
         # first:create a tenant
-        tenant_name = data_utils.rand_name(name='tenant')
-        tenant = self.tenants_client.create_tenant(name=tenant_name)['tenant']
-        # Delete the tenant at the end of the test
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        tenant = self.setup_test_tenant()
         # second:create a user
-        user = self.users_client.create_user(name=user_name,
-                                             password=user_password,
-                                             tenantId=tenant['id'],
-                                             email='')['user']
-        # Delete the user at the end of the test
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(name=user_name,
+                                     password=user_password,
+                                     tenantId=tenant['id'],
+                                     email='')
         # then get a token for the user
         body = self.token_client.auth(user_name,
                                       user_password,
@@ -65,32 +60,20 @@
         user_name = data_utils.rand_name(name='user')
         user_password = data_utils.rand_password()
         tenant_id = None  # No default tenant so will get unscoped token.
-        email = ''
-        user = self.users_client.create_user(name=user_name,
-                                             password=user_password,
-                                             tenantId=tenant_id,
-                                             email=email)['user']
-        # Delete the user at the end of the test
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(name=user_name,
+                                     password=user_password,
+                                     tenantId=tenant_id,
+                                     email='')
 
         # Create a couple tenants.
         tenant1_name = data_utils.rand_name(name='tenant')
-        tenant1 = self.tenants_client.create_tenant(
-            name=tenant1_name)['tenant']
-        # Delete the tenant at the end of the test
-        self.addCleanup(self.tenants_client.delete_tenant, tenant1['id'])
+        tenant1 = self.setup_test_tenant(name=tenant1_name)
 
         tenant2_name = data_utils.rand_name(name='tenant')
-        tenant2 = self.tenants_client.create_tenant(
-            name=tenant2_name)['tenant']
-        # Delete the tenant at the end of the test
-        self.addCleanup(self.tenants_client.delete_tenant, tenant2['id'])
+        tenant2 = self.setup_test_tenant(name=tenant2_name)
 
         # Create a role
-        role_name = data_utils.rand_name(name='role')
-        role = self.roles_client.create_role(name=role_name)['role']
-        # Delete the role at the end of the test
-        self.addCleanup(self.roles_client.delete_role, role['id'])
+        role = self.setup_test_role()
 
         # Grant the user the role on the tenants.
         self.roles_client.create_user_role_on_project(tenant1['id'],
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 5889813..2711a2d 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -18,10 +18,8 @@
 from testtools import matchers
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
-from tempest.lib.common.utils import test_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class UsersTestJSON(base.BaseIdentityV2AdminTest):
@@ -30,20 +28,14 @@
     def resource_setup(cls):
         super(UsersTestJSON, cls).resource_setup()
         cls.alt_user = data_utils.rand_name('test_user')
-        cls.alt_password = data_utils.rand_password()
         cls.alt_email = cls.alt_user + '@testmail.tm'
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2d55a71e-da1d-4b43-9c03-d269fd93d905')
     def test_create_user(self):
         # Create a user
         tenant = self.setup_test_tenant()
-        user = self.users_client.create_user(name=self.alt_user,
-                                             password=self.alt_password,
-                                             tenantId=tenant['id'],
-                                             email=self.alt_email)['user']
-        # Delete the User at the end of the test
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(name=self.alt_user, tenantId=tenant['id'])
         self.assertEqual(self.alt_user, user['name'])
 
     @decorators.idempotent_id('89d9fdb8-15c2-4304-a429-48715d0af33d')
@@ -51,13 +43,10 @@
         # Create a user with enabled : False
         tenant = self.setup_test_tenant()
         name = data_utils.rand_name('test_user')
-        user = self.users_client.create_user(name=name,
-                                             password=self.alt_password,
-                                             tenantId=tenant['id'],
-                                             email=self.alt_email,
-                                             enabled=False)['user']
-        # Delete the User at the end of the test
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(name=name,
+                                     tenantId=tenant['id'],
+                                     email=self.alt_email,
+                                     enabled=False)
         self.assertEqual(name, user['name'])
         self.assertEqual(False, user['enabled'])
         self.assertEqual(self.alt_email, user['email'])
@@ -65,14 +54,9 @@
     @decorators.idempotent_id('39d05857-e8a5-4ed4-ba83-0b52d3ab97ee')
     def test_update_user(self):
         # Test case to check if updating of user attributes is successful.
-        test_user = data_utils.rand_name('test_user')
         tenant = self.setup_test_tenant()
-        user = self.users_client.create_user(name=test_user,
-                                             password=self.alt_password,
-                                             tenantId=tenant['id'],
-                                             email=self.alt_email)['user']
-        # Delete the User at the end of this method
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(tenantId=tenant['id'])
+
         # Updating user details with new values
         u_name2 = data_utils.rand_name('user2')
         u_email2 = u_name2 + '@testmail.tm'
@@ -92,15 +76,8 @@
     @decorators.idempotent_id('29ed26f4-a74e-4425-9a85-fdb49fa269d2')
     def test_delete_user(self):
         # Delete a user
-        test_user = data_utils.rand_name('test_user')
         tenant = self.setup_test_tenant()
-        user = self.users_client.create_user(name=test_user,
-                                             password=self.alt_password,
-                                             tenantId=tenant['id'],
-                                             email=self.alt_email)['user']
-        # Delete the User at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.users_client.delete_user, user['id'])
+        user = self.create_test_user(tenantId=tenant['id'])
         self.users_client.delete_user(user['id'])
 
     @decorators.idempotent_id('aca696c3-d645-4f45-b728-63646045beb1')
@@ -152,24 +129,10 @@
         tenant = self.setup_test_tenant()
         user_ids = list()
         fetched_user_ids = list()
-        password1 = data_utils.rand_password()
-        alt_tenant_user1 = data_utils.rand_name('tenant_user1')
-        user1 = self.users_client.create_user(name=alt_tenant_user1,
-                                              password=password1,
-                                              tenantId=tenant['id'],
-                                              email='user1@123')['user']
+        user1 = self.create_test_user(tenantId=tenant['id'])
         user_ids.append(user1['id'])
-        # Delete the User at the end of the test
-        self.addCleanup(self.users_client.delete_user, user1['id'])
-        password2 = data_utils.rand_password()
-        alt_tenant_user2 = data_utils.rand_name('tenant_user2')
-        user2 = self.users_client.create_user(name=alt_tenant_user2,
-                                              password=password2,
-                                              tenantId=tenant['id'],
-                                              email='user2@123')['user']
+        user2 = self.create_test_user(tenantId=tenant['id'])
         user_ids.append(user2['id'])
-        # Delete the User at the end of the test
-        self.addCleanup(self.users_client.delete_user, user2['id'])
         # List of users for the respective tenant ID
         body = (self.tenants_client.list_tenant_users(tenant['id'])
                 ['users'])
@@ -195,16 +158,8 @@
         role = self.roles_client.create_user_role_on_project(
             tenant['id'], user['id'], role['id'])['role']
 
-        alt_user2 = data_utils.rand_name('second_user')
-        alt_password2 = data_utils.rand_password()
-        second_user = self.users_client.create_user(
-            name=alt_user2,
-            password=alt_password2,
-            tenantId=tenant['id'],
-            email='user2@123')['user']
+        second_user = self.create_test_user(tenantId=tenant['id'])
         user_ids.append(second_user['id'])
-        # Delete the User at the end of the test
-        self.addCleanup(self.users_client.delete_user, second_user['id'])
         role = self.roles_client.create_user_role_on_project(
             tenant['id'], second_user['id'], role['id'])['role']
         # List of users with roles for the respective tenant ID
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index 49fda4e..4f47e41 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -29,7 +28,7 @@
         cls.alt_password = data_utils.rand_password()
         cls.alt_email = cls.alt_user + '@testmail.tm'
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('60a1f5fa-5744-4cdf-82bf-60b7de2d29a4')
     def test_create_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to create a user
@@ -40,7 +39,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d80d0c2f-4514-4d1e-806d-0930dfc5a187')
     def test_create_user_with_empty_name(self):
         # User with an empty name should not be created
@@ -50,7 +49,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7704b4f3-3b75-4b82-87cc-931d41c8f780')
     def test_create_user_with_name_length_over_255(self):
         # Length of user name filed should be restricted to 255 characters
@@ -60,7 +59,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('57ae8558-120c-4723-9308-3751474e7ecf')
     def test_create_user_with_duplicate_name(self):
         # Duplicate user should not be created
@@ -73,7 +72,7 @@
                           tenantId=tenant['id'],
                           email=user['email'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
     def test_create_user_for_non_existent_tenant(self):
         # Attempt to create a user in a non-existent tenant should fail
@@ -83,7 +82,7 @@
                           tenantId='49ffgg99999',
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('55bbb103-d1ae-437b-989b-bcdf8175c1f4')
     def test_create_user_request_without_a_token(self):
         # Request to create a user without a valid token should fail
@@ -101,7 +100,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('23a2f3da-4a1a-41da-abdd-632328a861ad')
     def test_create_user_with_enabled_non_bool(self):
         # Attempt to create a user with valid enabled para should fail
@@ -112,7 +111,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email, enabled=3)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3d07e294-27a0-4144-b780-a2a1bf6fee19')
     def test_update_user_for_non_existent_user(self):
         # Attempt to update a user non-existent user should fail
@@ -121,7 +120,7 @@
         self.assertRaises(lib_exc.NotFound, self.users_client.update_user,
                           non_existent_id, name=user_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3cc2a64b-83aa-4b02-88f0-d6ab737c4466')
     def test_update_user_request_without_a_token(self):
         # Request to update a user without a valid token should fail
@@ -137,7 +136,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.users_client.update_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('424868d5-18a7-43e1-8903-a64f95ee3aac')
     def test_update_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to update user
@@ -145,7 +144,7 @@
                           self.non_admin_users_client.update_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d45195d5-33ed-41b9-a452-7d0d6a00f6e9')
     def test_delete_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to delete a user
@@ -154,14 +153,14 @@
                           self.non_admin_users_client.delete_user,
                           user['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7cc82f7e-9998-4f89-abae-23df36495867')
     def test_delete_non_existent_user(self):
         # Attempt to delete a non-existent user should fail
         self.assertRaises(lib_exc.NotFound, self.users_client.delete_user,
                           'junk12345123')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('57fe1df8-0aa7-46c0-ae9f-c2e785c7504a')
     def test_delete_user_request_without_a_token(self):
         # Request to delete a user without a valid token should fail
@@ -177,7 +176,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.users_client.delete_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('593a4981-f6d4-460a-99a1-57a78bf20829')
     def test_authentication_for_disabled_user(self):
         # Disabled user's token should not get authenticated
@@ -190,7 +189,7 @@
                           password,
                           tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('440a7a8d-9328-4b7b-83e0-d717010495e4')
     def test_authentication_when_tenant_is_disabled(self):
         # User's token for a disabled tenant should not be authenticated
@@ -203,7 +202,7 @@
                           password,
                           tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('921f1ad6-7907-40b8-853f-637e7ee52178')
     def test_authentication_with_invalid_tenant(self):
         # User's token for an invalid tenant should not be authenticated
@@ -214,7 +213,7 @@
                           password,
                           'junktenant1234')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bde9aecd-3b1c-4079-858f-beb5deaa5b5e')
     def test_authentication_with_invalid_username(self):
         # Non-existent user's token should not get authenticated
@@ -224,7 +223,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
                           'junkuser123', password, tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d5308b33-3574-43c3-8d87-1c090c5e1eca')
     def test_authentication_with_invalid_password(self):
         # User's token with invalid password should not be authenticated
@@ -233,14 +232,14 @@
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
                           user['name'], 'junkpass1234', tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('284192ce-fb7c-4909-a63b-9a502e0ddd11')
     def test_get_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to get user list
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.list_users)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a73591ec-1903-4ffe-be42-282b39fefc9d')
     def test_get_users_request_without_token(self):
         # Request to get list of users without a valid token should fail
@@ -252,7 +251,7 @@
 
         self.assertRaises(lib_exc.Unauthorized, self.users_client.list_users)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5d39046-fc5f-425c-b29e-bac2632da28e')
     def test_list_users_with_invalid_tenant(self):
         # Should not be able to return a list of all
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index e5a218d..75e877a 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -15,9 +15,8 @@
 from oslo_serialization import jsonutils as json
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class CredentialsTestJSON(base.BaseIdentityV3AdminTest):
@@ -52,7 +51,7 @@
     def _delete_credential(self, cred_id):
         self.creds_client.delete_credential(cred_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7cd59bf9-bda4-4c72-9467-d21cab278355')
     def test_credentials_create_get_update_delete(self):
         blob = '{"access": "%s", "secret": "%s"}' % (
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index 110695d..ac2faa9 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -11,9 +11,9 @@
 #    under the License.
 from tempest.api.identity import base
 from tempest import clients
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest.lib import auth
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
@@ -42,13 +42,10 @@
         self.addCleanup(self._delete_domain, dom_id)
 
         # create a project in the domain
-        proj_name = data_utils.rand_name('proj')
-        proj_body = self.projects_client.create_project(
-            proj_name, domain_id=dom_id)['project']
+        proj_body = self.setup_test_project(domain_id=dom_id)
         proj_id = proj_body['id']
-        self.addCleanup(self.projects_client.delete_project, proj_id)
         self.assertEqual(proj_body['domain_id'], dom_id,
-                         "project " + proj_name +
+                         "project " + proj_body['name'] +
                          "doesn't have domain id " + dom_id)
 
         # create a user in the domain, with the previous project as his
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 4cf9f66..86a5764 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -14,11 +14,10 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -87,7 +86,7 @@
         for domain in fetched_domains:
             self.assertEqual(True, domain['enabled'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f2f5b44a-82e8-4dad-8084-0661ea3b18cf')
     def test_create_update_delete_domain(self):
         # Create domain
@@ -168,7 +167,7 @@
         cls.domain_id = CONF.identity.default_domain_id
         super(DefaultDomainTestJSON, cls).resource_setup()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('17a5de24-e6a0-4e4a-a9ee-d85b6e5612b5')
     def test_default_domain_exists(self):
         domain = self.domains_client.show_domain(self.domain_id)['domain']
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 4555a6a..61b4fa2 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -14,16 +14,15 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
-    @test.attr(type=['negative', 'gate'])
+    @decorators.attr(type=['negative', 'gate'])
     @decorators.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
     def test_delete_active_domain(self):
         d_name = data_utils.rand_name('domain')
@@ -39,14 +38,14 @@
         self.assertRaises(lib_exc.Forbidden, self.domains_client.delete_domain,
                           domain_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9018461d-7d24-408d-b3fe-ae37e8cd5c9e')
     def test_create_domain_with_empty_name(self):
         # Domain name should not be empty
         self.assertRaises(lib_exc.BadRequest,
                           self.domains_client.create_domain, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('37b1bbf2-d664-4785-9a11-333438586eae')
     def test_create_domain_with_name_length_over_64(self):
         # Domain name length should not ne greater than 64 characters
@@ -55,14 +54,14 @@
                           self.domains_client.create_domain,
                           name=d_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('43781c07-764f-4cf2-a405-953c1916f605')
     def test_delete_non_existent_domain(self):
         # Attempt to delete a non existent domain should fail
         self.assertRaises(lib_exc.NotFound, self.domains_client.delete_domain,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e6f9e4a2-4f36-4be8-bdbc-4e199ae29427')
     def test_domain_create_duplicate(self):
         domain_name = data_utils.rand_name('domain-dup')
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 9a0b3e4..09f92e2 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -14,9 +14,8 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class EndPointsTestJSON(base.BaseIdentityV3AdminTest):
@@ -109,7 +108,7 @@
         fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
         self.assertNotIn(endpoint['id'], fetched_endpoints_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('37e8f15e-ee7c-4657-a1e7-f6b61e375eff')
     def test_update_endpoint(self):
         # Creating an endpoint so as to check update endpoint
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 8e00193..70dd7b5 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -15,10 +15,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class EndpointsNegativeTestJSON(base.BaseIdentityV3AdminTest):
@@ -48,7 +47,7 @@
             cls.services_client.delete_service(s)
         super(EndpointsNegativeTestJSON, cls).resource_cleanup()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ac6c137e-4d3d-448f-8c83-4f13d0942651')
     def test_create_with_enabled_False(self):
         # Enabled should be a boolean, not a string like 'False'
@@ -59,7 +58,7 @@
                           service_id=self.service_id, interface=interface,
                           url=url, region=region, enabled='False')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c43181e-0627-484a-8c79-923e8a59598b')
     def test_create_with_enabled_True(self):
         # Enabled should be a boolean, not a string like 'True'
@@ -86,13 +85,13 @@
         self.assertRaises(lib_exc.BadRequest, self.client.update_endpoint,
                           endpoint_for_update['id'], enabled=enabled)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('65e41f32-5eb7-498f-a92a-a6ccacf7439a')
     def test_update_with_enabled_False(self):
         # Enabled should be a boolean, not a string like 'False'
         self._assert_update_raises_bad_request('False')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('faba3587-f066-4757-a48e-b4a3f01803bb')
     def test_update_with_enabled_True(self):
         # Enabled should be a boolean, not a string like 'True'
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 5ce0709..2694402 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -14,9 +14,8 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class GroupsV3TestJSON(base.BaseIdentityV3AdminTest):
@@ -72,7 +71,7 @@
         # Verify that 'description' is not being updated or deleted.
         self.assertEqual(old_description, updated_group['description'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1598521a-2f36-4606-8df9-30772bd51339')
     def test_group_users_add_list_delete(self):
         name = data_utils.rand_name('Group')
@@ -82,12 +81,8 @@
         # add user into group
         users = []
         for _ in range(3):
-            name = data_utils.rand_name('User')
-            password = data_utils.rand_password()
-            user = self.users_client.create_user(name=name,
-                                                 password=password)['user']
+            user = self.create_test_user()
             users.append(user)
-            self.addCleanup(self.users_client.delete_user, user['id'])
             self.groups_client.add_group_user(group['id'], user['id'])
 
         # list users in group
@@ -105,10 +100,7 @@
     @decorators.idempotent_id('64573281-d26a-4a52-b899-503cb0f4e4ec')
     def test_list_user_groups(self):
         # create a user
-        user = self.users_client.create_user(
-            name=data_utils.rand_name('User'),
-            password=data_utils.rand_password())['user']
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user()
         # create two groups, and add user into them
         groups = []
         for _ in range(2):
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 8523396..f630f74 100644
--- a/tempest/api/identity/admin/v3/test_inherits.py
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -65,9 +65,7 @@
     @decorators.idempotent_id('4e6f0366-97c8-423c-b2be-41eae6ac91c8')
     def test_inherit_assign_list_check_revoke_roles_on_domains_user(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
         # Assign role on domains user
         self.inherited_roles_client.create_inherited_role_on_domains_user(
             self.domain['id'], self.user['id'], src_role['id'])
@@ -91,9 +89,7 @@
     @decorators.idempotent_id('c7a8dda2-be50-4fb4-9a9c-e830771078b1')
     def test_inherit_assign_list_check_revoke_roles_on_domains_group(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
         # Assign role on domains group
         self.inherited_roles_client.create_inherited_role_on_domains_group(
             self.domain['id'], self.group['id'], src_role['id'])
@@ -117,9 +113,7 @@
     @decorators.idempotent_id('18b70e45-7687-4b72-8277-b8f1a47d7591')
     def test_inherit_assign_check_revoke_roles_on_projects_user(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
         # Assign role on projects user
         self.inherited_roles_client.create_inherited_role_on_projects_user(
             self.project['id'], self.user['id'], src_role['id'])
@@ -134,9 +128,7 @@
     @decorators.idempotent_id('26021436-d5a4-4256-943c-ded01e0d4b45')
     def test_inherit_assign_check_revoke_roles_on_projects_group(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
         # Assign role on projects group
         self.inherited_roles_client.create_inherited_role_on_projects_group(
             self.project['id'], self.group['id'], src_role['id'])
@@ -152,17 +144,11 @@
     @decorators.idempotent_id('3acf666e-5354-42ac-8e17-8b68893bcd36')
     def test_inherit_assign_list_revoke_user_roles_on_domain(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
 
         # Create a project hierarchy
-        leaf_project_name = data_utils.rand_name('project')
-        leaf_project = self.projects_client.create_project(
-            leaf_project_name, domain_id=self.domain['id'],
-            parent_id=self.project['id'])['project']
-        self.addCleanup(
-            self.projects_client.delete_project, leaf_project['id'])
+        leaf_project = self.setup_test_project(domain_id=self.domain['id'],
+                                               parent_id=self.project['id'])
 
         # Assign role on domain
         self.inherited_roles_client.create_inherited_role_on_domains_user(
@@ -202,17 +188,11 @@
     @decorators.idempotent_id('9f02ccd9-9b57-46b4-8f77-dd5a736f3a06')
     def test_inherit_assign_list_revoke_user_roles_on_project_tree(self):
         # Create role
-        src_role = self.roles_client.create_role(
-            name=data_utils.rand_name('Role'))['role']
-        self.addCleanup(self.roles_client.delete_role, src_role['id'])
+        src_role = self.setup_test_role()
 
         # Create a project hierarchy
-        leaf_project_name = data_utils.rand_name('project')
-        leaf_project = self.projects_client.create_project(
-            leaf_project_name, domain_id=self.domain['id'],
-            parent_id=self.project['id'])['project']
-        self.addCleanup(
-            self.projects_client.delete_project, leaf_project['id'])
+        leaf_project = self.setup_test_project(domain_id=self.domain['id'],
+                                               parent_id=self.project['id'])
 
         # Assign role on parent project
         self.inherited_roles_client.create_inherited_role_on_projects_user(
diff --git a/tempest/api/identity/admin/v3/test_list_projects.py b/tempest/api/identity/admin/v3/test_list_projects.py
index 2d046bb..7e70c14 100644
--- a/tempest/api/identity/admin/v3/test_list_projects.py
+++ b/tempest/api/identity/admin/v3/test_list_projects.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index 0a0d65a..bcbf6b6 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/identity/admin/v3/test_oauth_consumers.py b/tempest/api/identity/admin/v3/test_oauth_consumers.py
new file mode 100644
index 0000000..f06fb8f
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_oauth_consumers.py
@@ -0,0 +1,91 @@
+# Copyright 2017 AT&T 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.identity import base
+from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as exceptions
+
+
+class OAUTHConsumersV3Test(base.BaseIdentityV3AdminTest):
+
+    def _create_consumer(self):
+        """Creates a consumer with a random description."""
+        description = data_utils.rand_name('test_create_consumer')
+        consumer = self.oauth_consumers_client.create_consumer(
+            description)['consumer']
+        # cleans up created consumers after tests
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.oauth_consumers_client.delete_consumer,
+                        consumer['id'])
+        return consumer
+
+    @decorators.idempotent_id('c8307ea6-a86c-47fd-ae7b-5b3b2caca76d')
+    def test_create_and_show_consumer(self):
+        """Tests to make sure that a consumer with parameters is made"""
+        consumer = self._create_consumer()
+        # fetch created consumer from client
+        fetched_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        # assert that the fetched consumer matches the created one and
+        # has all parameters
+        for key in ['description', 'id', 'links']:
+            self.assertEqual(consumer[key], fetched_consumer[key])
+
+    @decorators.idempotent_id('fdfa1b7f-2a31-4354-b2c7-f6ae20554f93')
+    def test_delete_consumer(self):
+        """Tests the delete function."""
+        consumer = self._create_consumer()
+        # fetch consumer from client to confirm it exists
+        fetched_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        self.assertEqual(consumer['id'], fetched_consumer['id'])
+        # delete existing consumer
+        self.oauth_consumers_client.delete_consumer(consumer['id'])
+        # check that consumer no longer exists
+        self.assertRaises(exceptions.NotFound,
+                          self.oauth_consumers_client.show_consumer,
+                          consumer['id'])
+
+    @decorators.idempotent_id('080a9b1a-c009-47c0-9979-5305bf72e3dc')
+    def test_update_consumer(self):
+        """Tests the update functionality"""
+        # create a new consumer to update
+        consumer = self._create_consumer()
+        # create new description
+        new_description = data_utils.rand_name('test_update_consumer')
+        # update consumer
+        self.oauth_consumers_client.update_consumer(consumer['id'],
+                                                    new_description)
+        # check that the same consumer now has the new description
+        updated_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        self.assertEqual(new_description, updated_consumer['description'])
+
+    @decorators.idempotent_id('09ca50de-78f2-4ffb-ac71-f2254036b2b8')
+    def test_list_consumers(self):
+        """Test for listing consumers"""
+        # create two consumers to populate list
+        new_consumer_one = self._create_consumer()
+        new_consumer_two = self._create_consumer()
+        # fetch the list of consumers
+        consumer_list = self.oauth_consumers_client \
+                            .list_consumers()['consumers']
+        # add fetched consumer ids to a list
+        id_list = [consumer['id'] for consumer in consumer_list]
+        # check if created consumers are in the list
+        self.assertIn(new_consumer_one['id'], id_list)
+        self.assertIn(new_consumer_two['id'], id_list)
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index eb1c69e..730d469 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -14,9 +14,8 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
@@ -44,7 +43,7 @@
         missing_pols = [p for p in policy_ids if p not in fetched_ids]
         self.assertEqual(0, len(missing_pols))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e544703a-2f03-4cf2-9b0f-350782fdb0d3')
     def test_create_update_delete_policy(self):
         # Test to update policy
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index b37d33d..1b1d3f7 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -13,11 +13,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
-
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
@@ -28,11 +26,8 @@
     @decorators.idempotent_id('0ecf465c-0dc4-4532-ab53-91ffeb74d12d')
     def test_project_create_with_description(self):
         # Create project with a description
-        project_name = data_utils.rand_name('project')
         project_desc = data_utils.rand_name('desc')
-        project = self.projects_client.create_project(
-            project_name, description=project_desc)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(description=project_desc)
         project_id = project['id']
         desc1 = project['description']
         self.assertEqual(desc1, project_desc, 'Description should have '
@@ -47,9 +42,8 @@
         # Create project with a domain
         domain = self.setup_test_domain()
         project_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(
-            project_name, domain_id=domain['id'])['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(
+            name=project_name, domain_id=domain['id'])
         project_id = project['id']
         self.assertEqual(project_name, project['name'])
         self.assertEqual(domain['id'], project['domain_id'])
@@ -57,8 +51,6 @@
         self.assertEqual(project_name, body['name'])
         self.assertEqual(domain['id'], body['domain_id'])
 
-    @testtools.skipUnless(CONF.identity_feature_enabled.reseller,
-                          'Reseller not available.')
     @decorators.idempotent_id('1854f9c0-70bc-4d11-a08a-1c789d339e3d')
     def test_project_create_with_parent(self):
         # Create root project without providing a parent_id
@@ -66,10 +58,8 @@
         domain_id = domain['id']
 
         root_project_name = data_utils.rand_name('root_project')
-        root_project = self.projects_client.create_project(
-            root_project_name, domain_id=domain_id)['project']
-        self.addCleanup(
-            self.projects_client.delete_project, root_project['id'])
+        root_project = self.setup_test_project(
+            name=root_project_name, domain_id=domain_id)
 
         root_project_id = root_project['id']
         parent_id = root_project['parent_id']
@@ -80,23 +70,16 @@
 
         # Create a project using root_project_id as parent_id
         project_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(
-            project_name, domain_id=domain_id,
-            parent_id=root_project_id)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(
+            name=project_name, domain_id=domain_id, parent_id=root_project_id)
         parent_id = project['parent_id']
         self.assertEqual(project_name, project['name'])
         self.assertEqual(root_project_id, parent_id)
 
     @decorators.idempotent_id('a7eb9416-6f9b-4dbb-b71b-7f73aaef59d5')
-    @testtools.skipUnless(CONF.identity_feature_enabled.reseller,
-                          'Reseller not available.')
     def test_create_is_domain_project(self):
-        project_name = data_utils.rand_name('is_domain_project')
-        project = self.projects_client.create_project(
-            project_name, domain_id=None, is_domain=True)['project']
+        project = self.setup_test_project(domain_id=None, is_domain=True)
         # To delete a domain, we need to disable it first
-        self.addCleanup(self.projects_client.delete_project, project['id'])
         self.addCleanup(self.projects_client.update_project, project['id'],
                         enabled=False)
 
@@ -115,10 +98,7 @@
     @decorators.idempotent_id('1f66dc76-50cc-4741-a200-af984509e480')
     def test_project_create_enabled(self):
         # Create a project that is enabled
-        project_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(
-            project_name, enabled=True)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(enabled=True)
         project_id = project['id']
         en1 = project['enabled']
         self.assertTrue(en1, 'Enable should be True in response')
@@ -129,10 +109,7 @@
     @decorators.idempotent_id('78f96a9c-e0e0-4ee6-a3ba-fbf6dfd03207')
     def test_project_create_not_enabled(self):
         # Create a project that is not enabled
-        project_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(
-            project_name, enabled=False)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(enabled=False)
         en1 = project['enabled']
         self.assertEqual('false', str(en1).lower(),
                          'Enable should be False in response')
@@ -145,8 +122,7 @@
     def test_project_update_name(self):
         # Update name attribute of a project
         p_name1 = data_utils.rand_name('project')
-        project = self.projects_client.create_project(p_name1)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(name=p_name1)
 
         resp1_name = project['name']
 
@@ -166,11 +142,8 @@
     @decorators.idempotent_id('f138b715-255e-4a7d-871d-351e1ef2e153')
     def test_project_update_desc(self):
         # Update description attribute of a project
-        p_name = data_utils.rand_name('project')
         p_desc = data_utils.rand_name('desc')
-        project = self.projects_client.create_project(
-            p_name, description=p_desc)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(description=p_desc)
         resp1_desc = project['description']
 
         p_desc2 = data_utils.rand_name('desc2')
@@ -189,11 +162,8 @@
     @decorators.idempotent_id('b6b25683-c97f-474d-a595-55d410b68100')
     def test_project_update_enable(self):
         # Update the enabled attribute of a project
-        p_name = data_utils.rand_name('project')
         p_en = False
-        project = self.projects_client.create_project(p_name,
-                                                      enabled=p_en)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project(enabled=p_en)
 
         resp1_en = project['enabled']
 
@@ -214,9 +184,7 @@
     def test_associate_user_to_project(self):
         # Associate a user to a project
         # Create a Project
-        p_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(p_name)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project()
 
         # Create a User
         u_name = data_utils.rand_name('user')
diff --git a/tempest/api/identity/admin/v3/test_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index 87f8684..33a9c8c 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.py
@@ -14,33 +14,31 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class ProjectsNegativeTestJSON(base.BaseIdentityV3AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('24c49279-45dd-4155-887a-cb738c2385aa')
     def test_list_projects_by_unauthorized_user(self):
         # Non-admin user should not be able to list projects
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_projects_client.list_projects)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('874c3e84-d174-4348-a16b-8c01f599561b')
     def test_project_create_duplicate(self):
         # Project names should be unique
         project_name = data_utils.rand_name('project-dup')
-        project = self.projects_client.create_project(project_name)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        self.setup_test_project(name=project_name)
 
         self.assertRaises(lib_exc.Conflict,
                           self.projects_client.create_project, project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fba9de2-3e1f-4e77-812a-60cb68f8df13')
     def test_create_project_by_unauthorized_user(self):
         # Non-admin user should not be authorized to create a project
@@ -49,14 +47,14 @@
             lib_exc.Forbidden, self.non_admin_projects_client.create_project,
             project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7828db17-95e5-475b-9432-9a51b4aa79a9')
     def test_create_project_with_empty_name(self):
         # Project name should not be empty
         self.assertRaises(lib_exc.BadRequest,
                           self.projects_client.create_project, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('502b6ceb-b0c8-4422-bf53-f08fdb21e2f0')
     def test_create_projects_name_length_over_64(self):
         # Project name length should not be greater than 64 characters
@@ -64,18 +62,16 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.projects_client.create_project, project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8d68c012-89e0-4394-8d6b-ccd7196def97')
     def test_project_delete_by_unauthorized_user(self):
         # Non-admin user should not be able to delete a project
-        project_name = data_utils.rand_name('project')
-        project = self.projects_client.create_project(project_name)['project']
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project()
         self.assertRaises(
             lib_exc.Forbidden, self.non_admin_projects_client.delete_project,
             project['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7965b581-60c1-43b7-8169-95d4ab7fc6fb')
     def test_delete_non_existent_project(self):
         # Attempt to delete a non existent project should fail
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index f57a07c..ac550a7 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class RegionsTestJSON(base.BaseIdentityV3AdminTest):
@@ -79,7 +78,7 @@
         regions_list = [r['id'] for r in body]
         self.assertNotIn(region['id'], regions_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2c12c5b5-efcf-4aa5-90c5-bff1ab0cdbe2')
     def test_create_region_with_specific_id(self):
         # Create a region with a specific id
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 9bee24a..ac56fc6 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -14,12 +14,11 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -74,7 +73,7 @@
         self.assertEqual(len(body), 1)
         self.assertIn(role_id, fetched_role_ids)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
     def test_role_create_update_show_list(self):
         r_name = data_utils.rand_name('Role')
@@ -381,3 +380,48 @@
         role_assignments = self.role_assignments.list_role_assignments(
             effective=True, **params)['role_assignments']
         self.assertEmpty(role_assignments)
+
+    @decorators.idempotent_id('3748c316-c18f-4b08-997b-c60567bc6235')
+    def test_list_all_implied_roles(self):
+        # Create inference rule from "roles[0]" to "roles[1]"
+        self._create_implied_role(
+            self.roles[0]['id'], self.roles[1]['id'])
+
+        # Create inference rule from "roles[0]" to "roles[2]"
+        self._create_implied_role(
+            self.roles[0]['id'], self.roles[2]['id'])
+
+        # Create inference rule from "roles[2]" to "role"
+        self._create_implied_role(
+            self.roles[2]['id'], self.role['id'])
+
+        rules = self.roles_client.list_all_role_inference_rules()[
+            'role_inferences']
+        # Sort the rules by the number of inferences, since there should be 1
+        # inference between "roles[2]" and "role" and 2 inferences for
+        # "roles[0]": between "roles[1]" and "roles[2]".
+        sorted_rules = sorted(rules, key=lambda r: len(r['implies']))
+
+        # Check that 2 sets of rules are returned.
+        self.assertEqual(2, len(sorted_rules))
+        # Check that only 1 inference rule exists between "roles[2]" and "role"
+        self.assertEqual(1, len(sorted_rules[0]['implies']))
+        # Check that 2 inference rules exist for "roles[0]": one between
+        # "roles[1]" and one between "roles[2]".
+        self.assertEqual(2, len(sorted_rules[1]['implies']))
+
+        # Check that "roles[2]" is the "prior_role" and that "role" is the
+        # "implies" role.
+        self.assertEqual(self.roles[2]['id'],
+                         sorted_rules[0]['prior_role']['id'])
+        self.assertEqual(self.role['id'],
+                         sorted_rules[0]['implies'][0]['id'])
+
+        # Check that "roles[0]" is the "prior_role" and that "roles[1]" and
+        # "roles[2]" are the "implies" roles.
+        self.assertEqual(self.roles[0]['id'],
+                         sorted_rules[1]['prior_role']['id'])
+
+        implies_ids = [r['id'] for r in sorted_rules[1]['implies']]
+        self.assertIn(self.roles[1]['id'], implies_ids)
+        self.assertIn(self.roles[2]['id'], implies_ids)
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 35e1814..ad4e549 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -14,10 +14,9 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class ServicesTestJSON(base.BaseIdentityV3AdminTest):
@@ -29,7 +28,7 @@
         self.assertRaises(lib_exc.NotFound, self.services_client.show_service,
                           service_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5193aad5-bcb7-411d-85b0-b3b61b96ef06')
     def test_create_update_get_service(self):
         # Creating a Service
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index a9508d1..1a9502a 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -16,10 +16,13 @@
 import six
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
+CONF = config.CONF
+
 
 class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
 
@@ -29,12 +32,9 @@
         # Create a User
         u_name = data_utils.rand_name('user')
         u_desc = '%s-description' % u_name
-        u_email = '%s@testmail.tm' % u_name
         u_password = data_utils.rand_password()
-        user = self.users_client.create_user(
-            name=u_name, description=u_desc, password=u_password,
-            email=u_email)['user']
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(
+            name=u_name, description=u_desc, password=u_password)
         # Perform Authentication
         resp = self.token.auth(user_id=user['id'],
                                password=u_password).response
@@ -60,27 +60,19 @@
         """
 
         # Create a user.
-        user_name = data_utils.rand_name(name='user')
         user_password = data_utils.rand_password()
-        user = self.users_client.create_user(name=user_name,
-                                             password=user_password)['user']
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        user = self.create_test_user(password=user_password)
 
         # Create a couple projects
         project1_name = data_utils.rand_name(name='project')
-        project1 = self.projects_client.create_project(
-            project1_name)['project']
-        self.addCleanup(self.projects_client.delete_project, project1['id'])
+        project1 = self.setup_test_project(name=project1_name)
 
         project2_name = data_utils.rand_name(name='project')
-        project2 = self.projects_client.create_project(
-            project2_name)['project']
+        project2 = self.setup_test_project(name=project2_name)
         self.addCleanup(self.projects_client.delete_project, project2['id'])
 
         # Create a role
-        role_name = data_utils.rand_name(name='role')
-        role = self.roles_client.create_role(name=role_name)['role']
-        self.addCleanup(self.roles_client.delete_role, role['id'])
+        role = self.setup_test_role()
 
         # Grant the user the role on both projects.
         self.roles_client.create_user_role_on_project(project1['id'],
@@ -150,3 +142,34 @@
                          token_auth['token']['project']['id'])
         self.assertEqual(project2['name'],
                          token_auth['token']['project']['name'])
+
+    @decorators.idempotent_id('08ed85ce-2ba8-4864-b442-bcc61f16ae89')
+    def test_get_available_project_scopes(self):
+        manager_project_id = self.manager.credentials.project_id
+        admin_user_id = self.os_adm.credentials.user_id
+        admin_role_id = self.get_role_by_name(CONF.identity.admin_role)['id']
+
+        # Grant the user the role on both projects.
+        self.roles_client.create_user_role_on_project(
+            manager_project_id, admin_user_id, admin_role_id)
+        self.addCleanup(
+            self.roles_client.delete_role_from_user_on_project,
+            manager_project_id, admin_user_id, admin_role_id)
+
+        assigned_project_ids = [self.os_adm.credentials.project_id,
+                                manager_project_id]
+
+        # Get available project scopes
+        available_projects =\
+            self.client.list_auth_projects()['projects']
+
+        # create list to save fetched project's id
+        fetched_project_ids = [i['id'] for i in available_projects]
+
+        # verifying the project ids in list
+        missing_project_ids = \
+            [p for p in assigned_project_ids
+             if p not in fetched_project_ids]
+        self.assertEmpty(missing_project_ids,
+                         "Failed to find project_id %s in fetched list" %
+                         ', '.join(missing_project_ids))
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 1a466a0..339b4bb 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -18,11 +18,10 @@
 from tempest.api.identity import base
 from tempest import clients
 from tempest.common import credentials_factory as common_creds
-from tempest.common.utils import data_utils
 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
 
@@ -46,21 +45,21 @@
 
     def create_trustor_and_roles(self):
         # create a project that trusts will be granted on
-        self.trustor_project_name = data_utils.rand_name(name='project')
+        trustor_project_name = data_utils.rand_name(name='project')
         project = self.projects_client.create_project(
-            self.trustor_project_name, domain_id='default')['project']
+            trustor_project_name, domain_id='default')['project']
         self.trustor_project_id = project['id']
         self.assertIsNotNone(self.trustor_project_id)
 
         # Create a trustor User
-        self.trustor_username = data_utils.rand_name('user')
-        u_desc = self.trustor_username + 'description'
-        u_email = self.trustor_username + '@testmail.xx'
-        self.trustor_password = data_utils.rand_password()
+        trustor_username = data_utils.rand_name('user')
+        u_desc = trustor_username + 'description'
+        u_email = trustor_username + '@testmail.xx'
+        trustor_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            name=self.trustor_username,
+            name=trustor_username,
             description=u_desc,
-            password=self.trustor_password,
+            password=trustor_password,
             email=u_email,
             project_id=self.trustor_project_id,
             domain_id='default')['user']
@@ -95,10 +94,10 @@
         # Initialize a new client with the trustor credentials
         creds = common_creds.get_credentials(
             identity_version='v3',
-            username=self.trustor_username,
-            password=self.trustor_password,
+            username=trustor_username,
+            password=trustor_password,
             user_domain_id='default',
-            tenant_name=self.trustor_project_name,
+            tenant_name=trustor_project_name,
             project_domain_id='default',
             domain_id='default')
         os = clients.Manager(credentials=creds)
@@ -265,7 +264,7 @@
         self.assertEqual(1, len(trusts_get))
         self.validate_trust(trusts_get[0], summary=True)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4773ebd5-ecbf-4255-b8d8-b63e6f72b65d')
     def test_get_trusts_all(self):
 
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index e0ec883..4f271cb 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -18,8 +18,8 @@
 import testtools
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
@@ -42,11 +42,7 @@
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user['id'])
         # Creating second project for updation
-        project = self.projects_client.create_project(
-            data_utils.rand_name('project'),
-            description=data_utils.rand_name('project-desc'))['project']
-        # Delete the Project at the end of this method
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        project = self.setup_test_project()
         # Updating user details with new values
         u_name2 = data_utils.rand_name('user2')
         u_email2 = u_name2 + '@testmail.tm'
@@ -102,11 +98,7 @@
         # List the projects that a user has access upon
         assigned_project_ids = list()
         fetched_project_ids = list()
-        u_project = self.projects_client.create_project(
-            data_utils.rand_name('project'),
-            description=data_utils.rand_name('project-desc'))['project']
-        # Delete the Project at the end of this method
-        self.addCleanup(self.projects_client.delete_project, u_project['id'])
+        u_project = self.setup_test_project()
         # Create a user.
         u_name = data_utils.rand_name('user')
         u_desc = u_name + 'description'
@@ -118,23 +110,15 @@
         # Delete the User at the end of this method
         self.addCleanup(self.users_client.delete_user, user_body['id'])
         # Creating Role
-        role_body = self.roles_client.create_role(
-            name=data_utils.rand_name('role'))['role']
-        # Delete the Role at the end of this method
-        self.addCleanup(self.roles_client.delete_role, role_body['id'])
+        role_body = self.setup_test_role()
 
         user = self.users_client.show_user(user_body['id'])['user']
         role = self.roles_client.show_role(role_body['id'])['role']
         for _ in range(2):
             # Creating project so as to assign role
-            project_body = self.projects_client.create_project(
-                data_utils.rand_name('project'),
-                description=data_utils.rand_name('project-desc'))['project']
+            project_body = self.setup_test_project()
             project = self.projects_client.show_project(
                 project_body['id'])['project']
-            # Delete the Project at the end of this method
-            self.addCleanup(
-                self.projects_client.delete_project, project_body['id'])
             # Assigning roles to user on project
             self.roles_client.create_user_role_on_project(project['id'],
                                                           user['id'],
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 9626108..09d1b9b 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -14,15 +14,14 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+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
 
 
 class UsersNegativeTest(base.BaseIdentityV3AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e75f006c-89cc-477b-874d-588e4eab4b17')
     def test_create_user_for_non_existent_domain(self):
         # Attempt to create a user in a non-existent domain should fail
@@ -34,7 +33,7 @@
                           email=u_email,
                           domain_id=data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b3c9fccc-4134-46f5-b600-1da6fb0a3b1f')
     def test_authentication_for_disabled_user(self):
         # Attempt to authenticate for disabled user should fail
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 3c15d8c..aff3238 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -13,8 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 import tempest.test
 
@@ -47,7 +47,7 @@
         else:
             users = cls.users_client.list_users()['users']
         user = [u for u in users if u['name'] == name]
-        if len(user) > 0:
+        if user:
             return user[0]
 
     @classmethod
@@ -57,20 +57,24 @@
         except AttributeError:
             tenants = cls.projects_client.list_projects()['projects']
         tenant = [t for t in tenants if t['name'] == name]
-        if len(tenant) > 0:
+        if tenant:
             return tenant[0]
 
     @classmethod
     def get_role_by_name(cls, name):
         roles = cls.roles_client.list_roles()['roles']
         role = [r for r in roles if r['name'] == name]
-        if len(role) > 0:
+        if role:
             return role[0]
 
-    def _create_test_user(self, **kwargs):
+    def create_test_user(self, **kwargs):
         if kwargs.get('password', None) is None:
-            user_password = data_utils.rand_password()
-            kwargs['password'] = user_password
+            kwargs['password'] = data_utils.rand_password()
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name('test_user')
+        if 'email' not in kwargs:
+            kwargs['email'] = kwargs['name'] + '@testmail.tm'
+
         user = self.users_client.create_user(**kwargs)['user']
         # Delete the user at the end of the test
         self.addCleanup(
@@ -78,9 +82,9 @@
             self.users_client.delete_user, user['id'])
         return user
 
-    def setup_test_role(self, domain_id=None):
+    def setup_test_role(self, name=None, domain_id=None):
         """Set up a test role."""
-        params = {'name': data_utils.rand_name('test_role')}
+        params = {'name': name or data_utils.rand_name('test_role')}
         if domain_id:
             params['domain_id'] = domain_id
 
@@ -145,17 +149,16 @@
     def setup_test_user(self, password=None):
         """Set up a test user."""
         tenant = self.setup_test_tenant()
-        username = data_utils.rand_name('test_user')
-        email = username + '@testmail.tm'
-        user = self._create_test_user(name=username, email=email,
-                                      tenantId=tenant['id'], password=password)
+        user = self.create_test_user(tenantId=tenant['id'], password=password)
         return user
 
-    def setup_test_tenant(self):
+    def setup_test_tenant(self, **kwargs):
         """Set up a test tenant."""
-        tenant = self.projects_client.create_tenant(
-            name=data_utils.rand_name('test_tenant'),
-            description=data_utils.rand_name('desc'))['tenant']
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name('test_tenant')
+        if 'description' not in kwargs:
+            kwargs['description'] = data_utils.rand_name('desc')
+        tenant = self.projects_client.create_tenant(**kwargs)['tenant']
         # Delete the tenant at the end of the test
         self.addCleanup(
             test_utils.call_and_ignore_notfound_exc,
@@ -212,6 +215,7 @@
         cls.groups_client = cls.os_adm.groups_client
         cls.projects_client = cls.os_adm.projects_client
         cls.role_assignments = cls.os_admin.role_assignments_client
+        cls.oauth_consumers_client = cls.os_adm.oauth_consumers_client
         if CONF.identity.admin_domain_scope:
             # NOTE(andreaf) When keystone policy requires it, the identity
             # admin clients for these tests shall use 'domain' scoped tokens.
@@ -241,18 +245,17 @@
     def setup_test_user(self, password=None):
         """Set up a test user."""
         project = self.setup_test_project()
-        username = data_utils.rand_name('test_user')
-        email = username + '@testmail.tm'
-        user = self._create_test_user(name=username, email=email,
-                                      project_id=project['id'],
-                                      password=password)
+        user = self.create_test_user(project_id=project['id'],
+                                     password=password)
         return user
 
-    def setup_test_project(self):
+    def setup_test_project(self, **kwargs):
         """Set up a test project."""
-        project = self.projects_client.create_project(
-            name=data_utils.rand_name('test_project'),
-            description=data_utils.rand_name('desc'))['project']
+        if 'name' not in kwargs:
+            kwargs['name'] = data_utils.rand_name('test_project')
+        if 'description' not in kwargs:
+            kwargs['description'] = data_utils.rand_name('test_description')
+        project = self.projects_client.create_project(**kwargs)['project']
         # Delete the project at the end of the test
         self.addCleanup(
             test_utils.call_and_ignore_notfound_exc,
diff --git a/tempest/api/identity/v2/test_api_discovery.py b/tempest/api/identity/v2/test_api_discovery.py
index 02caef5..5b9d38c 100644
--- a/tempest/api/identity/v2/test_api_discovery.py
+++ b/tempest/api/identity/v2/test_api_discovery.py
@@ -15,13 +15,12 @@
 
 from tempest.api.identity import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestApiDiscovery(base.BaseIdentityV2Test):
     """Tests for API discovery features."""
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('ea889a68-a15f-4166-bfb1-c12456eae853')
     def test_api_version_resources(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -32,7 +31,7 @@
         for res in expected_resources:
             self.assertIn(res, keys)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('007a0be0-78fe-4fdb-bbee-e9216cc17bb2')
     def test_api_media_types(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -47,7 +46,7 @@
         for s_type in supported_types:
             self.assertIn(s_type, media_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('77fd6be0-8801-48e6-b9bf-38cdd2f253ec')
     def test_api_version_statuses(self):
         descr = self.non_admin_client.show_api_description()['version']
diff --git a/tempest/api/identity/v3/test_api_discovery.py b/tempest/api/identity/v3/test_api_discovery.py
index 177a49d..c04c21b 100644
--- a/tempest/api/identity/v3/test_api_discovery.py
+++ b/tempest/api/identity/v3/test_api_discovery.py
@@ -15,14 +15,13 @@
 
 from tempest.api.identity import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestApiDiscovery(base.BaseIdentityV3Test):
     """Tests for API discovery features."""
 
     @decorators.idempotent_id('721f480f-35b6-46c7-846e-047e6acea0dc')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_api_versions(self):
         # NOTE: Actually this API doesn't depend on v3 API at all, because
         # the API operation is "GET /" without v3's endpoint. The reason of
@@ -35,7 +34,7 @@
             for res in expected_resources:
                 self.assertIn(res, version)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('b9232f5e-d9e5-4d97-b96c-28d3db4de1bd')
     def test_api_version_resources(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -46,7 +45,7 @@
         for res in expected_resources:
             self.assertIn(res, keys)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('657c1970-4722-4189-8831-7325f3bc4265')
     def test_api_media_types(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -61,7 +60,7 @@
         for s_type in supported_types:
             self.assertIn(s_type, media_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8879a470-abfb-47bb-bb8d-5a7fd279ad1e')
     def test_api_version_statuses(self):
         descr = self.non_admin_client.show_api_description()['version']
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index f263258..e7998ee 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -34,8 +34,6 @@
         super(IdentityV3UsersTest, cls).resource_setup()
         cls.creds = cls.os.credentials
         cls.user_id = cls.creds.user_id
-        cls.username = cls.creds.username
-        cls.password = cls.creds.password
 
     def _update_password(self, original_password, password):
         self.non_admin_users_client.update_user_password(
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
index 11b595a..fc5ed79 100644
--- a/tempest/api/image/admin/v2/test_images.py
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -17,8 +17,8 @@
 import testtools
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
 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
 
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index cd4f820..c586960 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -15,8 +15,8 @@
 import six
 
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 import tempest.test
 
@@ -145,6 +145,7 @@
         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
+        cls.versions_client = cls.os.image_versions_client
 
     def create_namespace(cls, namespace_name=None, visibility='public',
                          description='Tempest', protected=False,
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
index d1aa801..2748bd5 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -13,15 +13,14 @@
 #    under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+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
 
 
 class ImageMembersNegativeTest(base.BaseV1ImageMembersTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('147a9536-18e3-45da-91ea-b037a028f364')
     def test_add_member_with_non_existing_image(self):
         # Add member with non existing image.
@@ -30,7 +29,7 @@
                           self.image_member_client.create_image_member,
                           non_exist_image, self.alt_tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e1559f05-b667-4f1b-a7af-518b52dc0c0f')
     def test_delete_member_with_non_existing_image(self):
         # Delete member with non existing image.
@@ -39,7 +38,7 @@
                           self.image_member_client.delete_image_member,
                           non_exist_image, self.alt_tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5720333-dd69-4194-bb76-d2f048addd56')
     def test_delete_member_with_non_existing_tenant(self):
         # Delete member with non existing tenant.
@@ -49,7 +48,7 @@
                           self.image_member_client.delete_image_member,
                           image_id, non_exist_tenant)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f25f89e4-0b6c-453b-a853-1f80b9d7ef26')
     def test_get_image_without_membership(self):
         # Image is hidden from another tenants.
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 756c78c..b341ab7 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -17,9 +17,9 @@
 
 from tempest.api.image import base
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 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
 
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index abec82a..690b8da 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -15,16 +15,15 @@
 
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+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
 
 
 class CreateDeleteImagesNegativeTest(base.BaseV1ImageTest):
     """Here are negative tests for the deletion and creation of images."""
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('036ede36-6160-4463-8c01-c781eee6369d')
     def test_register_with_invalid_container_format(self):
         # Negative tests for invalid data supplied to POST /images
@@ -33,7 +32,7 @@
                                    'x-image-meta-container_format': 'wrong',
                                    'x-image-meta-disk_format': 'vhd'})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
     def test_register_with_invalid_disk_format(self):
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
@@ -41,7 +40,7 @@
                                    'x-image-meta-container_format': 'bare',
                                    'x-image-meta-disk_format': 'wrong'})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ec652588-7e3c-4b67-a2f2-0fa96f57c8fc')
     def test_delete_non_existent_image(self):
         # Return an error while trying to delete a non-existent image
@@ -50,13 +49,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('04f72aa3-fcec-45a3-81a3-308ef7cc82bc')
     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'])
+    @decorators.attr(type=['negative'])
     @decorators.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
@@ -64,13 +63,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           invalid_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4ed757cd-450c-44b1-9fd1-c819748c650d')
     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'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a4a448ab-3db2-4d2d-b9b2-6a1271241dfe')
     def test_delete_image_id_over_character_limit(self):
         # Return an error while trying to delete image with id over limit
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 2812c68..8310001 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -20,10 +20,9 @@
 
 from oslo_log import log as logging
 from tempest.api.image import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
@@ -32,7 +31,7 @@
 class BasicOperationsImagesTest(base.BaseV2ImageTest):
     """Here we test the basic operations of images"""
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('139b765e-7f3d-4b3d-8b37-3ca3876ee318')
     def test_register_upload_get_image_file(self):
         """Here we test these functionalities
@@ -74,7 +73,7 @@
         body = self.client.show_image_file(image['id'])
         self.assertEqual(file_content, body.data)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f848bb94-1c6e-45a4-8726-39e3a5b23535')
     def test_delete_image(self):
         # Deletes an image by image_id
@@ -96,7 +95,7 @@
         images_id = [item['id'] for item in images]
         self.assertNotIn(image['id'], images_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f66891a7-a35c-41a8-b590-a065c2a1caa6')
     def test_update_image(self):
         # Updates an image by image_id
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index 7a495e7..0208780 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -96,20 +96,3 @@
     def test_get_image_members_schema(self):
         body = self.schemas_client.show_schema("members")
         self.assertEqual("members", body['name'])
-
-    @decorators.idempotent_id('cb961424-3f68-4d21-8e36-30ad66fb6bfb')
-    def test_get_private_image(self):
-        image_id = self._create_image()
-        member = self.image_member_client.create_image_member(
-            image_id, member=self.alt_tenant_id)
-        self.assertEqual(member['member_id'], self.alt_tenant_id)
-        self.assertEqual(member['image_id'], image_id)
-        self.assertEqual(member['status'], 'pending')
-        self.assertNotIn(image_id, self._list_image_ids_as_alt())
-        self.alt_image_member_client.update_image_member(image_id,
-                                                         self.alt_tenant_id,
-                                                         status='accepted')
-        self.assertIn(image_id, self._list_image_ids_as_alt())
-        self.image_member_client.delete_image_member(image_id,
-                                                     self.alt_tenant_id)
-        self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index ae9630a..caa90f9 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -13,12 +13,11 @@
 from tempest.api.image import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImagesMemberNegativeTest(base.BaseV2MemberImageTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
     def test_image_share_invalid_status(self):
         image_id = self._create_image()
@@ -30,7 +29,7 @@
                           image_id, self.alt_tenant_id,
                           status='notavalidstatus')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
     def test_image_share_owner_cannot_accept(self):
         image_id = self._create_image()
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_objects.py b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
index 38e56d4..80f8112 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_objects.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_properties.py b/tempest/api/image/v2/test_images_metadefs_namespace_properties.py
index ead70f2..ed91726 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespace_properties.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_properties.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/image/v2/test_images_metadefs_namespace_tags.py b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
index 608d9fc..e2a3617 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespace_tags.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/image/v2/test_images_metadefs_namespaces.py b/tempest/api/image/v2/test_images_metadefs_namespaces.py
index 9fda937..f71b16c 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespaces.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespaces.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 04c752a..b4baf05 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -18,7 +18,6 @@
 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
 
 
 class ImagesNegativeTest(base.BaseV2ImageTest):
@@ -34,7 +33,7 @@
         ** delete the deleted image
      """
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81d9f')
     def test_get_non_existent_image(self):
         # get the non-existent image
@@ -42,14 +41,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_image,
                           non_existent_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2562ad')
     def test_get_image_null_id(self):
         # get image with image_id = NULL
         image_id = ""
         self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e57fc127-7ba0-4693-92d7-1d8a05ebcba9')
     def test_get_delete_deleted_image(self):
         # get and delete the deleted image
@@ -68,7 +67,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           image['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6fe40f1c-57bd-4918-89cc-8500f850f3de')
     def test_delete_non_existing_image(self):
         # delete non-existent image
@@ -76,7 +75,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('32248db1-ab88-4821-9604-c7c369f1f88c')
     def test_delete_image_null_id(self):
         # delete image with image_id=NULL
@@ -84,7 +83,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('292bd310-369b-41c7-a7a3-10276ef76753')
     def test_register_with_invalid_container_format(self):
         # Negative tests for invalid data supplied to POST /images
@@ -92,9 +91,22 @@
                           name='test', container_format='wrong',
                           disk_format='vhd')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('70c6040c-5a97-4111-9e13-e73665264ce1')
     def test_register_with_invalid_disk_format(self):
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           name='test', container_format='bare',
                           disk_format='wrong')
+
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('ab980a34-8410-40eb-872b-f264752f46e5')
+    def test_delete_protected_image(self):
+        # Create a protected image
+        image = self.create_image(protected=True)
+        self.addCleanup(self.client.update_image, image['id'],
+                        [dict(replace="/protected", value=False)])
+
+        # Try deleting the protected image
+        self.assertRaises(lib_exc.Forbidden,
+                          self.client.delete_image,
+                          image['id'])
diff --git a/tempest/api/image/v2/test_images_tags.py b/tempest/api/image/v2/test_images_tags.py
index fd9591f..601826e 100644
--- a/tempest/api/image/v2/test_images_tags.py
+++ b/tempest/api/image/v2/test_images_tags.py
@@ -13,7 +13,7 @@
 # under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/image/v2/test_images_tags_negative.py b/tempest/api/image/v2/test_images_tags_negative.py
index 2a08f3a..440fa36 100644
--- a/tempest/api/image/v2/test_images_tags_negative.py
+++ b/tempest/api/image/v2/test_images_tags_negative.py
@@ -13,15 +13,14 @@
 # under the License.
 
 from tempest.api.image import base
-from tempest.common.utils import data_utils
+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
 
 
 class ImagesTagsNegativeTest(base.BaseV2ImageTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8cd30f82-6f9a-4c6e-8034-c1b51fba43d9')
     def test_update_tags_for_non_existing_image(self):
         # Update tag with non existing image.
@@ -30,7 +29,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.add_image_tag,
                           non_exist_image, tag)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('39c023a2-325a-433a-9eea-649bf1414b19')
     def test_delete_non_existing_tag(self):
         # Delete non existing tag.
diff --git a/tempest/api/image/v2/test_versions.py b/tempest/api/image/v2/test_versions.py
new file mode 100644
index 0000000..84f1068
--- /dev/null
+++ b/tempest/api/image/v2/test_versions.py
@@ -0,0 +1,29 @@
+# Copyright 2017 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.image import base
+from tempest.lib import decorators
+
+
+class VersionsTest(base.BaseV2ImageTest):
+
+    @decorators.idempotent_id('659ea30a-a17c-4317-832c-0f68ed23c31d')
+    @decorators.attr(type='smoke')
+    def test_list_versions(self):
+        versions = self.versions_client.list_versions()['versions']
+        expected_resources = ('id', 'links', 'status')
+
+        for version in versions:
+            for res in expected_resources:
+                self.assertIn(res, version)
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index dc440d3..c83dd7f 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/network/admin/test_external_networks_negative.py b/tempest/api/network/admin/test_external_networks_negative.py
index 770d91f..0709d2a 100644
--- a/tempest/api/network/admin/test_external_networks_negative.py
+++ b/tempest/api/network/admin/test_external_networks_negative.py
@@ -19,14 +19,13 @@
 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
 
 CONF = config.CONF
 
 
 class ExternalNetworksAdminNegativeTestJSON(base.BaseAdminNetworkTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d402ae6c-0be0-4d8e-833b-a738895d98d0')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index e1970b9..e7460af 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -28,7 +28,6 @@
 
 class L3AgentSchedulerTestJSON(base.BaseAdminNetworkTest):
     _agent_mode = 'legacy'
-    is_dvr_router = False
 
     """
     Tests the following operations in the Neutron API using the REST client for
@@ -68,42 +67,6 @@
             raise exceptions.InvalidConfiguration(msg)
         cls.router = cls.create_router()
 
-        if CONF.network.dvr_extra_resources:
-            # NOTE(armax): If DVR is an available extension, and the created
-            # router is indeed a distributed one, more resources need to be
-            # provisioned in order to bind the router to the L3 agent in the
-            # Liberty release or older, and are not required since the Mitaka
-            # release.
-            if test.is_extension_enabled('dvr', 'network'):
-                cls.is_dvr_router = cls.admin_routers_client.show_router(
-                    cls.router['id'])['router'].get('distributed', False)
-                if cls.is_dvr_router:
-                    cls.network = cls.create_network()
-                    cls.create_subnet(cls.network)
-                    cls.port = cls.create_port(cls.network)
-                    cls.routers_client.add_router_interface(
-                        cls.router['id'], port_id=cls.port['id'])
-                    # NOTE: Sometimes we have seen this test fail with dvr in,
-                    # multinode tests, since the dhcp port is not created
-                    # before the test gets executed and so the router is not
-                    # scheduled on the given agent. By adding the external
-                    # gateway info to the router, the router should be properly
-                    # scheduled in the dvr_snat node. This is a temporary work
-                    # around to prevent a race condition.
-                    external_gateway_info = {
-                        'network_id': CONF.network.public_network_id,
-                        'enable_snat': True}
-                    cls.admin_routers_client.update_router(
-                        cls.router['id'],
-                        external_gateway_info=external_gateway_info)
-
-    @classmethod
-    def resource_cleanup(cls):
-        if cls.is_dvr_router:
-            cls.routers_client.remove_router_interface(cls.router['id'],
-                                                       port_id=cls.port['id'])
-        super(L3AgentSchedulerTestJSON, cls).resource_cleanup()
-
     @decorators.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
     def test_list_routers_on_l3_agent(self):
         self.admin_agents_client.list_routers_on_l3_agent(self.agent['id'])
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 2c639da..21688d2 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -39,7 +39,7 @@
             msg = "quotas extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('644f4e1b-1bf9-4af0-9fd8-eb56ac0f51cf')
     def test_network_quota_exceeding(self):
         # Set the network quota to two
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 7b6ebef..aa8b2dc 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest import test
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 78ca494..4ccad30 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -16,7 +16,7 @@
 import testtools
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 132e23e..7ceeb50 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -15,9 +15,9 @@
 
 import netaddr
 
-from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
@@ -106,7 +106,7 @@
 
             # Clean up metering label rules
             # Not all classes in the hierarchy have the client class variable
-            if len(cls.metering_label_rules) > 0:
+            if cls.metering_label_rules:
                 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(
diff --git a/tempest/api/network/base_security_groups.py b/tempest/api/network/base_security_groups.py
index 3ea3aea..b8d677a 100644
--- a/tempest/api/network/base_security_groups.py
+++ b/tempest/api/network/base_security_groups.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 
 
 class BaseSecGroupTest(base.BaseNetworkTest):
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 136f9e6..9d6d700 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -16,11 +16,12 @@
 import random
 
 import netaddr
+from oslo_utils import netutils
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
 from tempest.common.utils import net_info
 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
 
@@ -92,8 +93,8 @@
         port_mac = data_utils.rand_mac_address()
         port = self.create_port(self.network, mac_address=port_mac)
         real_ip = next(iter(port['fixed_ips']), None)['ip_address']
-        eui_ip = data_utils.get_ipv6_addr_by_EUI64(subnet['cidr'],
-                                                   port_mac).format()
+        eui_ip = str(netutils.get_ipv6_addr_by_EUI64(
+            subnet['cidr'], port_mac))
         return real_ip, eui_ip
 
     @decorators.idempotent_id('e5517e62-6f16-430d-a672-f80875493d4c')
@@ -188,10 +189,8 @@
                         self.network, **kwargs_dhcp)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                eui_ip = data_utils.get_ipv6_addr_by_EUI64(
-                    subnet_slaac['cidr'],
-                    port_mac
-                ).format()
+                eui_ip = str(netutils.get_ipv6_addr_by_EUI64(
+                    subnet_slaac['cidr'], port_mac))
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
@@ -236,10 +235,8 @@
                         self.network, ip_version=4)
                     subnet_slaac = self.create_subnet(self.network, **kwargs)
                 port_mac = data_utils.rand_mac_address()
-                eui_ip = data_utils.get_ipv6_addr_by_EUI64(
-                    subnet_slaac['cidr'],
-                    port_mac
-                ).format()
+                eui_ip = str(netutils.get_ipv6_addr_by_EUI64(
+                    subnet_slaac['cidr'], port_mac))
                 port = self.create_port(self.network, mac_address=port_mac)
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index 2662e9c..014d064 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -29,7 +29,7 @@
     etc/tempest.conf.
     """
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('ef28c7e6-e646-4979-9d67-deb207bc5564')
     def test_list_show_extensions(self):
         # List available extensions for the project
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 1156275..dc9042e 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 1dc574b..f0f92ac 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -64,7 +64,7 @@
         for i in range(2):
             cls.create_port(cls.network)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e8718')
     def test_create_list_show_update_delete_floating_ip(self):
         # Creates a floating IP
@@ -171,7 +171,7 @@
                          port_other_router['id'])
         self.assertIsNotNone(updated_floating_ip['fixed_ip_address'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('36de4bd0-f09c-43e3-a8e1-1decc1ffd3a5')
     def test_create_floating_ip_specifying_a_fixed_ip_address(self):
         body = self.floating_ips_client.create_floatingip(
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index cb29d3d..f5830ab 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -52,7 +52,7 @@
         cls.create_router_interface(router['id'], subnet['id'])
         cls.port = cls.create_port(cls.network)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('22996ea8-4a81-4b27-b6e1-fa5df92fa5e8')
     def test_create_floatingip_with_port_ext_net_unreachable(self):
         self.assertRaises(
@@ -61,7 +61,7 @@
             fixed_ip_address=self.port['fixed_ips'][0]
                                       ['ip_address'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('50b9aeb4-9f0b-48ee-aa31-fa955a48ff54')
     def test_create_floatingip_in_private_network(self):
         self.assertRaises(lib_exc.BadRequest,
@@ -71,7 +71,7 @@
                           fixed_ip_address=self.port['fixed_ips'][0]
                                                     ['ip_address'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6b3b8797-6d43-4191-985c-c48b773eb429')
     def test_associate_floatingip_port_ext_net_unreachable(self):
         # Create floating ip
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 42fa9e4..18dccc3 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -13,7 +13,7 @@
 # under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 69d4ebe..269f2c2 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,8 +18,8 @@
 
 from tempest.api.network import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -174,7 +174,7 @@
         project_network_v6_mask_bits is the equivalent for ipv6 subnets
     """
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0e269138-0da6-4efc-a46d-578161e7b221')
     def test_create_update_delete_network_subnet(self):
         # Create a network
@@ -196,7 +196,7 @@
         updated_subnet = body['subnet']
         self.assertEqual(updated_subnet['name'], new_name)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
     def test_show_network(self):
         # Verify the details of a network
@@ -220,7 +220,7 @@
         self.assertNotIn('tenant_id', network)
         self.assertNotIn('project_id', network)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
     def test_list_networks(self):
         # Verify the network exists in the list of all networks
@@ -241,7 +241,7 @@
         for network in networks:
             self.assertEqual(sorted(network.keys()), sorted(fields))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('bd635d81-6030-4dd1-b3b9-31ba0cfdf6cc')
     def test_show_subnet(self):
         # Verify the details of a subnet
@@ -263,7 +263,7 @@
         for field_name in fields:
             self.assertEqual(subnet[field_name], self.subnet[field_name])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('db68ba48-f4ea-49e9-81d1-e367f6d0b20a')
     def test_list_subnets(self):
         # Verify the subnet exists in the list of all subnets
@@ -368,7 +368,7 @@
             enable_dhcp=True,
             **self.subnet_dict(['gateway', 'host_routes', 'dns_nameservers']))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
     @test.requires_ext(extension='external-net', service='network')
     @testtools.skipUnless(CONF.network.public_network_id,
@@ -452,7 +452,7 @@
         for n in created_ports:
             self.assertNotIn(n['id'], ports_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('d4f9024d-1e28-4fc1-a6b1-25dbc6fa11e2')
     def test_bulk_create_delete_network(self):
         # Creates 2 networks in one request
@@ -468,7 +468,7 @@
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], networks_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8936533b-c0aa-4f29-8e53-6cc873aec489')
     def test_bulk_create_delete_subnet(self):
         networks = [self.create_network(), self.create_network()]
@@ -503,7 +503,7 @@
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], subnets_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('48037ff2-e889-4c3b-b86a-8e3f34d2d060')
     def test_bulk_create_delete_port(self):
         networks = [self.create_network(), self.create_network()]
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 3cc6fb7..bc4f41f 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -15,36 +15,35 @@
 #    under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
+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
 
 
 class NetworksNegativeTestJSON(base.BaseNetworkTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9293e937-824d-42d2-8d5b-e985ea67002a')
     def test_show_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.networks_client.show_network,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d746b40c-5e09-4043-99f7-cba1be8b70df')
     def test_show_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.subnets_client.show_subnet,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a954861d-cbfd-44e8-b0a9-7fab111f235d')
     def test_show_non_existent_port(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.ports_client.show_port,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('98bfe4e3-574e-4012-8b17-b2647063de87')
     def test_update_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
@@ -52,7 +51,7 @@
             lib_exc.NotFound, self.networks_client.update_network,
             non_exist_id, name="new_name")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('03795047-4a94-4120-a0a1-bd376e36fd4e')
     def test_delete_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
@@ -60,21 +59,21 @@
                           self.networks_client.delete_network,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1cc47884-ac52-4415-a31c-e7ce5474a868')
     def test_update_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.subnets_client.update_subnet,
                           non_exist_id, name='new_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a176c859-99fb-42ec-a208-8a85b552a239')
     def test_delete_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound,
                           self.subnets_client.delete_subnet, non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('13d3b106-47e6-4b9b-8d53-dae947f092fe')
     def test_create_port_on_non_existent_network(self):
         non_exist_net_id = data_utils.rand_uuid()
@@ -82,14 +81,14 @@
                           self.ports_client.create_port,
                           network_id=non_exist_net_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cf8eef21-4351-4f53-adcd-cc5cb1e76b92')
     def test_update_non_existent_port(self):
         non_exist_port_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.ports_client.update_port,
                           non_exist_port_id, name='new_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('49ec2bbd-ac2e-46fd-8054-798e679ff894')
     def test_delete_non_existent_port(self):
         non_exist_port_id = data_utils.rand_uuid()
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 3908aae..69a1441 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -21,8 +21,8 @@
 from tempest.api.network import base
 from tempest.api.network import base_security_groups as sec_base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
@@ -52,7 +52,7 @@
         ports_list = body['ports']
         self.assertFalse(port_id in [n['id'] for n in ports_list])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c72c1c0c-2193-4aca-aaa4-b1442640f51c')
     def test_create_update_delete_port(self):
         # Verify port creation
@@ -100,7 +100,7 @@
 
         return cidr
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0435f278-40ae-48cb-a404-b8a087bc09b1')
     def test_create_port_in_allowed_allocation_pools(self):
         network = self.create_network()
@@ -125,7 +125,7 @@
         ip_range = netaddr.IPRange(start_ip_address, end_ip_address)
         self.assertIn(ip_address, ip_range)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c9a685bd-e83f-499c-939f-9f7863ca259f')
     def test_show_port(self):
         # Verify the details of port
@@ -153,7 +153,7 @@
         for field_name in fields:
             self.assertEqual(port[field_name], self.port[field_name])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cf95b358-3e92-4a29-a148-52445e1ac50e')
     def test_list_ports(self):
         # Verify the port exists in the list of all ports
@@ -342,7 +342,7 @@
         self.assertEqual(free_mac_address,
                          show_port['mac_address'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
     @testtools.skipUnless(
         test.is_extension_enabled('security-group', 'network'),
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 694b86b..97ad4d4 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -17,8 +17,8 @@
 import testtools
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -41,7 +41,7 @@
                            if cls._ip_version == 4 else
                            CONF.network.project_network_v6_cidr)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f64403e2-8483-4b34-8ccd-b09a87bcc68c')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
@@ -122,7 +122,7 @@
             self._verify_router_gateway(create_body['router']['id'],
                                         exp_ext_gw_info=external_gateway_info)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('b42e6e39-2e37-49cc-a6f4-8467e940900a')
     def test_add_remove_router_interface_with_subnet_id(self):
         network = self.create_network()
@@ -141,7 +141,7 @@
         self.assertEqual(show_port_body['port']['device_id'],
                          router['id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2b7d2f37-6748-4d78-92e5-1d590234f0d5')
     def test_add_remove_router_interface_with_port_id(self):
         network = self.create_network()
@@ -239,6 +239,37 @@
              'enable_snat': False})
         self._verify_gateway_port(router['id'])
 
+    @decorators.idempotent_id('cbe42f84-04c2-11e7-8adb-fa163e4fa634')
+    @test.requires_ext(extension='ext-gw-mode', service='network')
+    @testtools.skipUnless(CONF.network.public_network_id,
+                          'The public_network_id option must be specified.')
+    @decorators.skip_because(bug='1676207')
+    def test_create_router_set_gateway_with_fixed_ip(self):
+        # Don't know public_network_address, so at first create address
+        # from public_network and delete
+        port = self.admin_ports_client.create_port(
+            network_id=CONF.network.public_network_id)['port']
+        self.admin_ports_client.delete_port(port_id=port['id'])
+
+        fixed_ip = {
+            'subnet_id': port['fixed_ips'][0]['subnet_id'],
+            'ip_address': port['fixed_ips'][0]['ip_address']
+        }
+        external_gateway_info = {
+            'network_id': CONF.network.public_network_id,
+            'external_fixed_ips': [fixed_ip]
+        }
+
+        # Create a router and set gateway to fixed_ip
+        router = self.admin_routers_client.create_router(
+            external_gateway_info=external_gateway_info)['router']
+        self.addCleanup(self.admin_routers_client.delete_router,
+                        router_id=router['id'])
+        # Examine router's gateway is equal to fixed_ip
+        self.assertEqual(router['external_gateway_info'][
+                         'external_fixed_ips'][0]['ip_address'],
+                         fixed_ip['ip_address'])
+
     @decorators.idempotent_id('ad81b7ee-4f81-407b-a19c-17e623f763e8')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
@@ -345,7 +376,7 @@
         show_body = self.routers_client.show_router(router['id'])
         self.assertTrue(show_body['router']['admin_state_up'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('802c73c9-c937-4cef-824b-2191e24a6aab')
     def test_add_multiple_router_interfaces(self):
         network01 = self.create_network(
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 2bda431..fdd8dd8 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -14,10 +14,11 @@
 #    under the License.
 
 import netaddr
+import testtools
 
 from tempest.api.network import base_routers as base
-from tempest.common.utils import data_utils
 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
@@ -44,7 +45,7 @@
                            if cls._ip_version == 4 else
                            CONF.network.project_network_v6_cidr)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('37a94fc0-a834-45b9-bd23-9a81d2fd1e22')
     def test_router_add_gateway_invalid_network_returns_404(self):
         self.assertRaises(lib_exc.NotFound,
@@ -53,7 +54,7 @@
                           external_gateway_info={
                               'network_id': self.router['id']})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('11836a18-0b15-4327-a50b-f0d9dc66bddd')
     def test_router_add_gateway_net_not_external_returns_400(self):
         alt_network = self.create_network()
@@ -65,7 +66,7 @@
                           external_gateway_info={
                               'network_id': alt_network['id']})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('957751a3-3c68-4fa2-93b6-eb52ea10db6e')
     def test_add_router_interfaces_on_overlapping_subnets_returns_400(self):
         network01 = self.create_network(
@@ -81,7 +82,32 @@
                           self.router['id'],
                           subnet02['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('7101cc02-058a-11e7-93e1-fa163e4fa634')
+    @test.requires_ext(extension='ext-gw-mode', service='network')
+    @testtools.skipUnless(CONF.network.public_network_id,
+                          'The public_network_id option must be specified.')
+    def test_router_set_gateway_used_ip_returns_409(self):
+        # At first create a address from public_network_id
+        port = self.admin_ports_client.create_port(
+            network_id=CONF.network.public_network_id)['port']
+        self.addCleanup(self.admin_ports_client.delete_port,
+                        port_id=port['id'])
+        # Add used ip and subnet_id in external_fixed_ips
+        fixed_ip = {
+            'subnet_id': port['fixed_ips'][0]['subnet_id'],
+            'ip_address': port['fixed_ips'][0]['ip_address']
+        }
+        external_gateway_info = {
+            'network_id': CONF.network.public_network_id,
+            'external_fixed_ips': [fixed_ip]
+        }
+        # Create a router and set gateway to used ip
+        self.assertRaises(lib_exc.Conflict,
+                          self.admin_routers_client.create_router,
+                          external_gateway_info=external_gateway_info)
+
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('04df80f9-224d-47f5-837a-bf23e33d1c20')
     def test_router_remove_interface_in_use_returns_409(self):
         self.routers_client.add_router_interface(self.router['id'],
@@ -90,21 +116,21 @@
                           self.routers_client.delete_router,
                           self.router['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c2a70d72-8826-43a7-8208-0209e6360c47')
     def test_show_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
         self.assertRaises(lib_exc.NotFound, self.routers_client.show_router,
                           router)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b23d1569-8b0c-4169-8d4b-6abd34fad5c7')
     def test_update_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
         self.assertRaises(lib_exc.NotFound, self.routers_client.update_router,
                           router, name="new_name")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c7edc5ad-d09d-41e6-a344-5c0c31e2e3e4')
     def test_delete_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
@@ -132,7 +158,7 @@
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
     def test_router_create_tenant_distributed_returns_forbidden(self):
         self.assertRaises(lib_exc.Forbidden, self.create_router,
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 607baf0..0d5e230 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.network import base_security_groups as base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -67,7 +67,7 @@
                              "rule does not match with %s." %
                              (key, value))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e30abd17-fef9-4739-8617-dc26da88e686')
     def test_list_security_groups(self):
         # Verify the security group belonging to project exist in list
@@ -80,7 +80,7 @@
         msg = "Security-group list doesn't contain default security-group"
         self.assertIsNotNone(found, msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('bfd128e5-3c92-44b6-9d66-7fe29d22c802')
     def test_create_list_update_show_delete_security_group(self):
         group_create_body, name = self._create_security_group()
@@ -109,7 +109,7 @@
         self.assertEqual(show_body['security_group']['description'],
                          new_description)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cfb99e0e-7410-4a3d-8a0c-959a63ee77e9')
     def test_create_show_delete_security_group_rule(self):
         group_create_body, _ = self._create_security_group()
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index f46b873..f51fb33 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -33,7 +33,7 @@
             msg = "security-group extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('424fd5c3-9ddc-486a-b45f-39bf0c820fc6')
     def test_show_non_existent_security_group(self):
         non_exist_id = data_utils.rand_uuid()
@@ -41,7 +41,7 @@
             lib_exc.NotFound, self.security_groups_client.show_security_group,
             non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4c094c09-000b-4e41-8100-9617600c02a6')
     def test_show_non_existent_security_group_rule(self):
         non_exist_id = data_utils.rand_uuid()
@@ -50,7 +50,7 @@
             self.security_group_rules_client.show_security_group_rule,
             non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f1bb89d-5664-4956-9fcd-83ee0fa603df')
     def test_delete_non_existent_security_group(self):
         non_exist_id = data_utils.rand_uuid()
@@ -59,7 +59,7 @@
                           non_exist_id
                           )
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('981bdc22-ce48-41ed-900a-73148b583958')
     def test_create_security_group_rule_with_bad_protocol(self):
         group_create_body, _ = self._create_security_group()
@@ -72,7 +72,7 @@
             security_group_id=group_create_body['security_group']['id'],
             protocol=pname, direction='ingress', ethertype=self.ethertype)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5f8daf69-3c5f-4aaa-88c9-db1d66f68679')
     def test_create_security_group_rule_with_bad_remote_ip_prefix(self):
         group_create_body, _ = self._create_security_group()
@@ -87,7 +87,7 @@
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_ip_prefix=remote_ip_prefix)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4bf786fd-2f02-443c-9716-5b98e159a49a')
     def test_create_security_group_rule_with_non_existent_remote_groupid(self):
         group_create_body, _ = self._create_security_group()
@@ -103,7 +103,7 @@
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_group_id=remote_group_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b5c4b247-6b02-435b-b088-d10d45650881')
     def test_create_security_group_rule_with_remote_ip_and_group(self):
         sg1_body, _ = self._create_security_group()
@@ -119,7 +119,7 @@
             ethertype=self.ethertype, remote_ip_prefix=prefix,
             remote_group_id=sg2_body['security_group']['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5666968c-fff3-40d6-9efc-df1c8bd01abb')
     def test_create_security_group_rule_with_bad_ethertype(self):
         group_create_body, _ = self._create_security_group()
@@ -132,7 +132,7 @@
             security_group_id=group_create_body['security_group']['id'],
             protocol='udp', direction='ingress', ethertype=ethertype)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0d9c7791-f2ad-4e2f-ac73-abf2373b0d2d')
     def test_create_security_group_rule_with_invalid_ports(self):
         group_create_body, _ = self._create_security_group()
@@ -166,7 +166,7 @@
                 direction='ingress', ethertype=self.ethertype)
             self.assertIn(msg, str(ex))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2323061e-9fbf-4eb0-b547-7e8fafc90849')
     def test_create_additional_default_security_group_fails(self):
         # Create security group named 'default', it should be failed.
@@ -175,7 +175,17 @@
                           self.security_groups_client.create_security_group,
                           name=name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('966e2b96-023a-11e7-a9e4-fa163e4fa634')
+    def test_create_security_group_update_name_default(self):
+        # Update security group name to 'default', it should be failed.
+        group_create_body, _ = self._create_security_group()
+        self.assertRaises(lib_exc.Conflict,
+                          self.security_groups_client.update_security_group,
+                          group_create_body['security_group']['id'],
+                          name="default")
+
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fde898f-ce88-493b-adc9-4e4692879fc5')
     def test_create_duplicate_security_group_rule_fails(self):
         # Create duplicate security group rule, it should fail.
@@ -201,7 +211,7 @@
             protocol='tcp', direction='ingress', ethertype=self.ethertype,
             port_range_min=min_port, port_range_max=max_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('be308db6-a7cf-4d5c-9baf-71bafd73f35e')
     def test_create_security_group_rule_with_non_existent_security_group(self):
         # Create security group rules with not existing security group.
@@ -217,7 +227,7 @@
     _ip_version = 6
     _project_network_cidr = CONF.network.project_network_v6_cidr
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7607439c-af73-499e-bf64-f687fd12a842')
     def test_create_security_group_rule_wrong_ip_prefix_version(self):
         group_create_body, _ = self._create_security_group()
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index d9599c4..01d7db2 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -13,8 +13,8 @@
 # under the License.
 
 from tempest.api.network import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -46,7 +46,7 @@
             msg = "subnet_allocation extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e9811')
     def test_create_list_show_update_delete_subnetpools(self):
         subnetpool_name = data_utils.rand_name('subnetpools')
diff --git a/tempest/api/network/test_versions.py b/tempest/api/network/test_versions.py
index 4f6d5ac..2f01e50 100644
--- a/tempest/api/network/test_versions.py
+++ b/tempest/api/network/test_versions.py
@@ -14,11 +14,10 @@
 
 from tempest.api.network import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class NetworksApiDiscovery(base.BaseNetworkTest):
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cac8a836-c2e0-4304-b556-cd299c7281d1')
     def test_api_version_resources(self):
         """Test that GET / returns expected resources.
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 642c1ac..c075b92 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -16,8 +16,8 @@
 import time
 
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
@@ -80,6 +80,7 @@
     def setup_clients(cls):
         super(BaseObjectTest, cls).setup_clients()
         cls.object_client = cls.os.object_client
+        cls.bulk_client = cls.os.bulk_client
         cls.container_client = cls.os.container_client
         cls.account_client = cls.os.account_client
         cls.capabilities_client = cls.os.capabilities_client
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index d882731..0a72d75 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -56,11 +56,10 @@
 
     def _upload_archive(self, filepath):
         # upload an archived file
-        params = {'extract-archive': 'tar'}
         with open(filepath) as fh:
             mydata = fh.read()
-            resp, body = self.account_client.create_account(data=mydata,
-                                                            params=params)
+            resp, body = self.bulk_client.upload_archive(
+                upload_path='', data=mydata, archive_file_format='tar')
         return resp, body
 
     def _check_contents_deleted(self, container_name):
@@ -113,9 +112,7 @@
         self._upload_archive(filepath)
 
         data = '%s/%s\n%s' % (container_name, object_name, container_name)
-        params = {'bulk-delete': ''}
-        resp, body = self.account_client.delete_account(data=data,
-                                                        params=params)
+        resp, body = self.bulk_client.delete_bulk_data(data=data)
 
         # When deleting multiple files using the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
@@ -140,10 +137,8 @@
         self._upload_archive(filepath)
 
         data = '%s/%s\n%s' % (container_name, object_name, container_name)
-        params = {'bulk-delete': ''}
 
-        resp, body = self.account_client.create_account_metadata(
-            {}, data=data, params=params)
+        resp, body = self.bulk_client.delete_bulk_data_with_post(data=data)
 
         # When deleting multiple files using the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index cbf0d4b..9077f88 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -13,8 +13,8 @@
 # under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -76,7 +76,7 @@
         cls.delete_containers()
         super(AccountQuotasTest, cls).resource_cleanup()
 
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     @decorators.idempotent_id('a22ef352-a342-4587-8f47-3bbdb5b039c4')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_upload_valid_object(self):
@@ -87,7 +87,7 @@
 
         self.assertHeaders(resp, 'Object', 'PUT')
 
-    @test.attr(type=["smoke"])
+    @decorators.attr(type=["smoke"])
     @decorators.idempotent_id('63f51f9f-5f1d-4fc6-b5be-d454d70949d6')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_admin_modify_quota(self):
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 2e85a43..f955d34 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -75,18 +75,20 @@
         cls.delete_containers()
         super(AccountQuotasNegativeTest, cls).resource_cleanup()
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('d1dc5076-555e-4e6d-9697-28f1fe976324')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_user_modify_quota(self):
         """Test that a user cannot modify or remove a quota on its account."""
 
         # Not able to remove quota
-        self.assertRaises(lib_exc.Forbidden,
-                          self.account_client.create_account_metadata,
-                          {"Quota-Bytes": ""})
+        self.assertRaises(
+            lib_exc.Forbidden,
+            self.account_client.create_update_or_delete_account_metadata,
+            create_update_metadata={"Quota-Bytes": ""})
 
         # Not able to modify quota
-        self.assertRaises(lib_exc.Forbidden,
-                          self.account_client.create_account_metadata,
-                          {"Quota-Bytes": "100"})
+        self.assertRaises(
+            lib_exc.Forbidden,
+            self.account_client.create_update_or_delete_account_metadata,
+            create_update_metadata={"Quota-Bytes": "100"})
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index cf7dbe8..e54b6e7 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -20,10 +20,9 @@
 
 from tempest.api.object_storage import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -54,7 +53,7 @@
         cls.delete_containers()
         super(AccountTest, cls).resource_cleanup()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('3499406a-ae53-4f8c-b43a-133d4dc6fe3f')
     def test_list_containers(self):
         # list of all containers should not be empty
@@ -265,7 +264,7 @@
         self.assertEqual(sorted(orig_container_list, reverse=True),
                          container_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4894c312-6056-4587-8d6f-86ffbf861f80')
     def test_list_account_metadata(self):
         # list all account metadata
@@ -273,13 +272,15 @@
         # set metadata to account
         metadata = {'test-account-meta1': 'Meta1',
                     'test-account-meta2': 'Meta2'}
-        resp, _ = self.account_client.create_account_metadata(metadata)
+        resp, _ = self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
 
         resp, _ = self.account_client.list_account_metadata()
         self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertIn('x-account-meta-test-account-meta1', resp)
         self.assertIn('x-account-meta-test-account-meta2', resp)
-        self.account_client.delete_account_metadata(metadata)
+        self.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=metadata)
 
     @decorators.idempotent_id('b904c2e3-24c2-4dba-ad7d-04e90a761be5')
     def test_list_no_account_metadata(self):
@@ -292,7 +293,8 @@
     def test_update_account_metadata_with_create_metadata(self):
         # add metadata to account
         metadata = {'test-account-meta1': 'Meta1'}
-        resp, _ = self.account_client.create_account_metadata(metadata)
+        resp, _ = self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, body = self.account_client.list_account_metadata()
@@ -300,14 +302,17 @@
         self.assertEqual(resp['x-account-meta-test-account-meta1'],
                          metadata['test-account-meta1'])
 
-        self.account_client.delete_account_metadata(metadata)
+        self.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=metadata)
 
     @decorators.idempotent_id('9f60348d-c46f-4465-ae06-d51dbd470953')
     def test_update_account_metadata_with_delete_metadata(self):
         # delete metadata from account
         metadata = {'test-account-meta1': 'Meta1'}
-        self.account_client.create_account_metadata(metadata)
-        resp, _ = self.account_client.delete_account_metadata(metadata)
+        self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
+        resp, _ = self.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=metadata)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -318,7 +323,8 @@
         # if the value of metadata is not set, the metadata is not
         # registered at a server
         metadata = {'test-account-meta1': ''}
-        resp, _ = self.account_client.create_account_metadata(metadata)
+        resp, _ = self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -329,9 +335,11 @@
         # Although the value of metadata is not set, the feature of
         # deleting metadata is valid
         metadata_1 = {'test-account-meta1': 'Meta1'}
-        self.account_client.create_account_metadata(metadata_1)
+        self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata_1)
         metadata_2 = {'test-account-meta1': ''}
-        resp, _ = self.account_client.delete_account_metadata(metadata_2)
+        resp, _ = self.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=metadata_2)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -341,11 +349,13 @@
     def test_update_account_metadata_with_create_and_delete_metadata(self):
         # Send a request adding and deleting metadata requests simultaneously
         metadata_1 = {'test-account-meta1': 'Meta1'}
-        self.account_client.create_account_metadata(metadata_1)
+        self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata_1)
         metadata_2 = {'test-account-meta2': 'Meta2'}
-        resp, body = self.account_client.create_and_delete_account_metadata(
-            metadata_2,
-            metadata_1)
+        resp, body = (
+            self.account_client.create_update_or_delete_account_metadata(
+                create_update_metadata=metadata_2,
+                delete_metadata=metadata_1))
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -354,4 +364,5 @@
         self.assertEqual(resp['x-account-meta-test-account-meta2'],
                          metadata_2['test-account-meta2'])
 
-        self.account_client.delete_account_metadata(metadata_2)
+        self.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=metadata_2)
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index d46534b..e98a4f5 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -16,7 +16,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -32,7 +31,7 @@
         cls.os = cls.os_roles_operator
         cls.os_operator = cls.os_roles_operator_alt
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
     def test_list_containers_with_non_authorized_user(self):
         # list containers using non-authorized user
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index aa4e92c..d4e5ec5 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index d5d5ea7..9c9d821 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -13,11 +13,10 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 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
 
@@ -47,7 +46,7 @@
         self.delete_containers([self.container_name])
         super(ObjectACLsNegativeTest, self).tearDown()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af587587-0c24-4e15-9822-8352ce711013')
     def test_write_object_without_using_creds(self):
         # trying to create object with empty headers
@@ -61,7 +60,7 @@
                           self.object_client.create_object,
                           self.container_name, object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af85af0b-a025-4e72-a90e-121babf55720')
     def test_delete_object_without_using_creds(self):
         # create object
@@ -78,7 +77,7 @@
                           self.object_client.delete_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('63d84e37-55a6-42e2-9e5f-276e60e26a00')
     def test_write_object_with_non_authorized_user(self):
         # attempt to upload another file using non-authorized user
@@ -93,7 +92,7 @@
                           self.object_client.create_object,
                           self.container_name, object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('abf63359-be52-4feb-87dd-447689fc77fd')
     def test_read_object_with_non_authorized_user(self):
         # attempt to read object using non-authorized user
@@ -111,7 +110,7 @@
                           self.object_client.get_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7343ac3d-cfed-4198-9bb0-00149741a492')
     def test_delete_object_with_non_authorized_user(self):
         # attempt to delete object using non-authorized user
@@ -129,7 +128,7 @@
                           self.object_client.delete_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9ed01334-01e9-41ea-87ea-e6f465582823')
     def test_read_object_without_rights(self):
         # attempt to read object using non-authorized user
@@ -153,7 +152,7 @@
                           self.object_client.get_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a3a585a7-d8cf-4b65-a1a0-edc2b1204f85')
     def test_write_object_without_rights(self):
         # attempt to write object using non-authorized user
@@ -174,7 +173,7 @@
                           self.container_name,
                           object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8ba512ad-aa6e-444e-b882-2906a0ea2052')
     def test_write_object_without_write_rights(self):
         # attempt to write object using non-authorized user
@@ -199,7 +198,7 @@
                           self.container_name,
                           object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b4e366f8-f185-47ab-b789-df4416f9ecdb')
     def test_delete_object_without_write_rights(self):
         # attempt to delete object using non-authorized user
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index d3b456a..8266341 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+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
@@ -50,7 +50,7 @@
 
     @decorators.idempotent_id('9a0fb034-86af-4df0-86fa-f8bd7db21ae0')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_valid_object(self):
         """Attempts to uploads an object smaller than the bytes quota."""
         object_name = data_utils.rand_name(name="TestObject")
@@ -67,7 +67,7 @@
 
     @decorators.idempotent_id('22eeeb2b-3668-4160-baef-44790f65a5a0')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_large_object(self):
         """Attempts to upload an object larger than the bytes quota."""
         object_name = data_utils.rand_name(name="TestObject")
@@ -84,7 +84,7 @@
 
     @decorators.idempotent_id('3a387039-697a-44fc-a9c0-935de31f426b')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_too_many_objects(self):
         """Attempts to upload many objects that exceeds the count limit."""
         for _ in range(QUOTA_COUNT):
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 2e617f3..2b5692d 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -14,9 +14,8 @@
 #    under the License.
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class ContainerTest(base.BaseObjectTest):
@@ -24,7 +23,7 @@
         self.delete_containers()
         super(ContainerTest, self).tearDown()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('92139d73-7819-4db1-85f8-3f2f22a8d91f')
     def test_create_container(self):
         container_name = data_utils.rand_name(name='TestContainer')
@@ -124,7 +123,7 @@
         resp, _ = self.container_client.delete_container(container_name)
         self.assertHeaders(resp, 'Container', 'DELETE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('312ff6bd-5290-497f-bda1-7c5fec6697ab')
     def test_list_container_contents(self):
         # get container contents list
@@ -271,7 +270,7 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual([object_name], object_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('96e68f0e-19ec-4aa2-86f3-adc6a45e14dd')
     def test_list_container_metadata(self):
         # List container metadata
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index ebbb84e..a8d70c5 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.py
@@ -16,11 +16,10 @@
 import testtools
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -36,7 +35,7 @@
             _, body = cls.capabilities_client.list_capabilities()
             cls.constraints = body['swift']
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('30686921-4bed-4764-a038-40d741ed4e78')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -52,7 +51,7 @@
         self.assertIn('Container name length of ' + str(max_length + 1) +
                       ' longer than ' + str(max_length), str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('41e645bf-2e68-4f84-bf7b-c71aa5cd76ce')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -69,7 +68,7 @@
                                container_name, metadata=metadata)
         self.assertIn('Metadata name too long', str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('81e36922-326b-4b7c-8155-3bbceecd7a82')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -86,7 +85,7 @@
                                container_name, metadata=metadata)
         self.assertIn('Metadata value longer than ' + str(max_length), str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('ac666539-d566-4f02-8ceb-58e968dfb732')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -106,7 +105,7 @@
         self.assertIn('Too many metadata items; max ' + str(max_count),
                       str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('1a95ab2e-b712-4a98-8a4d-8ce21b7557d6')
     def test_get_metadata_headers_with_invalid_container_name(self):
         # Attempts to retrieve metadata headers with an invalid
@@ -115,7 +114,7 @@
                           self.container_client.list_container_metadata,
                           'invalid_container_name')
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('125a24fa-90a7-4cfc-b604-44e49d788390')
     def test_update_metadata_with_nonexistent_container_name(self):
         # Attempts to update metadata using a nonexistent container name.
@@ -125,7 +124,7 @@
                           self.container_client.update_container_metadata,
                           'nonexistent_container_name', metadata)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('65387dbf-a0e2-4aac-9ddc-16eb3f1f69ba')
     def test_delete_with_nonexistent_container_name(self):
         # Attempts to delete metadata using a nonexistent container name.
@@ -135,7 +134,7 @@
                           self.container_client.delete_container_metadata,
                           'nonexistent_container_name', metadata)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('14331d21-1e81-420a-beea-19cb5e5207f5')
     def test_list_all_container_objects_with_nonexistent_container(self):
         # Attempts to get a listing of all objects on a container
@@ -145,7 +144,7 @@
                           self.container_client.list_container_contents,
                           'nonexistent_container_name', params)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('86b2ab08-92d5-493d-acd2-85f0c848819e')
     def test_list_all_container_objects_on_deleted_container(self):
         # Attempts to get a listing of all objects on a container
@@ -159,7 +158,7 @@
                           self.container_client.list_container_contents,
                           container_name, params)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('42da116e-1e8c-4c96-9e06-2f13884ed2b1')
     def test_delete_non_empty_container(self):
         # create a container and an object within it
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index a280248..9e01c26 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -14,7 +14,7 @@
 
 from tempest.api.object_storage import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
+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
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 63fb93d..3c11a51 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -18,12 +18,10 @@
 from six.moves.urllib import parse as urlparse
 import testtools
 
-
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -129,7 +127,7 @@
                 resp, object_content = obj_client.get_object(cont, obj_name)
                 self.assertEqual(object_content, obj_name[::-1].encode())
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.skip_because(bug='1317133')
     @decorators.idempotent_id('be008325-1bba-4925-b7dd-93b58f22ce9b')
     @testtools.skipIf(
diff --git a/tempest/api/object_storage/test_container_sync_middleware.py b/tempest/api/object_storage/test_container_sync_middleware.py
index df738b3..9eae138 100644
--- a/tempest/api/object_storage/test_container_sync_middleware.py
+++ b/tempest/api/object_storage/test_container_sync_middleware.py
@@ -37,7 +37,7 @@
         cls.key = 'sync_key'
         cls.cluster_name = CONF.object_storage.cluster_name
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('ea4645a1-d147-4976-82f7-e5a7a3065f80')
     @test.requires_ext(extension='container_sync', service='object')
     def test_container_synchronization(self):
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 2829ac7..3a2233a 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -19,7 +19,7 @@
 from six.moves.urllib import parse as urlparse
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -37,7 +37,8 @@
 
         cls.key = 'Meta'
         cls.metadata = {'Temp-URL-Key': cls.key}
-        cls.account_client.create_account_metadata(metadata=cls.metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=cls.metadata)
 
     def setUp(self):
         super(ObjectFormPostTest, self).setUp()
@@ -53,7 +54,8 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.account_client.delete_account_metadata(metadata=cls.metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=cls.metadata)
         cls.delete_containers()
         super(ObjectFormPostTest, cls).resource_cleanup()
 
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index 52b3978..c56d91a 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -19,7 +19,7 @@
 from six.moves.urllib import parse as urlparse
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+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
@@ -38,7 +38,8 @@
 
         cls.key = 'Meta'
         cls.metadata = {'Temp-URL-Key': cls.key}
-        cls.account_client.create_account_metadata(metadata=cls.metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=cls.metadata)
 
     def setUp(self):
         super(ObjectFormPostNegativeTest, self).setUp()
@@ -54,7 +55,8 @@
 
     @classmethod
     def resource_cleanup(cls):
-        cls.account_client.delete_account_metadata(metadata=cls.metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=cls.metadata)
         cls.delete_containers()
         super(ObjectFormPostNegativeTest, cls).resource_cleanup()
 
@@ -108,7 +110,7 @@
 
     @decorators.idempotent_id('d3fb3c4d-e627-48ce-9379-a1631f21336d')
     @test.requires_ext(extension='formpost', service='object')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_post_object_using_form_expired(self):
         body, content_type = self.get_multipart_form(expires=1)
         time.sleep(2)
@@ -125,7 +127,7 @@
 
     @decorators.idempotent_id('b277257f-113c-4499-b8d1-5fead79f7360')
     @test.requires_ext(extension='formpost', service='object')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_post_object_using_form_invalid_signature(self):
         self.key = "Wrong"
         body, content_type = self.get_multipart_form()
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 58fd822..21ea6ae 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -21,10 +21,9 @@
 
 from tempest.api.object_storage import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -75,7 +74,7 @@
             for meta_key in not_in_meta:
                 self.assertNotIn('x-object-meta-' + meta_key, resp)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5b4ce26f-3545-46c9-a2ba-5754358a4c62')
     def test_create_object(self):
         # create object
@@ -319,7 +318,7 @@
                                                    object_name)
         self.assertHeaders(resp, 'Object', 'DELETE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7a94c25d-66e6-434c-9c38-97d4e2c29945')
     def test_update_object_metadata(self):
         # update object metadata
@@ -460,7 +459,7 @@
             object_name)
         self.assertNotIn('x-object-meta-test-meta', resp)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('9a447cf6-de06-48de-8226-a8c6ed31caf2')
     def test_list_object_metadata(self):
         # get object metadata
@@ -530,7 +529,7 @@
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s' % (self.container_name, object_name))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('02610ba7-86b7-4272-9ed8-aa8d417cb3cd')
     def test_get_object(self):
         # retrieve object's data (in response body)
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 8ed9bf8..085ad13 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -18,7 +18,7 @@
 
 from tempest.api.object_storage import base
 from tempest.common import custom_matchers
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest import test
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 5e3c9f7..4b506f8 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -19,7 +19,7 @@
 from six.moves.urllib import parse as urlparse
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -37,7 +37,8 @@
         cls.metadatas = []
         metadata = {'Temp-URL-Key': cls.key}
         cls.metadatas.append(metadata)
-        cls.account_client.create_account_metadata(metadata=metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
 
         # create an object
         cls.object_name, cls.content = cls.create_object(cls.container_name)
@@ -45,8 +46,8 @@
     @classmethod
     def resource_cleanup(cls):
         for metadata in cls.metadatas:
-            cls.account_client.delete_account_metadata(
-                metadata=metadata)
+            cls.account_client.create_update_or_delete_account_metadata(
+                delete_metadata=metadata)
 
         cls.delete_containers()
 
@@ -110,7 +111,8 @@
     def test_get_object_using_temp_url_key_2(self):
         key2 = 'Meta2-'
         metadata = {'Temp-URL-Key-2': key2}
-        self.account_client.create_account_metadata(metadata=metadata)
+        self.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=metadata)
         self.metadatas.append(metadata)
 
         # make sure the metadata has been set
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 d0e0935..f4d63fd 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -19,7 +19,7 @@
 from six.moves.urllib import parse as urlparse
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
+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
@@ -39,14 +39,15 @@
         # update account metadata
         cls.key = 'Meta'
         cls.metadata = {'Temp-URL-Key': cls.key}
-        cls.account_client.create_account_metadata(metadata=cls.metadata)
+        cls.account_client.create_update_or_delete_account_metadata(
+            create_update_metadata=cls.metadata)
         cls.account_client_metadata, _ = \
             cls.account_client.list_account_metadata()
 
     @classmethod
     def resource_cleanup(cls):
-        resp, _ = cls.account_client.delete_account_metadata(
-            metadata=cls.metadata)
+        resp, _ = cls.account_client.create_update_or_delete_account_metadata(
+            delete_metadata=cls.metadata)
 
         cls.delete_containers()
 
@@ -91,7 +92,7 @@
 
         return url
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5a583aca-c804-41ba-9d9a-e7be132bdf0b')
     @test.requires_ext(extension='tempurl', service='object')
     def test_get_object_after_expiration_time(self):
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 1b12dac..dc0d179 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -16,8 +16,8 @@
 import testtools
 
 from tempest.api.object_storage import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 3701b55..8d3d344 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -14,8 +14,8 @@
 
 import yaml
 
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 import tempest.test
 
@@ -47,13 +47,8 @@
         cls.servers_client = cls.os.servers_client
         cls.keypairs_client = cls.os.keypairs_client
         cls.networks_client = cls.os.networks_client
-        cls.volumes_client = cls.os.volumes_client
         cls.images_v2_client = cls.os.image_client_v2
-
-        if CONF.volume_feature_enabled.api_v2:
-            cls.volumes_client = cls.os.volumes_v2_client
-        else:
-            cls.volumes_client = cls.os.volumes_client
+        cls.volumes_client = cls.os.volumes_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py
index 0a9b3e5..c8a9aa7 100644
--- a/tempest/api/orchestration/stacks/test_environment.py
+++ b/tempest/api/orchestration/stacks/test_environment.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index b079435..9c9d4f9 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -11,8 +11,8 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
 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
 
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 0154658..6faca71 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -14,8 +14,8 @@
 from oslo_log import log as logging
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
 from tempest import test
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index f106349..6b9c88b 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -11,8 +11,8 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 4d1db6d..a51648f 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/orchestration/stacks/test_resource_types.py b/tempest/api/orchestration/stacks/test_resource_types.py
index 63376d5..6d0707e 100644
--- a/tempest/api/orchestration/stacks/test_resource_types.py
+++ b/tempest/api/orchestration/stacks/test_resource_types.py
@@ -12,12 +12,11 @@
 
 from tempest.api.orchestration import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class ResourceTypesTest(base.BaseOrchestrationTest):
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7123d082-3577-4a30-8f00-f805327c4ffd')
     def test_resource_type_list(self):
         """Verify it is possible to list resource types."""
@@ -25,7 +24,7 @@
         self.assertIsInstance(resource_types, list)
         self.assertIn('OS::Nova::Server', resource_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0e85a483-828b-4a28-a0e3-f0a21809192b')
     def test_resource_type_show(self):
         """Verify it is possible to get schema about resource types."""
@@ -38,7 +37,7 @@
                                        'attributes', 'resource_type')
             self.assertEqual(resource_type, type_schema['resource_type'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8401821d-65fe-4d43-9fa3-57d5ce3a35c7')
     def test_resource_type_template(self):
         """Verify it is possible to get template about resource types."""
diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index 89b10cc..8192999 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.py
@@ -11,10 +11,9 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
+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
 
 
 class TestSoftwareConfig(base.BaseOrchestrationTest):
@@ -75,7 +74,7 @@
         self.assertRaises(
             lib_exc.NotFound, self.client.show_software_config, config_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('136162ed-9445-4b9c-b7fc-306af8b5da99')
     def test_get_software_config(self):
         """Testing software config get."""
@@ -83,7 +82,7 @@
             api_config = self.client.show_software_config(conf['id'])
             self._validate_config(conf, api_config)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1275c835-c967-4a2c-8d5d-ad533447ed91')
     def test_get_deployment_list(self):
         """Getting a list of all deployments"""
@@ -92,7 +91,7 @@
                       deploy_list['software_deployments']]
         self.assertIn(self.deployment_id, deploy_ids)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('fe7cd9f9-54b1-429c-a3b7-7df8451db913')
     def test_get_deployment_metadata(self):
         """Testing deployment metadata get"""
@@ -110,7 +109,7 @@
         self.assertEqual(config_id,
                          deployment['software_deployment']['config_id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f29d21f3-ed75-47cf-8cdc-ef1bdeb4c674')
     def test_software_deployment_create_validate(self):
         """Testing software deployment was created as expected."""
@@ -123,7 +122,7 @@
         self._validate_deployment(self.action, self.status,
                                   self.status_reason, self.configs[0]['id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2ac43ab3-34f2-415d-be2e-eabb4d14ee32')
     def test_software_deployment_update_no_metadata_change(self):
         """Testing software deployment update without metadata change."""
@@ -149,7 +148,7 @@
                 metadata['metadata'][0][key],
                 test_metadata['metadata'][0][key])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('92c48944-d79d-4595-a840-8e1a581c1a72')
     def test_software_deployment_update_with_metadata_change(self):
         """Testing software deployment update with metadata change."""
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 7b5f161..dc1bb4f 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -11,21 +11,20 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class StacksTestJSON(base.BaseOrchestrationTest):
     empty_template = "HeatTemplateFormatVersion: '2012-12-12'\n"
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('d35d628c-07f6-4674-85a1-74db9919e986')
     def test_stack_list_responds(self):
         stacks = self.client.list_stacks()['stacks']
         self.assertIsInstance(stacks, list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('10498bd5-a83e-4b62-a817-ce24afe938fe')
     def test_stack_crud_no_resources(self):
         stack_name = data_utils.rand_name('heat')
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index 505abe7..97fdac4 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -13,8 +13,8 @@
 # under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py
index 21548a0..4ff951d 100644
--- a/tempest/api/orchestration/stacks/test_templates.py
+++ b/tempest/api/orchestration/stacks/test_templates.py
@@ -11,7 +11,7 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 
diff --git a/tempest/api/orchestration/stacks/test_templates_negative.py b/tempest/api/orchestration/stacks/test_templates_negative.py
index a90abe2..eb93d95 100644
--- a/tempest/api/orchestration/stacks/test_templates_negative.py
+++ b/tempest/api/orchestration/stacks/test_templates_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.orchestration import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TemplateYAMLNegativeTestJSON(base.BaseOrchestrationTest):
@@ -35,7 +34,7 @@
         super(TemplateYAMLNegativeTestJSON, cls).resource_setup()
         cls.parameters = {}
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5586cbca-ddc4-4152-9db8-fa1ce5fc1876')
     def test_validate_template_url(self):
         """Validating template passing url to it."""
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index d34eb89..7ddf7af 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -11,8 +11,8 @@
 #    under the License.
 
 from tempest.api.orchestration import base
-from tempest.common.utils import data_utils
 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
@@ -35,18 +35,10 @@
         self.assertEqual('available', volume.get('status'))
         self.assertEqual(CONF.volume.volume_size, volume.get('size'))
 
-        # Some volume properties have been renamed with Cinder v2
-        if CONF.volume_feature_enabled.api_v2:
-            description_field = 'description'
-            name_field = 'name'
-        else:
-            description_field = 'display_description'
-            name_field = 'display_name'
-
         self.assertEqual(template['resources']['volume']['properties'][
-            'description'], volume.get(description_field))
+            'description'], volume.get('description'))
         self.assertEqual(template['resources']['volume']['properties'][
-            'name'], volume.get(name_field))
+            'name'], volume.get('name'))
 
     def _outputs_verify(self, stack_identifier, template):
         self.assertEqual('available',
diff --git a/tempest/api/volume/admin/v2/test_backends_capabilities.py b/tempest/api/volume/admin/test_backends_capabilities.py
similarity index 94%
rename from tempest/api/volume/admin/v2/test_backends_capabilities.py
rename to tempest/api/volume/admin/test_backends_capabilities.py
index 1060f2b..607fc43 100644
--- a/tempest/api/volume/admin/v2/test_backends_capabilities.py
+++ b/tempest/api/volume/admin/test_backends_capabilities.py
@@ -19,7 +19,7 @@
 from tempest.lib import decorators
 
 
-class BackendsCapabilitiesAdminV2TestsJSON(base.BaseVolumeAdminTest):
+class BackendsCapabilitiesAdminTestsJSON(base.BaseVolumeAdminTest):
 
     CAPABILITIES = ('namespace',
                     'vendor_name',
@@ -34,7 +34,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(BackendsCapabilitiesAdminV2TestsJSON, cls).resource_setup()
+        super(BackendsCapabilitiesAdminTestsJSON, cls).resource_setup()
         # Get host list, formation: host@backend-name
         cls.hosts = [
             pool['name'] for pool in
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index c3e904a..2db8010 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -12,31 +12,30 @@
 
 import six
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
 
 
-class VolumeMultiBackendV2Test(base.BaseVolumeAdminTest):
+class VolumeMultiBackendTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeMultiBackendV2Test, cls).skip_checks()
+        super(VolumeMultiBackendTest, cls).skip_checks()
 
         if not CONF.volume_feature_enabled.multi_backend:
             raise cls.skipException("Cinder multi-backend feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeMultiBackendV2Test, cls).resource_setup()
+        super(VolumeMultiBackendTest, cls).resource_setup()
 
         # read backend name from a list .
         backend_names = set(CONF.volume.backend_names)
 
-        cls.name_field = cls.special_fields['name_field']
         cls.volume_id_list_with_prefix = []
         cls.volume_id_list_without_prefix = []
 
@@ -65,7 +64,7 @@
         cls.create_volume_type(name=type_name,
                                extra_specs=extra_specs)
 
-        params = {cls.name_field: vol_name, 'volume_type': type_name,
+        params = {'name': vol_name, 'volume_type': type_name,
                   'size': CONF.volume.volume_size}
         cls.volume = cls.admin_volume_client.create_volume(
             **params)['volume']
@@ -90,7 +89,7 @@
             cls.admin_volume_client.delete_volume(volume_id)
             cls.admin_volume_client.wait_for_resource_deletion(volume_id)
 
-        super(VolumeMultiBackendV2Test, cls).resource_cleanup()
+        super(VolumeMultiBackendTest, cls).resource_cleanup()
 
     @decorators.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
     def test_backend_name_reporting(self):
@@ -140,7 +139,3 @@
         msg = ("volumes %s were created in the same backend" % ", "
                .join(volume_hosts))
         six.assertCountEqual(self, volume_hosts, set(volume_hosts), msg)
-
-
-class VolumeMultiBackendV1Test(VolumeMultiBackendV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_qos.py b/tempest/api/volume/admin/test_qos.py
index e1cfb30..e31c0ef 100644
--- a/tempest/api/volume/admin/test_qos.py
+++ b/tempest/api/volume/admin/test_qos.py
@@ -13,21 +13,21 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils as utils
 from tempest.common import waiters
+from tempest.lib.common.utils import data_utils as utils
 from tempest.lib import decorators
 
 
-class QosSpecsV2TestJSON(base.BaseVolumeAdminTest):
+class QosSpecsTestJSON(base.BaseVolumeAdminTest):
     """Test the Cinder QoS-specs.
 
     Tests for  create, list, delete, show, associate,
-    disassociate, set/unset key V2 APIs.
+    disassociate, set/unset key APIs.
     """
 
     @classmethod
     def resource_setup(cls):
-        super(QosSpecsV2TestJSON, cls).resource_setup()
+        super(QosSpecsTestJSON, cls).resource_setup()
         # Create admin qos client
         # Create a test shared qos-specs for tests
         cls.qos_name = utils.rand_name(cls.__name__ + '-QoS')
@@ -157,7 +157,3 @@
         operation = 'disassociate-all'
         waiters.wait_for_qos_operations(self.admin_volume_qos_client,
                                         self.created_qos['id'], operation)
-
-
-class QosSpecsV1TestJSON(QosSpecsV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/v2/test_snapshot_manage.py b/tempest/api/volume/admin/test_snapshot_manage.py
similarity index 97%
rename from tempest/api/volume/admin/v2/test_snapshot_manage.py
rename to tempest/api/volume/admin/test_snapshot_manage.py
index e8bd477..a2d5fb1 100644
--- a/tempest/api/volume/admin/v2/test_snapshot_manage.py
+++ b/tempest/api/volume/admin/test_snapshot_manage.py
@@ -23,7 +23,7 @@
 CONF = config.CONF
 
 
-class SnapshotManageAdminV2Test(base.BaseVolumeAdminTest):
+class SnapshotManageAdminTest(base.BaseVolumeAdminTest):
     """Unmanage & manage snapshots
 
      This feature provides the ability to import/export volume snapshot
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index e1c9492..471f39a 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -20,16 +20,16 @@
 CONF = config.CONF
 
 
-class SnapshotsActionsV2Test(base.BaseVolumeAdminTest):
+class SnapshotsActionsTest(base.BaseVolumeAdminTest):
     @classmethod
     def skip_checks(cls):
-        super(SnapshotsActionsV2Test, cls).skip_checks()
+        super(SnapshotsActionsTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(SnapshotsActionsV2Test, cls).resource_setup()
+        super(SnapshotsActionsTest, cls).resource_setup()
 
         # Create a test shared volume for tests
         cls.volume = cls.create_volume()
@@ -43,7 +43,7 @@
         snapshot_id = self.snapshot['id']
         self.admin_snapshots_client.reset_snapshot_status(snapshot_id,
                                                           status)
-        super(SnapshotsActionsV2Test, self).tearDown()
+        super(SnapshotsActionsTest, self).tearDown()
 
     def _create_reset_and_force_delete_temp_snapshot(self, status=None):
         # Create snapshot, reset snapshot status,
@@ -107,7 +107,3 @@
     def test_snapshot_force_delete_when_snapshot_is_error_deleting(self):
         # test force delete when status of snapshot is error_deleting
         self._create_reset_and_force_delete_temp_snapshot('error_deleting')
-
-
-class SnapshotsActionsV1Test(SnapshotsActionsV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/test_user_messages.py
similarity index 95%
rename from tempest/api/volume/admin/v3/test_user_messages.py
rename to tempest/api/volume/admin/test_user_messages.py
index ed85d4d..20c3538 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/test_user_messages.py
@@ -13,9 +13,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api.volume.v3 import base
-from tempest.common.utils import data_utils
+from tempest.api.volume import base
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
@@ -33,7 +33,8 @@
     'links']
 
 
-class UserMessagesTest(base.VolumesV3AdminTest):
+class UserMessagesTest(base.BaseVolumeAdminTest):
+    _api_version = 3
     min_microversion = '3.3'
     max_microversion = 'latest'
 
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index 73c927a..04d6cf9 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -17,14 +17,10 @@
 from tempest.lib import decorators
 
 
-class VolumeHostsAdminV2TestsJSON(base.BaseVolumeAdminTest):
+class VolumeHostsAdminTestsJSON(base.BaseVolumeAdminTest):
 
     @decorators.idempotent_id('d5f3efa2-6684-4190-9ced-1c2f526352ad')
     def test_list_hosts(self):
         hosts = self.admin_hosts_client.list_hosts()['hosts']
         self.assertGreaterEqual(len(hosts), 2, "No. of hosts are < 2,"
                                 "response of list hosts is: % s" % hosts)
-
-
-class VolumeHostsAdminV1TestsJSON(VolumeHostsAdminV2TestsJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_manage.py b/tempest/api/volume/admin/test_volume_manage.py
new file mode 100644
index 0000000..a039085
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_manage.py
@@ -0,0 +1,81 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# 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.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+CONF = config.CONF
+
+
+class VolumeManageAdminTest(base.BaseVolumeAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeManageAdminTest, cls).skip_checks()
+
+        if not CONF.volume_feature_enabled.manage_volume:
+            raise cls.skipException("Manage volume tests are disabled")
+
+        if len(CONF.volume.manage_volume_ref) != 2:
+            raise cls.skipException("Manage volume ref is not correctly "
+                                    "configured")
+
+    @decorators.idempotent_id('70076c71-0ce1-4208-a8ff-36a66e65cc1e')
+    def test_unmanage_manage_volume(self):
+        # Create original volume
+        org_vol_id = self.create_volume()['id']
+        org_vol_info = self.admin_volume_client.show_volume(
+            org_vol_id)['volume']
+
+        # Unmanage the original volume
+        self.admin_volume_client.unmanage_volume(org_vol_id)
+        self.admin_volume_client.wait_for_resource_deletion(org_vol_id)
+
+        # Verify the original volume does not exist in volume list
+        params = {'all_tenants': 1}
+        all_tenants_volumes = self.admin_volume_client.list_volumes(
+            detail=True, params=params)['volumes']
+        self.assertNotIn(org_vol_id, [v['id'] for v in all_tenants_volumes])
+
+        # Manage volume
+        new_vol_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume')
+        new_vol_ref = {
+            'name': new_vol_name,
+            'host': org_vol_info['os-vol-host-attr:host'],
+            'ref': {CONF.volume.manage_volume_ref[0]:
+                    CONF.volume.manage_volume_ref[1] % org_vol_id},
+            'volume_type': org_vol_info['volume_type'],
+            'availability_zone': org_vol_info['availability_zone']}
+        new_vol_id = self.admin_volume_manage_client.manage_volume(
+            **new_vol_ref)['volume']['id']
+        self.addCleanup(self.delete_volume,
+                        self.admin_volume_client, new_vol_id)
+        waiters.wait_for_volume_resource_status(self.admin_volume_client,
+                                                new_vol_id, 'available')
+
+        # Compare the managed volume with the original
+        new_vol_info = self.admin_volume_client.show_volume(
+            new_vol_id)['volume']
+        self.assertNotIn(new_vol_id, [org_vol_id])
+        self.assertEqual(new_vol_info['name'], new_vol_name)
+        for key in ['size',
+                    'volume_type',
+                    'availability_zone',
+                    'os-vol-host-attr:host']:
+            self.assertEqual(new_vol_info[key], org_vol_info[key])
diff --git a/tempest/api/volume/admin/v2/test_volume_pools.py b/tempest/api/volume/admin/test_volume_pools.py
similarity index 61%
rename from tempest/api/volume/admin/v2/test_volume_pools.py
rename to tempest/api/volume/admin/test_volume_pools.py
index 91d092d..60a3bda 100644
--- a/tempest/api/volume/admin/v2/test_volume_pools.py
+++ b/tempest/api/volume/admin/test_volume_pools.py
@@ -14,29 +14,26 @@
 #    under the License.
 
 from tempest.api.volume import base
+from tempest import config
 from tempest.lib import decorators
 
+CONF = config.CONF
 
-class VolumePoolsAdminV2TestsJSON(base.BaseVolumeAdminTest):
 
-    @classmethod
-    def resource_setup(cls):
-        super(VolumePoolsAdminV2TestsJSON, cls).resource_setup()
-        # Create a test shared volume for tests
-        cls.volume = cls.create_volume()
-
-    def _assert_host_volume_in_pools(self, with_detail=False):
-        volume_info = self.admin_volume_client.show_volume(
-            self.volume['id'])['volume']
+class VolumePoolsAdminTestsJSON(base.BaseVolumeAdminTest):
+    def _assert_pools(self, with_detail=False):
         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])
+        self.assertIn('name', cinder_pools[0])
+        if with_detail:
+            self.assertIn(CONF.volume.vendor_name,
+                          [pool['capabilities']['vendor_name']
+                           for pool in cinder_pools])
 
     @decorators.idempotent_id('0248a46c-e226-4933-be10-ad6fca8227e7')
     def test_get_pools_without_details(self):
-        self._assert_host_volume_in_pools()
+        self._assert_pools()
 
     @decorators.idempotent_id('d4bb61f7-762d-4437-b8a4-5785759a0ced')
     def test_get_pools_with_details(self):
-        self._assert_host_volume_in_pools(with_detail=True)
+        self._assert_pools(with_detail=True)
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 83fca45..58ca92f 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -13,25 +13,31 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 QUOTA_KEYS = ['gigabytes', 'snapshots', 'volumes', 'backups']
 QUOTA_USAGE_KEYS = ['reserved', 'limit', 'in_use']
 
 
-class BaseVolumeQuotasAdminV2TestJSON(base.BaseVolumeAdminTest):
+class BaseVolumeQuotasAdminTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_credentials(cls):
-        super(BaseVolumeQuotasAdminV2TestJSON, cls).setup_credentials()
+        super(BaseVolumeQuotasAdminTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
         cls.alt_client = cls.os_alt.volumes_client
 
+    @classmethod
+    def setup_clients(cls):
+        super(BaseVolumeQuotasAdminTestJSON, cls).setup_clients()
+        cls.transfer_client = cls.os.volume_transfers_v2_client
+        cls.alt_transfer_client = cls.os_alt.volume_transfers_v2_client
+
     @decorators.idempotent_id('59eada70-403c-4cef-a2a3-a8ce2f1b07a0')
     def test_list_quotas(self):
         quotas = (self.admin_quotas_client.show_quota_set(self.demo_tenant_id)
@@ -136,13 +142,13 @@
             self.alt_client.tenant_id, params={'usage': True})['quota_set']
 
         # Creates a volume transfer
-        transfer = self.volumes_client.create_volume_transfer(
+        transfer = self.transfer_client.create_volume_transfer(
             volume_id=volume['id'])['transfer']
         transfer_id = transfer['id']
         auth_key = transfer['auth_key']
 
         # Accepts a volume transfer
-        self.alt_client.accept_volume_transfer(
+        self.alt_transfer_client.accept_volume_transfer(
             transfer_id, auth_key=auth_key)['transfer']
 
         # Verify volume transferred is available
@@ -169,7 +175,3 @@
         self.assertEqual(primary_quota['gigabytes']['in_use'] -
                          volume['size'],
                          new_primary_quota['gigabytes']['in_use'])
-
-
-class VolumeQuotasAdminV1TestJSON(BaseVolumeQuotasAdminV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 8170626..63f61e4 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -17,22 +17,21 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
 
-class BaseVolumeQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
+class BaseVolumeQuotasNegativeTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     @classmethod
     def setup_credentials(cls):
-        super(BaseVolumeQuotasNegativeV2TestJSON, cls).setup_credentials()
+        super(BaseVolumeQuotasNegativeTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
 
     @classmethod
     def resource_setup(cls):
-        super(BaseVolumeQuotasNegativeV2TestJSON, cls).resource_setup()
+        super(BaseVolumeQuotasNegativeTestJSON, cls).resource_setup()
         cls.shared_quota_set = {'gigabytes': 2 * CONF.volume.volume_size,
                                 'volumes': 1}
 
@@ -46,14 +45,14 @@
         # they are created using utility wrapper methods.
         cls.volume = cls.create_volume()
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
     def test_quota_volumes(self):
         self.assertRaises(lib_exc.OverLimit,
                           self.volumes_client.create_volume,
                           size=CONF.volume.volume_size)
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
     def test_quota_volume_gigabytes(self):
         # NOTE(gfidente): quota set needs to be changed for this test
@@ -70,7 +69,3 @@
         self.assertRaises(lib_exc.OverLimit,
                           self.volumes_client.create_volume,
                           size=CONF.volume.volume_size)
-
-
-class VolumeQuotasNegativeV1TestJSON(BaseVolumeQuotasNegativeV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_retype_with_migration.py b/tempest/api/volume/admin/test_volume_retype_with_migration.py
index 4d32fdd..94d5299 100644
--- a/tempest/api/volume/admin/test_volume_retype_with_migration.py
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -23,11 +23,11 @@
 LOG = logging.getLogger(__name__)
 
 
-class VolumeRetypeWithMigrationV2Test(base.BaseVolumeAdminTest):
+class VolumeRetypeWithMigrationTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeRetypeWithMigrationV2Test, cls).skip_checks()
+        super(VolumeRetypeWithMigrationTest, cls).skip_checks()
 
         if not CONF.volume_feature_enabled.multi_backend:
             raise cls.skipException("Cinder multi-backend feature disabled.")
@@ -38,7 +38,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeRetypeWithMigrationV2Test, cls).resource_setup()
+        super(VolumeRetypeWithMigrationTest, cls).resource_setup()
         # read backend name from a list.
         backend_src = CONF.volume.backend_names[0]
         backend_dst = CONF.volume.backend_names[1]
@@ -73,7 +73,7 @@
                     fetched_vol['id'])
                 break
 
-        super(VolumeRetypeWithMigrationV2Test, cls).resource_cleanup()
+        super(VolumeRetypeWithMigrationTest, cls).resource_cleanup()
 
     @decorators.idempotent_id('a1a41f3f-9dad-493e-9f09-3ff197d477cd')
     def test_available_volume_retype_with_migration(self):
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 5dfdfce..4aab9c1 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -13,18 +13,14 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 from tempest.api.volume import base
-from tempest import config
 from tempest.lib import decorators
 
 
-CONF = config.CONF
-
-
 def _get_host(host):
     return host.split('@')[0]
 
 
-class VolumesServicesV2TestJSON(base.BaseVolumeAdminTest):
+class VolumesServicesTestJSON(base.BaseVolumeAdminTest):
     """Tests Volume Services API.
 
     volume service list requires admin privileges.
@@ -32,7 +28,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesServicesV2TestJSON, cls).resource_setup()
+        super(VolumesServicesTestJSON, cls).resource_setup()
         cls.services = (cls.admin_volume_services_client.list_services()
                         ['services'])
         # NOTE: Cinder service-list API returns the list contains
@@ -71,6 +67,20 @@
         # on order.
         self.assertEqual(sorted(s1), sorted(s2))
 
+    @decorators.idempotent_id('67ec6902-f91d-4dec-91fa-338523208bbc')
+    def test_get_service_by_volume_host_name(self):
+        volume_id = self.create_volume()['id']
+        volume = self.admin_volume_client.show_volume(volume_id)['volume']
+        hostname = _get_host(volume['os-vol-host-attr:host'])
+
+        services = (self.admin_volume_services_client.list_services(
+            host=hostname, binary='cinder-volume')['services'])
+
+        self.assertNotEqual(0, len(services),
+                            'cinder-volume not found on host %s' % hostname)
+        self.assertEqual(hostname, _get_host(services[0]['host']))
+        self.assertEqual('cinder-volume', services[0]['binary'])
+
     @decorators.idempotent_id('ffa6167c-4497-4944-a464-226bbdb53908')
     def test_get_service_by_service_and_host_name(self):
 
@@ -80,7 +90,3 @@
         self.assertNotEqual(0, len(services))
         self.assertEqual(self.host_name, _get_host(services[0]['host']))
         self.assertEqual(self.binary_name, services[0]['binary'])
-
-
-class VolumesServicesV1TestJSON(VolumesServicesV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
index 90a0022..fa8c7ab 100644
--- a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -17,28 +17,27 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
 
-class VolumeSnapshotQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
+class VolumeSnapshotQuotasNegativeTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).skip_checks()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException('Cinder volume snapshots are disabled')
 
     @classmethod
     def setup_credentials(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).setup_credentials()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).resource_setup()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).resource_setup()
         cls.default_volume_size = CONF.volume.volume_size
         cls.shared_quota_set = {'gigabytes': 3 * cls.default_volume_size,
                                 'volumes': 1, 'snapshots': 1}
@@ -54,14 +53,14 @@
         cls.volume = cls.create_volume()
         cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
     def test_quota_volume_snapshots(self):
         self.assertRaises(lib_exc.OverLimit,
                           self.snapshots_client.create_snapshot,
                           volume_id=self.volume['id'])
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('c99a1ca9-6cdf-498d-9fdf-25832babef27')
     def test_quota_volume_gigabytes_snapshots(self):
         self.addCleanup(self.admin_quotas_client.update_quota_set,
@@ -75,7 +74,3 @@
         self.assertRaises(lib_exc.OverLimit,
                           self.snapshots_client.create_snapshot,
                           volume_id=self.volume['id'])
-
-
-class VolumeSnapshotNegativeV1TestJSON(VolumeSnapshotQuotasNegativeV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/v2/test_volume_type_access.py b/tempest/api/volume/admin/test_volume_type_access.py
similarity index 96%
rename from tempest/api/volume/admin/v2/test_volume_type_access.py
rename to tempest/api/volume/admin/test_volume_type_access.py
index b60b33b..297ab6e 100644
--- a/tempest/api/volume/admin/v2/test_volume_type_access.py
+++ b/tempest/api/volume/admin/test_volume_type_access.py
@@ -23,13 +23,13 @@
 CONF = config.CONF
 
 
-class VolumeTypesAccessV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesAccessTest(base.BaseVolumeAdminTest):
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_clients(cls):
-        super(VolumeTypesAccessV2Test, cls).setup_clients()
+        super(VolumeTypesAccessTest, cls).setup_clients()
         cls.alt_client = cls.os_alt.volumes_client
 
     @decorators.idempotent_id('d4dd0027-835f-4554-a6e5-50903fb79184')
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 5d08416..ac717f8 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -14,15 +14,15 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
 
 
-class VolumeTypesV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesTest(base.BaseVolumeAdminTest):
 
     @decorators.idempotent_id('9d9b28e3-1b2e-4483-a2cc-24aa0ea1de54')
     def test_volume_type_list(self):
@@ -36,7 +36,6 @@
         # Create/update/get/delete volume with volume_type and extra spec.
         volume_types = list()
         vol_name = data_utils.rand_name(self.__class__.__name__ + '-volume')
-        name_field = self.special_fields['name_field']
         proto = CONF.volume.storage_protocol
         vendor = CONF.volume.vendor_name
         extra_specs = {"storage_protocol": proto,
@@ -46,14 +45,14 @@
             vol_type = self.create_volume_type(
                 extra_specs=extra_specs)
             volume_types.append(vol_type)
-        params = {name_field: vol_name,
+        params = {'name': vol_name,
                   'volume_type': volume_types[0]['id'],
                   'size': CONF.volume.volume_size}
 
         # Create volume
         volume = self.create_volume(**params)
         self.assertEqual(volume_types[0]['name'], volume["volume_type"])
-        self.assertEqual(volume[name_field], vol_name,
+        self.assertEqual(volume['name'], vol_name,
                          "The created volume name is not equal "
                          "to the requested name")
         self.assertIsNotNone(volume['id'],
@@ -74,7 +73,7 @@
                          fetched_volume['volume_type'],
                          'The fetched Volume type is different '
                          'from updated volume type')
-        self.assertEqual(vol_name, fetched_volume[name_field],
+        self.assertEqual(vol_name, fetched_volume['name'],
                          'The fetched Volume is different '
                          'from the created Volume')
         self.assertEqual(volume['id'], fetched_volume['id'],
@@ -123,43 +122,55 @@
             fetched_volume_type['os-volume-type-access:is_public'])
 
     @decorators.idempotent_id('7830abd0-ff99-4793-a265-405684a54d46')
-    def test_volume_type_encryption_create_get_delete(self):
-        # Create/get/delete encryption type.
-        provider = "LuksEncryptor"
-        control_location = "front-end"
-        body = self.create_volume_type()
+    def test_volume_type_encryption_create_get_update_delete(self):
+        # Create/get/update/delete encryption type.
+        create_kwargs = {'provider': 'LuksEncryptor',
+                         'control_location': 'front-end'}
+        volume_type_id = self.create_volume_type()['id']
+
         # Create encryption type
         encryption_type = \
             self.admin_encryption_types_client.create_encryption_type(
-                body['id'], provider=provider,
-                control_location=control_location)['encryption']
+                volume_type_id, **create_kwargs)['encryption']
         self.assertIn('volume_type_id', encryption_type)
-        self.assertEqual(provider, encryption_type['provider'],
-                         "The created encryption_type provider is not equal "
-                         "to the requested provider")
-        self.assertEqual(control_location, encryption_type['control_location'],
-                         "The created encryption_type control_location is not "
-                         "equal to the requested control_location")
+        for key in create_kwargs:
+            self.assertEqual(create_kwargs[key], encryption_type[key],
+                             'The created encryption_type %s is different '
+                             'from the requested encryption_type' % key)
 
         # Get encryption type
+        encrypt_type_id = encryption_type['volume_type_id']
         fetched_encryption_type = (
             self.admin_encryption_types_client.show_encryption_type(
-                encryption_type['volume_type_id']))
-        self.assertEqual(provider,
-                         fetched_encryption_type['provider'],
-                         'The fetched encryption_type provider is different '
-                         'from the created encryption_type')
-        self.assertEqual(control_location,
-                         fetched_encryption_type['control_location'],
-                         'The fetched encryption_type control_location is '
-                         'different from the created encryption_type')
+                encrypt_type_id))
+        for key in create_kwargs:
+            self.assertEqual(create_kwargs[key], fetched_encryption_type[key],
+                             'The fetched encryption_type %s is different '
+                             'from the created encryption_type' % key)
+
+        # Update encryption type
+        update_kwargs = {'key_size': 128,
+                         'provider': 'SomeProvider',
+                         'cipher': 'aes-xts-plain64',
+                         'control_location': 'back-end'}
+        self.admin_encryption_types_client.update_encryption_type(
+            encrypt_type_id, **update_kwargs)
+        updated_encryption_type = (
+            self.admin_encryption_types_client.show_encryption_type(
+                encrypt_type_id))
+        for key in update_kwargs:
+            self.assertEqual(update_kwargs[key], updated_encryption_type[key],
+                             'The fetched encryption_type %s is different '
+                             'from the updated encryption_type' % key)
 
         # Delete encryption type
-        type_id = encryption_type['volume_type_id']
-        self.admin_encryption_types_client.delete_encryption_type(type_id)
-        self.admin_encryption_types_client.wait_for_resource_deletion(type_id)
+        self.admin_encryption_types_client.delete_encryption_type(
+            encrypt_type_id)
+        self.admin_encryption_types_client.wait_for_resource_deletion(
+            encrypt_type_id)
         deleted_encryption_type = (
-            self.admin_encryption_types_client.show_encryption_type(type_id))
+            self.admin_encryption_types_client.show_encryption_type(
+                encrypt_type_id))
         self.assertEmpty(deleted_encryption_type)
 
     @decorators.idempotent_id('cf9f07c6-db9e-4462-a243-5933ad65e9c8')
@@ -183,7 +194,3 @@
         self.assertEqual(name, updated_vol_type['name'])
         self.assertEqual(description, updated_vol_type['description'])
         self.assertEqual(is_public, updated_vol_type['is_public'])
-
-
-class VolumeTypesV1Test(VolumeTypesV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 1729d06..b5a2fb7 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -18,11 +18,11 @@
 from tempest.lib import exceptions as lib_exc
 
 
-class VolumeTypesExtraSpecsV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesExtraSpecsTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeTypesExtraSpecsV2Test, cls).resource_setup()
+        super(VolumeTypesExtraSpecsTest, cls).resource_setup()
         cls.volume_type = cls.create_volume_type()
 
     @decorators.idempotent_id('b42923e9-0452-4945-be5b-d362ae533e60')
@@ -77,7 +77,3 @@
             lib_exc.NotFound,
             self.admin_volume_types_client.show_volume_type_extra_specs,
             self.volume_type['id'], spec_key)
-
-
-class VolumeTypesExtraSpecsV1Test(VolumeTypesExtraSpecsV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 5f590bc..4fa934e 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -14,21 +14,20 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
+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
 
 
-class ExtraSpecsNegativeV2Test(base.BaseVolumeAdminTest):
+class ExtraSpecsNegativeTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(ExtraSpecsNegativeV2Test, cls).resource_setup()
+        super(ExtraSpecsNegativeTest, cls).resource_setup()
         extra_specs = {"spec1": "val1"}
         cls.volume_type = cls.create_volume_type(extra_specs=extra_specs)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('08961d20-5cbb-4910-ac0f-89ad6dbb2da1')
     def test_update_no_body(self):
         # Should not update volume type extra specs with no body
@@ -37,7 +36,7 @@
             self.admin_volume_types_client.update_volume_type_extra_specs,
             self.volume_type['id'], "spec1", None)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('25e5a0ee-89b3-4c53-8310-236f76c75365')
     def test_update_nonexistent_extra_spec_id(self):
         # Should not update volume type extra specs with nonexistent id.
@@ -48,7 +47,7 @@
             self.volume_type['id'], data_utils.rand_uuid(),
             extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9bf7a657-b011-4aec-866d-81c496fbe5c8')
     def test_update_none_extra_spec_id(self):
         # Should not update volume type extra specs with none id.
@@ -58,7 +57,7 @@
             self.admin_volume_types_client.update_volume_type_extra_specs,
             self.volume_type['id'], None, extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a77dfda2-9100-448e-9076-ed1711f4bdfc')
     def test_update_multiple_extra_spec(self):
         # Should not update volume type extra specs with multiple specs as
@@ -70,7 +69,7 @@
             self.volume_type['id'], list(extra_spec)[0],
             extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('49d5472c-a53d-4eab-a4d3-450c4db1c545')
     def test_create_nonexistent_type_id(self):
         # Should not create volume type extra spec for nonexistent volume
@@ -81,7 +80,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             data_utils.rand_uuid(), extra_specs)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c821bdc8-43a4-4bf4-86c8-82f3858d5f7d')
     def test_create_none_body(self):
         # Should not create volume type extra spec for none POST body.
@@ -90,7 +89,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             self.volume_type['id'], None)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bc772c71-1ed4-4716-b945-8b5ed0f15e87')
     def test_create_invalid_body(self):
         # Should not create volume type extra spec for invalid POST body.
@@ -99,7 +98,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             self.volume_type['id'], extra_specs=['invalid'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('031cda8b-7d23-4246-8bf6-bbe73fd67074')
     def test_delete_nonexistent_volume_type_id(self):
         # Should not delete volume type extra spec for nonexistent
@@ -109,7 +108,7 @@
             self.admin_volume_types_client.delete_volume_type_extra_specs,
             data_utils.rand_uuid(), "spec1")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dee5cf0c-cdd6-4353-b70c-e847050d71fb')
     def test_list_nonexistent_volume_type_id(self):
         # Should not list volume type extra spec for nonexistent type id.
@@ -118,7 +117,7 @@
             self.admin_volume_types_client.list_volume_types_extra_specs,
             data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f402cbd-1838-4eb4-9554-126a6b1908c9')
     def test_get_nonexistent_volume_type_id(self):
         # Should not get volume type extra spec for nonexistent type id.
@@ -127,7 +126,7 @@
             self.admin_volume_types_client.show_volume_type_extra_specs,
             data_utils.rand_uuid(), "spec1")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c881797d-12ff-4f1a-b09d-9f6212159753')
     def test_get_nonexistent_extra_spec_id(self):
         # Should not get volume type extra spec for nonexistent extra spec
@@ -136,7 +135,3 @@
             lib_exc.NotFound,
             self.admin_volume_types_client.show_volume_type_extra_specs,
             self.volume_type['id'], data_utils.rand_uuid())
-
-
-class ExtraSpecsNegativeV1Test(ExtraSpecsNegativeV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 69e9cc0..4cad52a 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -17,22 +17,20 @@
 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
 
 
-class VolumeTypesNegativeV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesNegativeTest(base.BaseVolumeAdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b48c98f2-e662-4885-9b71-032256906314')
     def test_create_with_nonexistent_volume_type(self):
         # Should not be able to create volume with nonexistent volume_type.
-        name_field = self.special_fields['name_field']
-        params = {name_field: data_utils.rand_uuid(),
+        params = {'name': data_utils.rand_uuid(),
                   'volume_type': data_utils.rand_uuid()}
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.create_volume, **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('878b4e57-faa2-4659-b0d1-ce740a06ae81')
     def test_create_with_empty_name(self):
         # Should not be able to create volume type with an empty name.
@@ -40,7 +38,7 @@
             lib_exc.BadRequest,
             self.admin_volume_types_client.create_volume_type, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('994610d6-0476-4018-a644-a2602ef5d4aa')
     def test_get_nonexistent_type_id(self):
         # Should not be able to get volume type with nonexistent type id.
@@ -48,7 +46,7 @@
                           self.admin_volume_types_client.show_volume_type,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6b3926d2-7d73-4896-bc3d-e42dfd11a9f6')
     def test_delete_nonexistent_type_id(self):
         # Should not be able to delete volume type with nonexistent type id.
@@ -56,7 +54,7 @@
                           self.admin_volume_types_client.delete_volume_type,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.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.
@@ -64,7 +62,3 @@
         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 693ffe7..7f291e9 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -17,7 +17,7 @@
 from tempest.lib import decorators
 
 
-class VolumesActionsV2Test(base.BaseVolumeAdminTest):
+class VolumesActionsTest(base.BaseVolumeAdminTest):
 
     def _create_reset_and_force_delete_temp_volume(self, status=None):
         # Create volume, reset volume status, and force delete temp volume
@@ -32,7 +32,9 @@
     def test_volume_reset_status(self):
         # test volume reset status : available->error->available
         volume = self.create_volume()
-        for status in ['error', 'available']:
+        self.addCleanup(self.admin_volume_client.reset_volume_status,
+                        volume['id'], status='available')
+        for status in ['error', 'available', 'maintenance']:
             self.admin_volume_client.reset_volume_status(
                 volume['id'], status=status)
             volume_get = self.admin_volume_client.show_volume(
@@ -54,6 +56,7 @@
         # test force delete when status of volume is error
         self._create_reset_and_force_delete_temp_volume('error')
 
-
-class VolumesActionsV1Test(VolumesActionsV2Test):
-    _api_version = 1
+    @decorators.idempotent_id('b957cabd-1486-4e21-90cf-a9ed3c39dfb2')
+    def test_volume_force_delete_when_volume_is_maintenance(self):
+        # test force delete when status of volume is maintenance
+        self._create_reset_and_force_delete_temp_volume('maintenance')
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 13b7384..afc3281 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -17,19 +17,19 @@
 from oslo_serialization import jsonutils as json
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
 CONF = config.CONF
 
 
-class VolumesBackupsAdminV2Test(base.BaseVolumeAdminTest):
+class VolumesBackupsAdminTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesBackupsAdminV2Test, cls).skip_checks()
+        super(VolumesBackupsAdminTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
@@ -136,7 +136,3 @@
                                                       status="error")
         waiters.wait_for_volume_resource_status(self.admin_backups_client,
                                                 backup['id'], 'error')
-
-
-class VolumesBackupsAdminV1Test(VolumesBackupsAdminV2Test):
-    _api_version = 1
diff --git a/tempest/api/volume/admin/v2/test_volumes_list.py b/tempest/api/volume/admin/test_volumes_list.py
similarity index 95%
rename from tempest/api/volume/admin/v2/test_volumes_list.py
rename to tempest/api/volume/admin/test_volumes_list.py
index 6bab373..9d98b7a 100644
--- a/tempest/api/volume/admin/v2/test_volumes_list.py
+++ b/tempest/api/volume/admin/test_volumes_list.py
@@ -23,11 +23,11 @@
 CONF = config.CONF
 
 
-class VolumesListAdminV2TestJSON(base.BaseVolumeAdminTest):
+class VolumesListAdminTestJSON(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesListAdminV2TestJSON, cls).resource_setup()
+        super(VolumesListAdminTestJSON, cls).resource_setup()
         # Create 3 test volumes
         # NOTE(zhufl): When using pre-provisioned credentials, the project
         # may have volumes other than those created below.
diff --git a/tempest/api/volume/admin/v3/__init__.py b/tempest/api/volume/admin/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/admin/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index fd10fb3..767b3c7 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,10 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.api.volume import api_microversion_fixture
 from tempest.common import compute
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common import api_version_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 import tempest.test
@@ -24,7 +26,8 @@
 CONF = config.CONF
 
 
-class BaseVolumeTest(tempest.test.BaseTestCase):
+class BaseVolumeTest(api_version_utils.BaseMicroversionTest,
+                     tempest.test.BaseTestCase):
     """Base test case class for all Cinder API tests."""
 
     _api_version = 2
@@ -37,11 +40,7 @@
         if not CONF.service_available.cinder:
             skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
-        if cls._api_version == 1:
-            if not CONF.volume_feature_enabled.api_v1:
-                msg = "Volume API v1 is disabled"
-                raise cls.skipException(msg)
-        elif cls._api_version == 2:
+        if cls._api_version == 2:
             if not CONF.volume_feature_enabled.api_v2:
                 msg = "Volume API v2 is disabled"
                 raise cls.skipException(msg)
@@ -53,6 +52,10 @@
             msg = ("Invalid Cinder API version (%s)" % cls._api_version)
             raise exceptions.InvalidConfiguration(msg)
 
+        api_version_utils.check_skip_with_microversion(
+            cls.min_microversion, cls.max_microversion,
+            CONF.volume.min_microversion, CONF.volume.max_microversion)
+
     @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
@@ -62,30 +65,30 @@
     def setup_clients(cls):
         super(BaseVolumeTest, cls).setup_clients()
         cls.servers_client = cls.os.servers_client
-        cls.compute_networks_client = cls.os.compute_networks_client
         cls.compute_images_client = cls.os.compute_images_client
 
-        if cls._api_version == 1:
-            cls.snapshots_client = cls.os.snapshots_client
-            cls.volumes_client = cls.os.volumes_client
-            cls.backups_client = cls.os.backups_client
-            cls.volume_services_client = cls.os.volume_services_client
-            cls.volumes_extension_client = cls.os.volumes_extension_client
-            cls.availability_zone_client = (
-                cls.os.volume_availability_zone_client)
-            cls.volume_limits_client = cls.os.volume_limits_client
-        else:
-            cls.snapshots_client = cls.os.snapshots_v2_client
-            cls.volumes_client = cls.os.volumes_v2_client
-            cls.backups_client = cls.os.backups_v2_client
-            cls.volumes_extension_client = cls.os.volumes_v2_extension_client
-            cls.availability_zone_client = (
-                cls.os.volume_v2_availability_zone_client)
-            cls.volume_limits_client = cls.os.volume_v2_limits_client
+        cls.snapshots_client = cls.os.snapshots_v2_client
+        cls.volumes_client = cls.os.volumes_v2_client
+        cls.backups_client = cls.os.backups_v2_client
+        cls.volumes_extension_client = cls.os.volumes_v2_extension_client
+        cls.availability_zone_client = (
+            cls.os.volume_v2_availability_zone_client)
+        cls.volume_limits_client = cls.os.volume_v2_limits_client
+        cls.messages_client = cls.os.volume_v3_messages_client
+        cls.versions_client = cls.os.volume_v3_versions_client
+
+    def setUp(self):
+        super(BaseVolumeTest, self).setUp()
+        self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+            self.request_microversion))
 
     @classmethod
     def resource_setup(cls):
         super(BaseVolumeTest, cls).resource_setup()
+        cls.request_microversion = (
+            api_version_utils.select_request_microversion(
+                cls.min_microversion,
+                CONF.volume.min_microversion))
 
         cls.snapshots = []
         cls.volumes = []
@@ -94,15 +97,6 @@
         cls.build_interval = CONF.volume.build_interval
         cls.build_timeout = CONF.volume.build_timeout
 
-        if cls._api_version == 1:
-            # Special fields and resp code for cinder v1
-            cls.special_fields = {'name_field': 'display_name',
-                                  'descrip_field': 'display_description'}
-        else:
-            # Special fields and resp code for cinder v2
-            cls.special_fields = {'name_field': 'name',
-                                  'descrip_field': 'description'}
-
     @classmethod
     def resource_cleanup(cls):
         cls.clear_snapshots()
@@ -124,10 +118,9 @@
             min_disk = image.get('minDisk')
             kwargs['size'] = max(kwargs['size'], min_disk)
 
-        name_field = cls.special_fields['name_field']
-        if name_field not in kwargs:
+        if 'name' not in kwargs:
             name = data_utils.rand_name(cls.__name__ + '-Volume')
-            kwargs[name_field] = name
+            kwargs['name'] = name
 
         volume = cls.volumes_client.create_volume(**kwargs)['volume']
         cls.volumes.append(volume)
@@ -138,10 +131,9 @@
     @classmethod
     def create_snapshot(cls, volume_id=1, **kwargs):
         """Wrapper utility that returns a test snapshot."""
-        name_field = cls.special_fields['name_field']
-        if name_field not in kwargs:
+        if 'name' not in kwargs:
             name = data_utils.rand_name(cls.__name__ + '-Snapshot')
-            kwargs[name_field] = name
+            kwargs['name'] = name
 
         snapshot = cls.snapshots_client.create_snapshot(
             volume_id=volume_id, **kwargs)['snapshot']
@@ -154,6 +146,9 @@
         """Wrapper utility that returns a test backup."""
         if backup_client is None:
             backup_client = self.backups_client
+        if 'name' not in kwargs:
+            name = data_utils.rand_name(self.__class__.__name__ + '-Backup')
+            kwargs['name'] = name
 
         backup = backup_client.create_backup(
             volume_id=volume_id, **kwargs)['backup']
@@ -246,38 +241,27 @@
     def setup_clients(cls):
         super(BaseVolumeAdminTest, cls).setup_clients()
 
-        if cls._api_version == 1:
-            cls.admin_volume_qos_client = cls.os_adm.volume_qos_client
-            cls.admin_volume_services_client = \
-                cls.os_adm.volume_services_client
-            cls.admin_volume_types_client = cls.os_adm.volume_types_client
-            cls.admin_volume_client = cls.os_adm.volumes_client
-            cls.admin_hosts_client = cls.os_adm.volume_hosts_client
-            cls.admin_snapshots_client = cls.os_adm.snapshots_client
-            cls.admin_backups_client = cls.os_adm.backups_client
-            cls.admin_encryption_types_client = \
-                cls.os_adm.encryption_types_client
-            cls.admin_quotas_client = cls.os_adm.volume_quotas_client
-            cls.admin_volume_limits_client = cls.os_adm.volume_limits_client
-        elif cls._api_version == 2:
-            cls.admin_volume_qos_client = cls.os_adm.volume_qos_v2_client
-            cls.admin_volume_services_client = \
-                cls.os_adm.volume_services_v2_client
-            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 = \
-                cls.os_adm.encryption_types_v2_client
-            cls.admin_quotas_client = cls.os_adm.volume_quotas_v2_client
-            cls.admin_volume_limits_client = cls.os_adm.volume_v2_limits_client
-            cls.admin_capabilities_client = \
-                cls.os_adm.volume_capabilities_v2_client
-            cls.admin_scheduler_stats_client = \
-                cls.os_adm.volume_scheduler_stats_v2_client
+        cls.admin_volume_qos_client = cls.os_adm.volume_qos_v2_client
+        cls.admin_volume_services_client = \
+            cls.os_adm.volume_services_v2_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+        cls.admin_volume_manage_client = cls.os_adm.volume_manage_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 = \
+            cls.os_adm.encryption_types_v2_client
+        cls.admin_quotas_client = cls.os_adm.volume_quotas_v2_client
+        cls.admin_volume_limits_client = cls.os_adm.volume_v2_limits_client
+        cls.admin_capabilities_client = \
+            cls.os_adm.volume_capabilities_v2_client
+        cls.admin_scheduler_stats_client = \
+            cls.os_adm.volume_scheduler_stats_v2_client
+        cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index 25fe5ad..666efdf 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -17,12 +17,12 @@
 from tempest.lib import decorators
 
 
-class AvailabilityZoneV2TestJSON(base.BaseVolumeTest):
-    """Tests Availability Zone V2 API List"""
+class AvailabilityZoneTestJSON(base.BaseVolumeTest):
+    """Tests Availability Zone API List"""
 
     @classmethod
     def setup_clients(cls):
-        super(AvailabilityZoneV2TestJSON, cls).setup_clients()
+        super(AvailabilityZoneTestJSON, cls).setup_clients()
         cls.client = cls.availability_zone_client
 
     @decorators.idempotent_id('01f1ae88-eba9-4c6b-a011-6f7ace06b725')
@@ -31,7 +31,3 @@
         availability_zone = (self.client.list_availability_zones()
                              ['availabilityZoneInfo'])
         self.assertGreater(len(availability_zone), 0)
-
-
-class AvailabilityZoneV1TestJSON(AvailabilityZoneV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index ca86748..39ce00c 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -25,14 +25,14 @@
 LOG = logging.getLogger(__name__)
 
 
-class ExtensionsV2TestJSON(base.BaseVolumeTest):
+class ExtensionsTestJSON(base.BaseVolumeTest):
 
     @decorators.idempotent_id('94607eb0-43a5-47ca-82aa-736b41bd2e2c')
     def test_list_extensions(self):
         # List of all extensions
         extensions = (self.volumes_extension_client.list_extensions()
                       ['extensions'])
-        if len(CONF.volume_feature_enabled.api_extensions) == 0:
+        if not CONF.volume_feature_enabled.api_extensions:
             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))
@@ -43,7 +43,3 @@
             self.assertIn(ext, map(lambda x: x['alias'], extensions))
         else:
             raise self.skipException('There are not any extensions configured')
-
-
-class ExtensionsV1TestJSON(ExtensionsV2TestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/v2/test_image_metadata.py b/tempest/api/volume/test_image_metadata.py
similarity index 87%
rename from tempest/api/volume/v2/test_image_metadata.py
rename to tempest/api/volume/test_image_metadata.py
index 9c082b3..77baf18 100644
--- a/tempest/api/volume/v2/test_image_metadata.py
+++ b/tempest/api/volume/test_image_metadata.py
@@ -23,11 +23,18 @@
 CONF = config.CONF
 
 
-class VolumesV2ImageMetadata(base.BaseVolumeTest):
+class VolumesImageMetadata(base.BaseVolumeTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesImageMetadata, cls).skip_checks()
+        if not CONF.service_available.glance:
+            skip_msg = ("%s skipped as Glance is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ImageMetadata, cls).resource_setup()
+        super(VolumesImageMetadata, cls).resource_setup()
         # Create a volume from image ID
         cls.volume = cls.create_volume(imageRef=CONF.compute.image_ref)
 
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index d5ad8d2..164ed37 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -22,16 +22,16 @@
 CONF = config.CONF
 
 
-class SnapshotV2MetadataTestJSON(base.BaseVolumeTest):
+class SnapshotMetadataTestJSON(base.BaseVolumeTest):
     @classmethod
     def skip_checks(cls):
-        super(SnapshotV2MetadataTestJSON, cls).skip_checks()
+        super(SnapshotMetadataTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(SnapshotV2MetadataTestJSON, cls).resource_setup()
+        super(SnapshotMetadataTestJSON, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
         # Create a snapshot
@@ -41,7 +41,7 @@
         # Update the metadata to {}
         self.snapshots_client.update_snapshot_metadata(
             self.snapshot['id'], metadata={})
-        super(SnapshotV2MetadataTestJSON, self).tearDown()
+        super(SnapshotMetadataTestJSON, self).tearDown()
 
     @decorators.idempotent_id('a2f20f99-e363-4584-be97-bc33afb1a56c')
     def test_crud_snapshot_metadata(self):
@@ -102,7 +102,3 @@
         body = self.snapshots_client.show_snapshot_metadata(
             self.snapshot['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
-
-
-class SnapshotV1MetadataTestJSON(SnapshotV2MetadataTestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/test_versions.py b/tempest/api/volume/test_versions.py
new file mode 100644
index 0000000..0083a3b
--- /dev/null
+++ b/tempest/api/volume/test_versions.py
@@ -0,0 +1,29 @@
+# Copyright 2017 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.volume import base
+from tempest.lib import decorators
+
+
+class VersionsTest(base.BaseVolumeTest):
+
+    _api_version = 3
+
+    @decorators.idempotent_id('77838fc4-b49b-4c64-9533-166762517369')
+    @decorators.attr(type='smoke')
+    def test_list_versions(self):
+        # NOTE: The version data is checked on service client side
+        #       with JSON-Schema validation. It is enough to just call
+        #       the API here.
+        self.versions_client.list_versions()['versions']
diff --git a/tempest/api/volume/test_volume_absolute_limits.py b/tempest/api/volume/test_volume_absolute_limits.py
index 36445b9..836e489 100644
--- a/tempest/api/volume/test_volume_absolute_limits.py
+++ b/tempest/api/volume/test_volume_absolute_limits.py
@@ -21,14 +21,14 @@
 CONF = config.CONF
 
 
-class AbsoluteLimitsV2Tests(base.BaseVolumeTest):
+class AbsoluteLimitsTests(base.BaseVolumeTest):
 
     # avoid existing volumes of pre-defined tenant
     force_tenant_isolation = True
 
     @classmethod
     def resource_setup(cls):
-        super(AbsoluteLimitsV2Tests, cls).resource_setup()
+        super(AbsoluteLimitsTests, cls).resource_setup()
         # Create a shared volume for tests
         cls.volume = cls.create_volume()
 
@@ -46,7 +46,3 @@
         self.assertEqual(absolute_limits['totalSnapshotsUsed'], 0)
         self.assertEqual(absolute_limits['totalBackupsUsed'], 0)
         self.assertEqual(absolute_limits['totalBackupGigabytesUsed'], 0)
-
-
-class AbsoluteLimitsV1Tests(AbsoluteLimitsV2Tests):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volume_delete_cascade.py b/tempest/api/volume/test_volume_delete_cascade.py
new file mode 100644
index 0000000..bb32c11
--- /dev/null
+++ b/tempest/api/volume/test_volume_delete_cascade.py
@@ -0,0 +1,101 @@
+# 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 operator
+
+import testtools
+
+from tempest.api.volume import base
+from tempest import config
+from tempest.lib import decorators
+
+CONF = config.CONF
+
+
+class VolumesDeleteCascade(base.BaseVolumeTest):
+    """Delete a volume with associated snapshots.
+
+    Cinder provides the ability to delete a volume with its
+    associated snapshots.
+    It is allow a volume and its snapshots to be removed in one operation
+    both for usability and performance reasons.
+    """
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesDeleteCascade, cls).skip_checks()
+        if not CONF.volume_feature_enabled.snapshot:
+            raise cls.skipException("Cinder snapshot feature disabled")
+
+    def _assert_cascade_delete(self, volume_id):
+        # Fetch volume ids
+        volume_list = [
+            vol['id'] for vol in
+            self.volumes_client.list_volumes()['volumes']
+            ]
+
+        # Verify the parent volume was deleted
+        self.assertNotIn(volume_id, volume_list)
+
+        # List snapshots
+        snapshot_list = self.snapshots_client.list_snapshots()['snapshots']
+
+        # Verify snapshots were deleted
+        self.assertNotIn(volume_id, map(operator.itemgetter('volume_id'),
+                                        snapshot_list))
+
+    @decorators.idempotent_id('994e2d40-de37-46e8-b328-a58fba7e4a95')
+    def test_volume_delete_cascade(self):
+        # The case validates the ability to delete a volume
+        # with associated snapshots.
+
+        # Create a volume
+        volume = self.create_volume()
+
+        for _ in range(2):
+            self.create_snapshot(volume['id'])
+
+        # Delete the parent volume with associated snapshots
+        self.volumes_client.delete_volume(volume['id'], cascade=True)
+        self.volumes_client.wait_for_resource_deletion(volume['id'])
+
+        # Verify volume parent was deleted with its associated snapshots
+        self._assert_cascade_delete(volume['id'])
+
+    @decorators.idempotent_id('59a77ede-609b-4ee8-9f68-fc3c6ffe97b5')
+    @testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
+                      'Skip because of Bug#1677525')
+    def test_volume_from_snapshot_cascade_delete(self):
+        # The case validates the ability to delete a volume with
+        # associated snapshot while there is another volume created
+        # from that snapshot.
+
+        # Create a volume
+        volume = self.create_volume()
+
+        snapshot = self.create_snapshot(volume['id'])
+
+        # Create volume from snapshot
+        volume_snap = self.create_volume(snapshot_id=snapshot['id'])
+        volume_details = self.volumes_client.show_volume(
+            volume_snap['id'])['volume']
+        self.assertEqual(snapshot['id'], volume_details['snapshot_id'])
+
+        # Delete the parent volume with associated snapshot
+        self.volumes_client.delete_volume(volume['id'], cascade=True)
+        self.volumes_client.wait_for_resource_deletion(volume['id'])
+
+        # Verify volume parent was deleted with its associated snapshot
+        self._assert_cascade_delete(volume['id'])
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index 9e7b0a7..b4d22fe 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -19,18 +19,18 @@
 from tempest.lib import decorators
 
 
-class VolumesV2MetadataTest(base.BaseVolumeTest):
+class VolumesMetadataTest(base.BaseVolumeTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2MetadataTest, cls).resource_setup()
+        super(VolumesMetadataTest, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
 
     def tearDown(self):
         # Update the metadata to {}
         self.volumes_client.update_volume_metadata(self.volume['id'], {})
-        super(VolumesV2MetadataTest, self).tearDown()
+        super(VolumesMetadataTest, self).tearDown()
 
     @decorators.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
     def test_crud_volume_metadata(self):
@@ -89,7 +89,3 @@
         body = self.volumes_client.show_volume_metadata(
             self.volume['id'])['metadata']
         self.assertThat(body.items(), matchers.ContainsAll(expect.items()))
-
-
-class VolumesV1MetadataTest(VolumesV2MetadataTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 9f63b14..afcffc2 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -20,23 +20,26 @@
 from tempest.lib import decorators
 
 
-class VolumesV2TransfersTest(base.BaseVolumeTest):
+class VolumesTransfersTest(base.BaseVolumeTest):
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_clients(cls):
-        super(VolumesV2TransfersTest, cls).setup_clients()
+        super(VolumesTransfersTest, cls).setup_clients()
 
-        cls.client = cls.volumes_client
-        cls.alt_client = cls.os_alt.volumes_client
-        cls.adm_client = cls.os_adm.volumes_client
+        cls.client = cls.os.volume_transfers_v2_client
+        cls.alt_client = cls.os_alt.volume_transfers_v2_client
+        cls.alt_volumes_client = cls.os_alt.volumes_v2_client
+        cls.adm_volumes_client = cls.os_adm.volumes_v2_client
 
     @decorators.idempotent_id('4d75b645-a478-48b1-97c8-503f64242f1a')
     def test_create_get_list_accept_volume_transfer(self):
         # Create a volume first
         volume = self.create_volume()
-        self.addCleanup(self.delete_volume, self.adm_client, volume['id'])
+        self.addCleanup(self.delete_volume,
+                        self.adm_volumes_client,
+                        volume['id'])
 
         # Create a volume transfer
         transfer = self.client.create_volume_transfer(
@@ -44,7 +47,7 @@
         transfer_id = transfer['id']
         auth_key = transfer['auth_key']
         waiters.wait_for_volume_resource_status(
-            self.client, volume['id'], 'awaiting-transfer')
+            self.volumes_client, volume['id'], 'awaiting-transfer')
 
         # Get a volume transfer
         body = self.client.show_volume_transfer(transfer_id)['transfer']
@@ -58,21 +61,23 @@
         # Accept a volume transfer by alt_tenant
         body = self.alt_client.accept_volume_transfer(
             transfer_id, auth_key=auth_key)['transfer']
-        waiters.wait_for_volume_resource_status(self.alt_client,
+        waiters.wait_for_volume_resource_status(self.alt_volumes_client,
                                                 volume['id'], 'available')
 
     @decorators.idempotent_id('ab526943-b725-4c07-b875-8e8ef87a2c30')
     def test_create_list_delete_volume_transfer(self):
         # Create a volume first
         volume = self.create_volume()
-        self.addCleanup(self.delete_volume, self.adm_client, volume['id'])
+        self.addCleanup(self.delete_volume,
+                        self.adm_volumes_client,
+                        volume['id'])
 
         # Create a volume transfer
         body = self.client.create_volume_transfer(
             volume_id=volume['id'])['transfer']
         transfer_id = body['id']
         waiters.wait_for_volume_resource_status(
-            self.client, volume['id'], 'awaiting-transfer')
+            self.volumes_client, volume['id'], 'awaiting-transfer')
 
         # List all volume transfers (looking for the one we created)
         body = self.client.list_volume_transfers()['transfers']
@@ -85,8 +90,4 @@
         # Delete a volume transfer
         self.client.delete_volume_transfer(transfer_id)
         waiters.wait_for_volume_resource_status(
-            self.client, volume['id'], 'available')
-
-
-class VolumesV1TransfersTest(VolumesV2TransfersTest):
-    _api_version = 1
+            self.volumes_client, volume['id'], 'available')
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 0a6901c..1e05f22 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -14,9 +14,9 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 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 decorators
 from tempest.lib import exceptions
@@ -25,12 +25,11 @@
 CONF = config.CONF
 
 
-class VolumesV2ActionsTest(base.BaseVolumeTest):
+class VolumesActionsTest(base.BaseVolumeTest):
 
     @classmethod
     def setup_clients(cls):
-        super(VolumesV2ActionsTest, cls).setup_clients()
-        cls.client = cls.volumes_client
+        super(VolumesActionsTest, cls).setup_clients()
         if CONF.service_available.glance:
             # Check if glance v1 is available to determine which client to use.
             if CONF.image_feature_enabled.api_v1:
@@ -44,35 +43,35 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ActionsTest, cls).resource_setup()
+        super(VolumesActionsTest, cls).resource_setup()
 
         # Create a test shared volume for attach/detach tests
         cls.volume = cls.create_volume()
 
     @decorators.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute')
     def test_attach_detach_volume_to_instance(self):
         # Create a server
         server = self.create_server(wait_until='ACTIVE')
         # Volume is attached and detached successfully from an instance
-        self.client.attach_volume(self.volume['id'],
-                                  instance_uuid=server['id'],
-                                  mountpoint='/dev/%s' %
-                                             CONF.compute.volume_device_name)
-        waiters.wait_for_volume_resource_status(self.client,
+        self.volumes_client.attach_volume(self.volume['id'],
+                                          instance_uuid=server['id'],
+                                          mountpoint='/dev/%s' %
+                                          CONF.compute.volume_device_name)
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'in-use')
-        self.client.detach_volume(self.volume['id'])
-        waiters.wait_for_volume_resource_status(self.client,
+        self.volumes_client.detach_volume(self.volume['id'])
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'available')
 
     @decorators.idempotent_id('63e21b4c-0a0c-41f6-bfc3-7c2816815599')
     def test_volume_bootable(self):
         # Verify that a volume bootable flag is retrieved
         for bool_bootable in [True, False]:
-            self.client.set_bootable_volume(self.volume['id'],
-                                            bootable=bool_bootable)
-            fetched_volume = self.client.show_volume(
+            self.volumes_client.set_bootable_volume(self.volume['id'],
+                                                    bootable=bool_bootable)
+            fetched_volume = self.volumes_client.show_volume(
                 self.volume['id'])['volume']
             # Get Volume information
             # NOTE(masayukig): 'bootable' is "true" or "false" in the current
@@ -87,16 +86,18 @@
         # Create a server
         server = self.create_server(wait_until='ACTIVE')
         # Verify that a volume's attachment information is retrieved
-        self.client.attach_volume(self.volume['id'],
-                                  instance_uuid=server['id'],
-                                  mountpoint='/dev/%s' %
-                                             CONF.compute.volume_device_name)
-        waiters.wait_for_volume_resource_status(self.client, self.volume['id'],
+        self.volumes_client.attach_volume(self.volume['id'],
+                                          instance_uuid=server['id'],
+                                          mountpoint='/dev/%s' %
+                                          CONF.compute.volume_device_name)
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                self.volume['id'],
                                                 'in-use')
-        self.addCleanup(waiters.wait_for_volume_resource_status, self.client,
+        self.addCleanup(waiters.wait_for_volume_resource_status,
+                        self.volumes_client,
                         self.volume['id'], 'available')
-        self.addCleanup(self.client.detach_volume, self.volume['id'])
-        volume = self.client.show_volume(self.volume['id'])['volume']
+        self.addCleanup(self.volumes_client.detach_volume, self.volume['id'])
+        volume = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('attachments', volume)
         attachment = volume['attachments'][0]
 
@@ -115,7 +116,7 @@
         # there is no way to delete it from Cinder, so we delete it from Glance
         # using the Glance image_client and from Cinder via tearDownClass.
         image_name = data_utils.rand_name(self.__class__.__name__ + '-Image')
-        body = self.client.upload_volume(
+        body = self.volumes_client.upload_volume(
             self.volume['id'], image_name=image_name,
             disk_format=CONF.volume.disk_format)['os-volume_upload_image']
         image_id = body["image_id"]
@@ -123,37 +124,33 @@
                         self.image_client.delete_image,
                         image_id)
         waiters.wait_for_image_status(self.image_client, image_id, 'active')
-        waiters.wait_for_volume_resource_status(self.client,
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'available')
 
     @decorators.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33')
     def test_reserve_unreserve_volume(self):
         # Mark volume as reserved.
-        body = self.client.reserve_volume(self.volume['id'])
+        body = self.volumes_client.reserve_volume(self.volume['id'])
         # To get the volume info
-        body = self.client.show_volume(self.volume['id'])['volume']
+        body = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('attaching', body['status'])
         # Unmark volume as reserved.
-        body = self.client.unreserve_volume(self.volume['id'])
+        body = self.volumes_client.unreserve_volume(self.volume['id'])
         # To get the volume info
-        body = self.client.show_volume(self.volume['id'])['volume']
+        body = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('available', body['status'])
 
     @decorators.idempotent_id('fff74e1e-5bd3-4b33-9ea9-24c103bc3f59')
     def test_volume_readonly_update(self):
         for readonly in [True, False]:
             # Update volume readonly
-            self.client.update_volume_readonly(self.volume['id'],
-                                               readonly=readonly)
+            self.volumes_client.update_volume_readonly(self.volume['id'],
+                                                       readonly=readonly)
             # Get Volume information
-            fetched_volume = self.client.show_volume(
+            fetched_volume = self.volumes_client.show_volume(
                 self.volume['id'])['volume']
             # NOTE(masayukig): 'readonly' is "True" or "False" in the current
             # cinder implementation. So we need to cast boolean values to str
             # to compare here.
             self.assertEqual(str(readonly),
                              fetched_volume['metadata']['readonly'])
-
-
-class VolumesV1ActionsTest(VolumesV2ActionsTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index e24a142..5ad209c 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -13,23 +13,24 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
 from testtools import matchers
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
 
 
-class VolumesBackupsV2Test(base.BaseVolumeTest):
+class VolumesBackupsTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesBackupsV2Test, cls).skip_checks()
+        super(VolumesBackupsTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
@@ -49,6 +50,8 @@
                                                 'available')
         return restored_volume
 
+    @testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
+                      'ceph does not support arbitrary container names')
     @decorators.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
     def test_volume_backup_create_get_detailed_list_restore_delete(self):
         # Create a volume with metadata
@@ -65,7 +68,8 @@
         description = data_utils.rand_name("volume-backup-description")
         backup = self.create_backup(volume_id=volume['id'],
                                     name=backup_name,
-                                    description=description)
+                                    description=description,
+                                    container='container')
         self.assertEqual(backup_name, backup['name'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
@@ -74,6 +78,7 @@
         backup = self.backups_client.show_backup(backup['id'])['backup']
         self.assertEqual(backup_name, backup['name'])
         self.assertEqual(description, backup['description'])
+        self.assertEqual('container', backup['container'])
 
         # Get all backups with detail
         backups = self.backups_client.list_backups(
@@ -113,6 +118,8 @@
                                     name=backup_name, force=True)
         self.assertEqual(backup_name, backup['name'])
 
+    @testtools.skipUnless(CONF.service_available.glance,
+                          "Glance is not available")
     @decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
     def test_bootable_volume_backup_and_restore(self):
         # Create volume from image
@@ -134,7 +141,3 @@
             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_clone.py b/tempest/api/volume/test_volumes_clone.py
index d653808..a6bbb0a 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.volume import base
 from tempest import config
 from tempest.lib import decorators
@@ -21,11 +23,11 @@
 CONF = config.CONF
 
 
-class VolumesV2CloneTest(base.BaseVolumeTest):
+class VolumesCloneTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2CloneTest, cls).skip_checks()
+        super(VolumesCloneTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
@@ -45,6 +47,8 @@
         self.assertEqual(volume['source_volid'], src_vol['id'])
         self.assertEqual(volume['size'], src_size + 1)
 
+    @testtools.skipUnless(CONF.service_available.glance,
+                          "Glance is not available")
     @decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
     def test_create_from_bootable_volume(self):
         # Create volume from image
@@ -60,7 +64,3 @@
         self.assertEqual('true', cloned_vol_details['bootable'])
         self.assertEqual(src_vol['id'], cloned_vol_details['source_volid'])
         self.assertEqual(src_vol['size'], cloned_vol_details['size'])
-
-
-class VolumesV1CloneTest(VolumesV2CloneTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_clone_negative.py b/tempest/api/volume/test_volumes_clone_negative.py
index 5331243..bba7a0b 100644
--- a/tempest/api/volume/test_volumes_clone_negative.py
+++ b/tempest/api/volume/test_volumes_clone_negative.py
@@ -17,20 +17,19 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
 
-class VolumesV2CloneNegativeTest(base.BaseVolumeTest):
+class VolumesCloneNegativeTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2CloneNegativeTest, cls).skip_checks()
+        super(VolumesCloneNegativeTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9adae371-a257-43a5-459a-dc7c88e66e0e')
     def test_create_from_volume_decreasing_size(self):
         # Creates a volume from another volume passing a size different from
@@ -43,7 +42,3 @@
                           self.volumes_client.create_volume,
                           size=src_size - 1,
                           source_volid=src_vol['id'])
-
-
-class VolumesV1CloneNegativeTest(VolumesV2CloneNegativeTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 3df9b00..84ecb22 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -18,7 +18,7 @@
 from tempest.lib import decorators
 
 
-class VolumesV2ExtendTest(base.BaseVolumeTest):
+class VolumesExtendTest(base.BaseVolumeTest):
 
     @decorators.idempotent_id('9a36df71-a257-43a5-9555-dc7c88e66e0e')
     def test_volume_extend(self):
@@ -31,7 +31,3 @@
                                                 volume['id'], 'available')
         volume = self.volumes_client.show_volume(volume['id'])['volume']
         self.assertEqual(volume['size'], extend_size)
-
-
-class VolumesV1ExtendTest(VolumesV2ExtendTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index a3e46a8..1d9b846 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -17,34 +17,31 @@
 from testtools import matchers
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
 
 
-class VolumesV2GetTest(base.BaseVolumeTest):
+class VolumesGetTest(base.BaseVolumeTest):
 
     def _volume_create_get_update_delete(self, **kwargs):
-        name_field = self.special_fields['name_field']
-        descrip_field = self.special_fields['descrip_field']
-
         # Create a volume, Get it's details and Delete the volume
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
         metadata = {'Type': 'Test'}
         # Create a volume
-        kwargs[name_field] = v_name
+        kwargs['name'] = v_name
         kwargs['metadata'] = metadata
         volume = self.volumes_client.create_volume(**kwargs)['volume']
         self.assertIn('id', volume)
         self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
-        self.assertIn(name_field, volume)
-        self.assertEqual(volume[name_field], v_name,
+        self.assertIn('name', volume)
+        self.assertEqual(volume['name'], v_name,
                          "The created volume name is not equal "
                          "to the requested name")
 
@@ -52,7 +49,7 @@
         fetched_volume = self.volumes_client.show_volume(
             volume['id'])['volume']
         self.assertEqual(v_name,
-                         fetched_volume[name_field],
+                         fetched_volume['name'],
                          'The fetched Volume name is different '
                          'from the created Volume')
         self.assertEqual(volume['id'],
@@ -71,25 +68,25 @@
 
         # Update Volume
         # Test volume update when display_name is same with original value
-        params = {name_field: v_name}
+        params = {'name': v_name}
         self.volumes_client.update_volume(volume['id'], **params)
         # Test volume update when display_name is new
         new_v_name = data_utils.rand_name(
             self.__class__.__name__ + '-new-Volume')
         new_desc = 'This is the new description of volume'
-        params = {name_field: new_v_name,
-                  descrip_field: new_desc}
+        params = {'name': new_v_name,
+                  'description': new_desc}
         update_volume = self.volumes_client.update_volume(
             volume['id'], **params)['volume']
         # Assert response body for update_volume method
-        self.assertEqual(new_v_name, update_volume[name_field])
-        self.assertEqual(new_desc, update_volume[descrip_field])
+        self.assertEqual(new_v_name, update_volume['name'])
+        self.assertEqual(new_desc, update_volume['description'])
         # Assert response body for show_volume method
         updated_volume = self.volumes_client.show_volume(
             volume['id'])['volume']
         self.assertEqual(volume['id'], updated_volume['id'])
-        self.assertEqual(new_v_name, updated_volume[name_field])
-        self.assertEqual(new_desc, updated_volume[descrip_field])
+        self.assertEqual(new_v_name, updated_volume['name'])
+        self.assertEqual(new_desc, updated_volume['description'])
         self.assertThat(updated_volume['metadata'].items(),
                         matchers.ContainsAll(metadata.items()),
                         'The fetched Volume metadata misses data '
@@ -99,7 +96,7 @@
         # contains specific characters,
         # then test volume update if display_name is duplicated
         new_v_desc = data_utils.rand_name('@#$%^* description')
-        params = {descrip_field: new_v_desc,
+        params = {'description': new_v_desc,
                   'availability_zone': volume['availability_zone'],
                   'size': CONF.volume.volume_size}
         new_volume = self.volumes_client.create_volume(**params)['volume']
@@ -109,8 +106,8 @@
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 new_volume['id'], 'available')
 
-        params = {name_field: volume[name_field],
-                  descrip_field: volume[descrip_field]}
+        params = {'name': volume['name'],
+                  'description': volume['description']}
         self.volumes_client.update_volume(new_volume['id'], **params)
 
         if 'imageRef' in kwargs:
@@ -118,12 +115,12 @@
         else:
             self.assertEqual('false', updated_volume['bootable'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('27fb0e9f-fb64-41dd-8bdb-1ffa762f0d51')
     def test_volume_create_get_update_delete(self):
         self._volume_create_get_update_delete(size=CONF.volume.volume_size)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
     @test.services('image')
     def test_volume_create_get_update_delete_from_image(self):
@@ -141,7 +138,3 @@
         origin = self.create_volume()
         self._volume_create_get_update_delete(source_volid=origin['id'],
                                               size=CONF.volume.volume_size)
-
-
-class VolumesV1GetTest(VolumesV2GetTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index d1da95d..9787160 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -13,17 +13,19 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
-import operator
 
+import operator
+import random
+
+from six.moves.urllib import parse
 from testtools import matchers
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
-class VolumesV2ListTestJSON(base.BaseVolumeTest):
+class VolumesListTestJSON(base.BaseVolumeTest):
     # NOTE: This test creates a number of 1G volumes. To run successfully,
     # ensure that the backing file for the volume group that Nova uses
     # has space for at least 3 1G volumes!
@@ -44,7 +46,7 @@
             fetched_list = [fieldsgetter(item) for item in fetched_list]
 
         missing_vols = [v for v in expected_list if v not in fetched_list]
-        if len(missing_vols) == 0:
+        if not missing_vols:
             return
 
         def str_vol(vol):
@@ -57,8 +59,12 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ListTestJSON, cls).resource_setup()
+        super(VolumesListTestJSON, cls).resource_setup()
         cls.name = cls.VOLUME_FIELDS[1]
+
+        existing_volumes = cls.volumes_client.list_volumes()['volumes']
+        cls.volume_id_list = [vol['id'] for vol in existing_volumes]
+
         # Create 3 test volumes
         cls.volume_list = []
         cls.metadata = {'Type': 'work'}
@@ -66,6 +72,7 @@
             volume = cls.create_volume(metadata=cls.metadata)
             volume = cls.volumes_client.show_volume(volume['id'])['volume']
             cls.volume_list.append(volume)
+            cls.volume_id_list.append(volume['id'])
 
     def _list_by_param_value_and_assert(self, params, with_detail=False):
         """list or list_details with given params and validates result"""
@@ -78,11 +85,7 @@
                 params=params)['volumes']
 
         # Validating params of fetched volumes
-        # In v2, only list detail view includes items in params.
-        # In v1, list view and list detail view are same. So the
-        # following check should be run when 'with_detail' is True
-        # or v1 tests.
-        if with_detail or self._api_version == 1:
+        if with_detail:
             for volume in fetched_vol_list:
                 for key in params:
                     msg = "Failed to list volumes %s by %s" % \
@@ -95,7 +98,7 @@
                     else:
                         self.assertEqual(params[key], volume[key], msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0b6ddd39-b948-471f-8038-4787978747c4')
     def test_volume_list(self):
         # Get a list of Volumes
@@ -222,7 +225,156 @@
                   'status': 'available'}
         self._list_by_param_value_and_assert(params, with_detail=True)
 
+    @decorators.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
+    def test_volume_list_details_with_multiple_params(self):
+        # List volumes detail using combined condition
+        def _list_details_with_multiple_params(limit=2,
+                                               status='available',
+                                               sort_dir='asc',
+                                               sort_key='id'):
+            params = {'limit': limit,
+                      'status': status,
+                      'sort_dir': sort_dir,
+                      'sort_key': sort_key
+                      }
+            fetched_volume = self.volumes_client.list_volumes(
+                detail=True, params=params)['volumes']
+            self.assertEqual(limit, len(fetched_volume),
+                             "The count of volumes is %s, expected:%s " %
+                             (len(fetched_volume), limit))
+            self.assertEqual(status, fetched_volume[0]['status'])
+            self.assertEqual(status, fetched_volume[1]['status'])
+            val0 = fetched_volume[0][sort_key]
+            val1 = fetched_volume[1][sort_key]
+            if sort_dir == 'asc':
+                self.assertLess(val0, val1,
+                                "list is not in asc order with sort_key: %s."
+                                " %s" % (sort_key, fetched_volume))
+            elif sort_dir == 'desc':
+                self.assertGreater(val0, val1,
+                                   "list is not in desc order with sort_key: "
+                                   "%s. %s" % (sort_key, fetched_volume))
 
-class VolumesV1ListTestJSON(VolumesV2ListTestJSON):
-    _api_version = 1
-    VOLUME_FIELDS = ('id', 'display_name')
+        _list_details_with_multiple_params()
+        _list_details_with_multiple_params(sort_dir='desc')
+
+    def _test_pagination(self, resource, ids=None, limit=1, **kwargs):
+        """Check list pagination functionality for a resource.
+
+        This method requests the list of resources and follows pagination
+        links.
+
+        If an iterable is supplied in ids it will check that all ids are
+        retrieved and that only those are listed, that we will get a next
+        link for an empty page if the number of items is divisible by used
+        limit (this is expected behavior).
+
+        We can specify number of items per request using limit argument.
+        """
+
+        # Get list method for the type of resource from the client
+        client = getattr(self, resource + '_client')
+        method = getattr(client, 'list_' + resource)
+
+        # Include limit in params for list request
+        params = kwargs.pop('params', {})
+        params['limit'] = limit
+
+        # Store remaining items we are expecting from list
+        if ids is not None:
+            remaining = list(ids)
+        else:
+            remaining = None
+
+        # Mark that the current iteration is not from a 'next' link
+        next = None
+
+        while True:
+            # Get a list page
+            response = method(params=params, **kwargs)
+
+            # If we have to check ids
+            if remaining is not None:
+                # Confirm we receive expected number of elements
+                num_expected = min(len(remaining), limit)
+                self.assertEqual(num_expected, len(response[resource]),
+                                 'Requested %(#expect)d but got %(#received)d '
+                                 % {'#expect': num_expected,
+                                    '#received': len(response[resource])})
+
+                # For each received element
+                for element in response[resource]:
+                    element_id = element['id']
+                    # Check it's one of expected ids
+                    self.assertIn(element_id,
+                                  ids,
+                                  'Id %(id)s is not in expected ids %(ids)s' %
+                                  {'id': element_id, 'ids': ids})
+                    # If not in remaining, we have received it twice
+                    self.assertIn(element_id,
+                                  remaining,
+                                  'Id %s was received twice' % element_id)
+                    # We no longer expect it
+                    remaining.remove(element_id)
+
+            # If the current iteration is from a 'next' link, check that the
+            # absolute url is the same as the one used for this request
+            if next:
+                self.assertEqual(next, response.response['content-location'])
+
+            # Get next from response
+            next = None
+            for link in response.get(resource + '_links', ()):
+                if link['rel'] == 'next':
+                    next = link['href']
+                    break
+
+            # Check if we have next and we shouldn't or the other way around
+            if remaining is not None:
+                if remaining or (num_expected and len(ids) % limit == 0):
+                    self.assertIsNotNone(next, 'Missing link to next page')
+                else:
+                    self.assertIsNone(next, 'Unexpected link to next page')
+
+            # If we can follow to the next page, get params from url to make
+            # request in the form of a relative URL
+            if next:
+                params = parse.urlparse(next).query
+
+            # If cannot follow make sure it's because we have finished
+            else:
+                self.assertEqual([], remaining or [],
+                                 'No more pages reported, but still '
+                                 'missing ids %s' % remaining)
+                break
+
+    @decorators.idempotent_id('e9138a2c-f67b-4796-8efa-635c196d01de')
+    def test_volume_list_details_pagination(self):
+        self._test_pagination('volumes', ids=self.volume_id_list, detail=True)
+
+    @decorators.idempotent_id('af55e775-8e4b-4feb-8719-215c43b0238c')
+    def test_volume_list_pagination(self):
+        self._test_pagination('volumes', ids=self.volume_id_list, detail=False)
+
+    @decorators.idempotent_id('46eff077-100b-427f-914e-3db2abcdb7e2')
+    def test_volume_list_with_detail_param_marker(self):
+        # Choosing a random volume from a list of volumes for 'marker'
+        # parameter
+        marker = random.choice(self.volume_id_list)
+
+        # Though Cinder volumes are returned sorted by ID by default
+        # this is implicit. Let make this explicit in case Cinder
+        # folks change their minds.
+        params = {'marker': marker, 'sort': 'id:asc'}
+
+        # Running volume list using marker parameter
+        vol_with_marker = self.volumes_client.list_volumes(
+            detail=True, params=params)['volumes']
+
+        expected_volumes_id = {
+            id for id in self.volume_id_list if id > marker
+        }
+
+        self.assertEqual(
+            expected_volumes_id, {v['id'] for v in vol_with_marker}
+        )
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 28e65ed..5ba72c3 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -14,164 +14,133 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
+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
 
 
-class VolumesV2NegativeTest(base.BaseVolumeTest):
+class VolumesNegativeTest(base.BaseVolumeTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2NegativeTest, cls).resource_setup()
-
-        cls.name_field = cls.special_fields['name_field']
+        super(VolumesNegativeTest, cls).resource_setup()
 
         # Create a test shared instance and volume for attach/detach tests
         cls.volume = cls.create_volume()
         cls.mountpoint = "/dev/vdc"
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f131c586-9448-44a4-a8b0-54ca838aa43e')
     def test_volume_get_nonexistent_volume_id(self):
         # Should not be able to get a non-existent volume
         self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('555efa6e-efcd-44ef-8a3b-4a7ca4837a29')
     def test_volume_delete_nonexistent_volume_id(self):
         # Should not be able to delete a non-existent Volume
         self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1ed83a8a-682d-4dfb-a30e-ee63ffd6c049')
     def test_create_volume_with_invalid_size(self):
-        # Should not be able to create volume with invalid size
-        # in request
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
+        # Should not be able to create volume with invalid size in request
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='#$%', params=params)
+                          self.volumes_client.create_volume, size='#$%')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
     def test_create_volume_without_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='', params=params)
+                          self.volumes_client.create_volume, size='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41331caa-eaf4-4001-869d-bc18c1869360')
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='0', params=params)
+                          self.volumes_client.create_volume, size='0')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8b472729-9eba-446e-a83b-916bdb34bef7')
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='-1', params=params)
+                          self.volumes_client.create_volume, size='-1')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('10254ed8-3849-454e-862e-3ab8e6aa01d2')
     def test_create_volume_with_nonexistent_volume_type(self):
         # Should not be able to create volume with non-existent volume type
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', volume_type=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', volume_type=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0c36f6ae-4604-4017-b0a9-34fdc63096f9')
     def test_create_volume_with_nonexistent_snapshot_id(self):
         # Should not be able to create volume with non-existent snapshot
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', snapshot_id=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', snapshot_id=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('47c73e08-4be8-45bb-bfdf-0c4e79b88344')
     def test_create_volume_with_nonexistent_source_volid(self):
         # Should not be able to create volume with non-existent source volume
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', source_volid=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', source_volid=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0186422c-999a-480e-a026-6a665744c30c')
     def test_update_volume_with_nonexistent_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id=data_utils.rand_uuid(), params=params)
+                          volume_id=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e66e40d6-65e6-4e75-bdc7-636792fa152d')
     def test_update_volume_with_invalid_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id=data_utils.rand_name('invalid'),
-                          params=params)
+                          volume_id=data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('72aeca85-57a5-4c1f-9057-f320f9ea575b')
     def test_update_volume_with_empty_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id='', params=params)
+                          volume_id='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('30799cfd-7ee4-446c-b66c-45b383ed211b')
     def test_get_invalid_volume_id(self):
         # Should not be able to get volume with invalid id
         self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c6c3db06-29ad-4e91-beb0-2ab195fe49e3')
     def test_get_volume_without_passing_volume_id(self):
         # Should not be able to get volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.show_volume, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f035827-7c32-4019-9240-b4ec2dbd9dfd')
     def test_delete_invalid_volume_id(self):
         # Should not be able to delete volume when invalid ID is passed
         self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('441a1550-5d44-4b30-af0f-a6d402f52026')
     def test_delete_volume_without_passing_volume_id(self):
         # Should not be able to delete volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.delete_volume, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
     @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
@@ -183,14 +152,14 @@
                           instance_uuid=server['id'],
                           mountpoint=self.mountpoint)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f9c24e4-011d-46b5-b992-952140ce237a')
     def test_detach_volumes_with_invalid_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.detach_volume,
                           'xxx')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e0c75c74-ee34-41a9-9288-2a2051452854')
     def test_volume_extend_with_size_smaller_than_original_size(self):
         # Extend volume with smaller size than original size.
@@ -199,7 +168,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5d0b480d-e833-439f-8a5a-96ad2ed6f22f')
     def test_volume_extend_with_non_number_size(self):
         # Extend volume when size is non number.
@@ -208,7 +177,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('355218f1-8991-400a-a6bb-971239287d92')
     def test_volume_extend_with_None_size(self):
         # Extend volume with None size.
@@ -217,7 +186,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8f05a943-013c-4063-ac71-7baf561e82eb')
     def test_volume_extend_with_nonexistent_volume_id(self):
         # Extend volume size when volume is nonexistent.
@@ -225,7 +194,7 @@
         self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           data_utils.rand_uuid(), new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
     def test_volume_extend_without_passing_volume_id(self):
         # Extend volume size when passing volume id is None.
@@ -233,21 +202,21 @@
         self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           None, new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ac6084c0-0546-45f9-b284-38a367e0e0e2')
     def test_reserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.reserve_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('eb467654-3dc1-4a72-9b46-47c29d22654c')
     def test_unreserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.unreserve_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('449c4ed2-ecdd-47bb-98dc-072aeccf158c')
     def test_reserve_volume_with_negative_volume_status(self):
         # Mark volume as reserved.
@@ -259,26 +228,26 @@
         # Unmark volume as reserved.
         self.volumes_client.unreserve_volume(self.volume['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0f4aa809-8c7b-418f-8fb3-84c7a5dfc52f')
     def test_list_volumes_with_nonexistent_name(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
+        params = {'name': v_name}
         fetched_volume = self.volumes_client.list_volumes(
             params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9ca17820-a0e7-4cbd-a7fa-f4468735e359')
     def test_list_volumes_detail_with_nonexistent_name(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {self.name_field: v_name}
+        params = {'name': v_name}
         fetched_volume = \
             self.volumes_client.list_volumes(
                 detail=True, params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('143b279b-7522-466b-81be-34a87d564a7c')
     def test_list_volumes_with_invalid_status(self):
         params = {'status': 'null'}
@@ -286,7 +255,7 @@
             params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ba94b27b-be3f-496c-a00e-0283b373fa75')
     def test_list_volumes_detail_with_invalid_status(self):
         params = {'status': 'null'}
@@ -294,7 +263,3 @@
             self.volumes_client.list_volumes(detail=True,
                                              params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
-
-
-class VolumesV1NegativeTest(VolumesV2NegativeTest):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 5abda5e..8ffc99d 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -13,28 +13,26 @@
 from testtools import matchers
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
 CONF = config.CONF
 
 
-class VolumesV2SnapshotTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotTestJSON, cls).skip_checks()
+        super(VolumesSnapshotTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2SnapshotTestJSON, cls).resource_setup()
+        super(VolumesSnapshotTestJSON, cls).resource_setup()
         cls.volume_origin = cls.create_volume()
-        cls.name_field = cls.special_fields['name_field']
-        cls.descrip_field = cls.special_fields['descrip_field']
 
     @decorators.idempotent_id('b467b54c-07a4-446d-a1cf-651dedcc3ff1')
     @test.services('compute')
@@ -104,40 +102,42 @@
         self.assertEqual(self.volume_origin['id'],
                          snap_get['volume_id'],
                          "Referred volume origin mismatch")
+        self.assertEqual(self.volume_origin['size'], snap_get['size'])
 
         # Verify snapshot metadata
         self.assertThat(snap_get['metadata'].items(),
                         matchers.ContainsAll(metadata.items()))
 
         # Compare also with the output from the list action
-        tracking_data = (snapshot['id'], snapshot[self.name_field])
+        tracking_data = (snapshot['id'], snapshot['name'])
         snaps_list = self.snapshots_client.list_snapshots()['snapshots']
-        snaps_data = [(f['id'], f[self.name_field]) for f in snaps_list]
+        snaps_data = [(f['id'], f['name']) for f in snaps_list]
         self.assertIn(tracking_data, snaps_data)
 
         # Updates snapshot with new values
         new_s_name = data_utils.rand_name(
             self.__class__.__name__ + '-new-snap')
         new_desc = 'This is the new description of snapshot.'
-        params = {self.name_field: new_s_name,
-                  self.descrip_field: new_desc}
+        params = {'name': new_s_name,
+                  'description': new_desc}
         update_snapshot = self.snapshots_client.update_snapshot(
             snapshot['id'], **params)['snapshot']
         # Assert response body for update_snapshot method
-        self.assertEqual(new_s_name, update_snapshot[self.name_field])
-        self.assertEqual(new_desc, update_snapshot[self.descrip_field])
+        self.assertEqual(new_s_name, update_snapshot['name'])
+        self.assertEqual(new_desc, update_snapshot['description'])
         # Assert response body for show_snapshot method
         updated_snapshot = self.snapshots_client.show_snapshot(
             snapshot['id'])['snapshot']
-        self.assertEqual(new_s_name, updated_snapshot[self.name_field])
-        self.assertEqual(new_desc, updated_snapshot[self.descrip_field])
+        self.assertEqual(new_s_name, updated_snapshot['name'])
+        self.assertEqual(new_desc, updated_snapshot['description'])
 
         # Delete the snapshot
         self.delete_snapshot(snapshot['id'])
 
     @decorators.idempotent_id('677863d1-3142-456d-b6ac-9924f667a7f4')
     def test_volume_from_snapshot(self):
-        # Creates a volume a snapshot passing a size different from the source
+        # Creates a volume from a snapshot passing a size
+        # different from the source
         src_size = CONF.volume.volume_size
 
         src_vol = self.create_volume(size=src_size)
@@ -158,7 +158,3 @@
         # Should allow
         self.assertEqual(volume['snapshot_id'], src_snap['id'])
         self.assertEqual(volume['size'], src_size + 1)
-
-
-class VolumesV1SnapshotTestJSON(VolumesV2SnapshotTestJSON):
-    _api_version = 1
diff --git a/tempest/api/volume/test_volumes_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
index a0eaa00..507df1f 100644
--- a/tempest/api/volume/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -17,22 +17,25 @@
 CONF = config.CONF
 
 
-class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotListTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+        super(VolumesSnapshotListTestJSON, 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()
+        super(VolumesSnapshotListTestJSON, cls).resource_setup()
+        cls.snapshot_id_list = []
         volume_origin = cls.create_volume()
-        cls.name_field = cls.special_fields['name_field']
+
         # Create snapshots with params
-        for _ in range(2):
-            cls.snapshot = cls.create_snapshot(volume_origin['id'])
+        for _ in range(3):
+            snapshot = cls.create_snapshot(volume_origin['id'])
+            cls.snapshot_id_list.append(snapshot['id'])
+        cls.snapshot = snapshot
 
     def _list_by_param_values_and_assert(self, with_detail=False, **params):
         """list or list_details with given params and validates result."""
@@ -59,7 +62,7 @@
     def test_snapshots_list_with_params(self):
         """list snapshots with params."""
         # Verify list snapshots by display_name filter
-        params = {self.name_field: self.snapshot[self.name_field]}
+        params = {'name': self.snapshot['name']}
         self._list_by_param_values_and_assert(**params)
 
         # Verify list snapshots by status filter
@@ -68,21 +71,21 @@
 
         # Verify list snapshots by status and display name filter
         params = {'status': 'available',
-                  self.name_field: self.snapshot[self.name_field]}
+                  'name': self.snapshot['name']}
         self._list_by_param_values_and_assert(**params)
 
     @decorators.idempotent_id('220a1022-1fcd-4a74-a7bd-6b859156cda2')
     def test_snapshots_list_details_with_params(self):
         """list snapshot details with params."""
         # Verify list snapshot details by display_name filter
-        params = {self.name_field: self.snapshot[self.name_field]}
+        params = {'name': self.snapshot['name']}
         self._list_by_param_values_and_assert(with_detail=True, **params)
         # Verify list snapshot details by status filter
         params = {'status': 'available'}
         self._list_by_param_values_and_assert(with_detail=True, **params)
         # Verify list snapshot details by status and display name filter
         params = {'status': 'available',
-                  self.name_field: self.snapshot[self.name_field]}
+                  'name': self.snapshot['name']}
         self._list_by_param_values_and_assert(with_detail=True, **params)
 
     @decorators.idempotent_id('db4d8e0a-7a2e-41cc-a712-961f6844e896')
@@ -98,12 +101,60 @@
         self._list_snapshots_by_param_limit(limit=100000,
                                             expected_elements=len(snap_list))
 
-    @decorators.skip_because(bug='1540893')
     @decorators.idempotent_id('e3b44b7f-ae87-45b5-8a8c-66110eb24d0a')
     def test_snapshot_list_param_limit_equals_zero(self):
         # List returns zero elements
         self._list_snapshots_by_param_limit(limit=0, expected_elements=0)
 
+    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 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)
 
-class VolumesV1SnapshotLimitTestJSON(VolumesV2SnapshotListTestJSON):
-    _api_version = 1
+    @decorators.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')
+
+    @decorators.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')
+
+    @decorators.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')
+
+    @decorators.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')
+
+    @decorators.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')
+
+    @decorators.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')
+
+    @decorators.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/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 9e44379..ea5f036 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -11,24 +11,23 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.common.utils import data_utils
 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
 
 
-class VolumesV2SnapshotNegativeTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotNegativeTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotNegativeTestJSON, cls).skip_checks()
+        super(VolumesSnapshotNegativeTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e3e466af-70ab-4f4b-a967-ab04e3532ea7')
     def test_create_snapshot_with_nonexistent_volume_id(self):
         # Create a snapshot with nonexistent volume id
@@ -38,7 +37,7 @@
                           volume_id=data_utils.rand_uuid(),
                           display_name=s_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
     def test_create_snapshot_without_passing_volume_id(self):
         # Create a snapshot without passing volume id
@@ -47,7 +46,7 @@
                           self.snapshots_client.create_snapshot,
                           volume_id=None, display_name=s_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('677863d1-34f9-456d-b6ac-9924f667a7f4')
     def test_volume_from_snapshot_decreasing_size(self):
         # Creates a volume a snapshot passing a size different from the source
@@ -62,13 +61,23 @@
                           size=src_size - 1,
                           snapshot_id=src_snap['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fd92339-e22f-4591-86b4-1e2215372a40')
     def test_list_snapshot_invalid_param_limit(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.snapshots_client.list_snapshots,
                           limit='invalid')
 
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
+    def test_list_snapshots_invalid_param_sort(self):
+        self.assertRaises(lib_exc.BadRequest,
+                          self.snapshots_client.list_snapshots,
+                          sort_key='invalid')
 
-class VolumesV1SnapshotNegativeTestJSON(VolumesV2SnapshotNegativeTestJSON):
-    _api_version = 1
+    @decorators.attr(type=['negative'])
+    @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
+    def test_list_snapshots_invalid_param_marker(self):
+        self.assertRaises(lib_exc.NotFound,
+                          self.snapshots_client.list_snapshots,
+                          marker=data_utils.rand_uuid())
diff --git a/tempest/api/volume/v2/__init__.py b/tempest/api/volume/v2/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/v2/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
deleted file mode 100644
index d2328c8..0000000
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# Copyright 2013 IBM Corp.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import random
-
-from six.moves.urllib import parse
-
-from tempest.api.volume import base
-from tempest.lib import decorators
-
-
-class VolumesV2ListTestJSON(base.BaseVolumeTest):
-    """volumes v2 specific tests.
-
-    This test creates a number of 1G volumes. To run successfully,
-    ensure that the backing file for the volume group that Nova uses
-    has space for at least 3 1G volumes!
-    If you are running a Devstack environment, ensure that the
-    VOLUME_BACKING_FILE_SIZE is at least 4G in your localrc
-    """
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesV2ListTestJSON, cls).resource_setup()
-
-        # Create 3 test volumes
-        # NOTE(zhufl): When using pre-provisioned credentials, the project
-        # 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 _ in range(3):
-            volume = cls.create_volume()
-            cls.volume_id_list.append(volume['id'])
-
-    @decorators.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
-    def test_volume_list_details_with_multiple_params(self):
-        # List volumes detail using combined condition
-        def _list_details_with_multiple_params(limit=2,
-                                               status='available',
-                                               sort_dir='asc',
-                                               sort_key='id'):
-            params = {'limit': limit,
-                      'status': status,
-                      'sort_dir': sort_dir,
-                      'sort_key': sort_key
-                      }
-            fetched_volume = self.volumes_client.list_volumes(
-                detail=True, params=params)['volumes']
-            self.assertEqual(limit, len(fetched_volume),
-                             "The count of volumes is %s, expected:%s " %
-                             (len(fetched_volume), limit))
-            self.assertEqual(status, fetched_volume[0]['status'])
-            self.assertEqual(status, fetched_volume[1]['status'])
-            val0 = fetched_volume[0][sort_key]
-            val1 = fetched_volume[1][sort_key]
-            if sort_dir == 'asc':
-                self.assertLess(val0, val1,
-                                "list is not in asc order with sort_key: %s."
-                                " %s" % (sort_key, fetched_volume))
-            elif sort_dir == 'desc':
-                self.assertGreater(val0, val1,
-                                   "list is not in desc order with sort_key: "
-                                   "%s. %s" % (sort_key, fetched_volume))
-
-        _list_details_with_multiple_params()
-        _list_details_with_multiple_params(sort_dir='desc')
-
-    def _test_pagination(self, resource, ids=None, limit=1, **kwargs):
-        """Check list pagination functionality for a resource.
-
-        This method requests the list of resources and follows pagination
-        links.
-
-        If an iterable is supplied in ids it will check that all ids are
-        retrieved and that only those are listed, that we will get a next
-        link for an empty page if the number of items is divisible by used
-        limit (this is expected behavior).
-
-        We can specify number of items per request using limit argument.
-        """
-
-        # Get list method for the type of resource from the client
-        client = getattr(self, resource + '_client')
-        method = getattr(client, 'list_' + resource)
-
-        # Include limit in params for list request
-        params = kwargs.pop('params', {})
-        params['limit'] = limit
-
-        # Store remaining items we are expecting from list
-        if ids is not None:
-            remaining = list(ids)
-        else:
-            remaining = None
-
-        # Mark that the current iteration is not from a 'next' link
-        next = None
-
-        while True:
-            # Get a list page
-            response = method(params=params, **kwargs)
-
-            # If we have to check ids
-            if remaining is not None:
-                # Confirm we receive expected number of elements
-                num_expected = min(len(remaining), limit)
-                self.assertEqual(num_expected, len(response[resource]),
-                                 'Requested %(#expect)d but got %(#received)d '
-                                 % {'#expect': num_expected,
-                                    '#received': len(response[resource])})
-
-                # For each received element
-                for element in response[resource]:
-                    element_id = element['id']
-                    # Check it's one of expected ids
-                    self.assertIn(element_id,
-                                  ids,
-                                  'Id %(id)s is not in expected ids %(ids)s' %
-                                  {'id': element_id, 'ids': ids})
-                    # If not in remaining, we have received it twice
-                    self.assertIn(element_id,
-                                  remaining,
-                                  'Id %s was received twice' % element_id)
-                    # We no longer expect it
-                    remaining.remove(element_id)
-
-            # If the current iteration is from a 'next' link, check that the
-            # absolute url is the same as the one used for this request
-            if next:
-                self.assertEqual(next, response.response['content-location'])
-
-            # Get next from response
-            next = None
-            for link in response.get(resource + '_links', ()):
-                if link['rel'] == 'next':
-                    next = link['href']
-                    break
-
-            # Check if we have next and we shouldn't or the other way around
-            if remaining is not None:
-                if remaining or (num_expected and len(ids) % limit == 0):
-                    self.assertIsNotNone(next, 'Missing link to next page')
-                else:
-                    self.assertIsNone(next, 'Unexpected link to next page')
-
-            # If we can follow to the next page, get params from url to make
-            # request in the form of a relative URL
-            if next:
-                params = parse.urlparse(next).query
-
-            # If cannot follow make sure it's because we have finished
-            else:
-                self.assertEqual([], remaining or [],
-                                 'No more pages reported, but still '
-                                 'missing ids %s' % remaining)
-                break
-
-    @decorators.idempotent_id('e9138a2c-f67b-4796-8efa-635c196d01de')
-    def test_volume_list_details_pagination(self):
-        self._test_pagination('volumes', ids=self.volume_id_list, detail=True)
-
-    @decorators.idempotent_id('af55e775-8e4b-4feb-8719-215c43b0238c')
-    def test_volume_list_pagination(self):
-        self._test_pagination('volumes', ids=self.volume_id_list, detail=False)
-
-    @decorators.idempotent_id('46eff077-100b-427f-914e-3db2abcdb7e2')
-    @decorators.skip_because(bug='1572765')
-    def test_volume_list_with_detail_param_marker(self):
-        # Choosing a random volume from a list of volumes for 'marker'
-        # parameter
-        random_volume = random.choice(self.volume_id_list)
-
-        params = {'marker': random_volume}
-
-        # Running volume list using marker parameter
-        vol_with_marker = self.volumes_client.list_volumes(
-            detail=True, params=params)['volumes']
-
-        # Fetching the index of the random volume from volume_id_list
-        index_marker = self.volume_id_list.index(random_volume)
-
-        # The expected list with marker parameter
-        verify_volume_list = self.volume_id_list[:index_marker]
-
-        failed_msg = "Failed to list volume details by marker"
-
-        # Validating the expected list is the same like the observed list
-        self.assertEqual(verify_volume_list,
-                         map(lambda x: x['id'],
-                             vol_with_marker[::-1]), failed_msg)
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_list.py b/tempest/api/volume/v2/test_volumes_snapshots_list.py
deleted file mode 100644
index d385f65..0000000
--- a/tempest/api/volume/v2/test_volumes_snapshots_list.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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.lib import decorators
-
-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
-        volume_origin = cls.create_volume()
-        # Create 3 snapshots
-        for _ in range(3):
-            snapshot = cls.create_snapshot(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)
-
-    @decorators.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')
-
-    @decorators.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')
-
-    @decorators.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')
-
-    @decorators.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')
-
-    @decorators.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')
-
-    @decorators.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')
-
-    @decorators.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/api/volume/v2/test_volumes_snapshots_negative.py b/tempest/api/volume/v2/test_volumes_snapshots_negative.py
deleted file mode 100644
index e5581b9..0000000
--- a/tempest/api/volume/v2/test_volumes_snapshots_negative.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2017 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.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
-
-
-class VolumesV2SnapshotNegativeTest(base.BaseVolumeTest):
-
-    @classmethod
-    def skip_checks(cls):
-        super(VolumesV2SnapshotNegativeTest, cls).skip_checks()
-        if not CONF.volume_feature_enabled.snapshot:
-            raise cls.skipException("Cinder volume snapshots are disabled")
-
-    @test.attr(type=['negative'])
-    @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
-    def test_list_snapshots_invalid_param_sort(self):
-        self.assertRaises(lib_exc.BadRequest,
-                          self.snapshots_client.list_snapshots,
-                          sort_key='invalid')
-
-    @test.attr(type=['negative'])
-    @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
-    def test_list_snapshots_invalid_param_marker(self):
-        self.assertRaises(lib_exc.NotFound,
-                          self.snapshots_client.list_snapshots,
-                          marker=data_utils.rand_uuid())
diff --git a/tempest/api/volume/v3/__init__.py b/tempest/api/volume/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/v3/base.py b/tempest/api/volume/v3/base.py
deleted file mode 100644
index 31fc1eb..0000000
--- a/tempest/api/volume/v3/base.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2016 Andrew Kerr
-# 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 api_microversion_fixture
-from tempest.api.volume import base
-from tempest import config
-from tempest.lib.common import api_version_utils
-
-CONF = config.CONF
-
-
-class VolumesV3Test(api_version_utils.BaseMicroversionTest,
-                    base.BaseVolumeTest):
-    """Base test case class for all v3 Cinder API tests."""
-
-    _api_version = 3
-
-    @classmethod
-    def skip_checks(cls):
-        super(VolumesV3Test, cls).skip_checks()
-        api_version_utils.check_skip_with_microversion(
-            cls.min_microversion, cls.max_microversion,
-            CONF.volume.min_microversion, CONF.volume.max_microversion)
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesV3Test, cls).resource_setup()
-        cls.request_microversion = (
-            api_version_utils.select_request_microversion(
-                cls.min_microversion,
-                CONF.volume.min_microversion))
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV3Test, cls).setup_clients()
-        cls.messages_client = cls.os.volume_v3_messages_client
-
-    def setUp(self):
-        super(VolumesV3Test, self).setUp()
-        self.useFixture(api_microversion_fixture.APIMicroversionFixture(
-            self.request_microversion))
-
-
-class VolumesV3AdminTest(VolumesV3Test,
-                         base.BaseVolumeAdminTest):
-    """Base test case class for all v3 Volume Admin API tests."""
-
-    credentials = ['primary', 'admin']
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV3AdminTest, cls).setup_clients()
-        cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
-        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
diff --git a/tempest/clients.py b/tempest/clients.py
index 9cb918a..dbaacda 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -125,6 +125,8 @@
                 self.image_v2.NamespacePropertiesClient()
             self.namespace_tags_client = \
                 self.image_v2.NamespaceTagsClient()
+            self.image_versions_client = \
+                self.image_v2.VersionsClient()
 
     def _set_compute_clients(self):
         self.agents_client = self.compute.AgentsClient()
@@ -157,7 +159,6 @@
         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 = (
@@ -166,11 +167,10 @@
 
         # NOTE: The following client needs special timeout values because
         # the API is a proxy for the other component.
-        params_volume = {}
-        for _key in ('build_interval', 'build_timeout'):
-            _value = self.parameters['volume'].get(_key)
-            if _value:
-                params_volume[_key] = _value
+        params_volume = {
+            'build_interval': CONF.volume.build_interval,
+            'build_timeout': CONF.volume.build_timeout
+        }
         self.volumes_extensions_client = self.compute.VolumesClient(
             **params_volume)
         self.compute_versions_client = self.compute.VersionsClient(
@@ -227,6 +227,8 @@
         self.groups_client = self.identity_v3.GroupsClient(**params_v3)
         self.identity_versions_v3_client = self.identity_v3.VersionsClient(
             **params_v3)
+        self.oauth_consumers_client = self.identity_v3.OAUTHConsumerClient(
+            **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
@@ -260,9 +262,11 @@
         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.volume_manage_v2_client = self.volume_v2.VolumeManageClient()
         self.volumes_client = self.volume_v1.VolumesClient()
         self.volumes_v2_client = self.volume_v2.VolumesClient()
         self.volume_v3_messages_client = self.volume_v3.MessagesClient()
+        self.volume_v3_versions_client = self.volume_v3.VersionsClient()
         self.volume_types_client = self.volume_v1.TypesClient()
         self.volume_types_v2_client = self.volume_v2.TypesClient()
         self.volume_hosts_client = self.volume_v1.HostsClient()
@@ -281,6 +285,8 @@
             self.volume_v2.CapabilitiesClient()
         self.volume_scheduler_stats_v2_client = \
             self.volume_v2.SchedulerStatsClient()
+        self.volume_transfers_v2_client = \
+            self.volume_v2.TransfersClient()
 
     def _set_object_storage_clients(self):
         # Mandatory parameters (always defined)
@@ -288,6 +294,8 @@
 
         self.account_client = object_storage.AccountClient(self.auth_provider,
                                                            **params)
+        self.bulk_client = object_storage.BulkMiddlewareClient(
+            self.auth_provider, **params)
         self.capabilities_client = object_storage.CapabilitiesClient(
             self.auth_provider, **params)
         self.container_client = object_storage.ContainerClient(
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index a632726..f1c0a3e 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -105,7 +105,7 @@
 
     def _filter_by_tenant_id(self, item_list):
         if (item_list is None
-                or len(item_list) == 0
+                or not item_list
                 or not hasattr(self, 'tenant_id')
                 or self.tenant_id is None
                 or 'tenant_id' not in item_list[0]):
diff --git a/tempest/cmd/config-generator.tempest.conf b/tempest/cmd/config-generator.tempest.conf
index d718f93..b8f16d9 100644
--- a/tempest/cmd/config-generator.tempest.conf
+++ b/tempest/cmd/config-generator.tempest.conf
@@ -2,7 +2,4 @@
 output_file = etc/tempest.conf.sample
 namespace = tempest.config
 namespace = oslo.concurrency
-namespace = oslo.i18n
 namespace = oslo.log
-namespace = oslo.serialization
-namespace = oslo.utils
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 99da983..9587ffe 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -13,14 +13,27 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 
+import base64
+import socket
+import struct
+import textwrap
+
+import six
+from six.moves.urllib import parse as urlparse
+
 from oslo_log import log as logging
 from oslo_utils import excutils
 
 from tempest.common import fixed_network
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common import rest_client
+from tempest.lib.common.utils import data_utils
+
+if six.PY2:
+    ord_func = ord
+else:
+    ord_func = int
 
 CONF = config.CONF
 
@@ -113,14 +126,23 @@
             if wait_until is None:
                 wait_until = 'ACTIVE'
 
+        if 'user_data' not in kwargs:
+            # If nothing overrides the default user data script then run
+            # a simple script on the host to print networking info. This is
+            # to aid in debugging ssh failures.
+            script = '''
+                     #!/bin/sh
+                     echo "Printing {user} user authorized keys"
+                     cat ~{user}/.ssh/authorized_keys || true
+                     '''.format(user=CONF.validation.image_ssh_user)
+            script_clean = textwrap.dedent(script).lstrip().encode('utf8')
+            script_b64 = base64.b64encode(script_clean)
+            kwargs['user_data'] = script_b64
+
     if volume_backed:
         volume_name = data_utils.rand_name(__name__ + '-volume')
         volumes_client = clients.volumes_v2_client
-        name_field = 'name'
-        if not CONF.volume_feature_enabled.api_v2:
-            volumes_client = clients.volumes_client
-            name_field = 'display_name'
-        params = {name_field: volume_name,
+        params = {'name': volume_name,
                   'imageRef': image_id,
                   'size': CONF.volume.volume_size}
         volume = volumes_client.create_volume(**params)
@@ -210,3 +232,87 @@
             servers_client.shelve_offload_server(server_id)
             waiters.wait_for_server_status(servers_client, server_id,
                                            'SHELVED_OFFLOADED')
+
+
+def create_websocket(url):
+    url = urlparse.urlparse(url)
+    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    client_socket.connect((url.hostname, url.port))
+    # Turn the Socket into a WebSocket to do the communication
+    return _WebSocket(client_socket, url)
+
+
+class _WebSocket(object):
+    def __init__(self, client_socket, url):
+        """Contructor for the WebSocket wrapper to the socket."""
+        self._socket = client_socket
+        # Upgrade the HTTP connection to a WebSocket
+        self._upgrade(url)
+
+    def receive_frame(self):
+        """Wrapper for receiving data to parse the WebSocket frame format"""
+        # We need to loop until we either get some bytes back in the frame
+        # or no data was received (meaning the socket was closed).  This is
+        # done to handle the case where we get back some empty frames
+        while True:
+            header = self._socket.recv(2)
+            # If we didn't receive any data, just return None
+            if not header:
+                return None
+            # We will make the assumption that we are only dealing with
+            # frames less than 125 bytes here (for the negotiation) and
+            # that only the 2nd byte contains the length, and since the
+            # server doesn't do masking, we can just read the data length
+            if ord_func(header[1]) & 127 > 0:
+                return self._socket.recv(ord_func(header[1]) & 127)
+
+    def send_frame(self, data):
+        """Wrapper for sending data to add in the WebSocket frame format."""
+        frame_bytes = list()
+        # For the first byte, want to say we are sending binary data (130)
+        frame_bytes.append(130)
+        # Only sending negotiation data so don't need to worry about > 125
+        # We do need to add the bit that says we are masking the data
+        frame_bytes.append(len(data) | 128)
+        # We don't really care about providing a random mask for security
+        # So we will just hard-code a value since a test program
+        mask = [7, 2, 1, 9]
+        for i in range(len(mask)):
+            frame_bytes.append(mask[i])
+        # Mask each of the actual data bytes that we are going to send
+        for i in range(len(data)):
+            frame_bytes.append(ord_func(data[i]) ^ mask[i % 4])
+        # Convert our integer list to a binary array of bytes
+        frame_bytes = struct.pack('!%iB' % len(frame_bytes), * frame_bytes)
+        self._socket.sendall(frame_bytes)
+
+    def close(self):
+        """Helper method to close the connection."""
+        # Close down the real socket connection and exit the test program
+        if self._socket is not None:
+            self._socket.shutdown(1)
+            self._socket.close()
+            self._socket = None
+
+    def _upgrade(self, url):
+        """Upgrade the HTTP connection to a WebSocket and verify."""
+        # The real request goes to the /websockify URI always
+        reqdata = 'GET /websockify HTTP/1.1\r\n'
+        reqdata += 'Host: %s:%s\r\n' % (url.hostname, url.port)
+        # Tell the HTTP Server to Upgrade the connection to a WebSocket
+        reqdata += 'Upgrade: websocket\r\nConnection: Upgrade\r\n'
+        # The token=xxx is sent as a Cookie not in the URI
+        reqdata += 'Cookie: %s\r\n' % url.query
+        # Use a hard-coded WebSocket key since a test program
+        reqdata += 'Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n'
+        reqdata += 'Sec-WebSocket-Version: 13\r\n'
+        # We are choosing to use binary even though browser may do Base64
+        reqdata += 'Sec-WebSocket-Protocol: binary\r\n\r\n'
+        # Send the HTTP GET request and get the response back
+        self._socket.sendall(reqdata.encode('utf8'))
+        self.response = data = self._socket.recv(4096)
+        # Loop through & concatenate all of the data in the response body
+        while data and self.response.find(b'\r\n\r\n') < 0:
+            data = self._socket.recv(4096)
+            self.response += data
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index a92d16a..8053cac 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -241,7 +241,7 @@
 
     def _get_creds(self, roles=None):
         useable_hashes = self._get_match_hash_list(roles)
-        if len(useable_hashes) == 0:
+        if not useable_hashes:
             msg = 'No users configured for type/roles %s' % roles
             raise lib_exc.InvalidCredentials(msg)
         free_hash = self._get_free_hash(useable_hashes)
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index b7c776b..9319d2a 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -11,17 +11,12 @@
 #    under the License.
 
 import re
-import sys
 import time
 
-import netaddr
-import six
-
 from oslo_log import log as logging
 
 from tempest import config
-from tempest.lib.common import ssh
-from tempest.lib.common.utils import test_utils
+from tempest.lib.common.utils.linux import remote_client
 import tempest.lib.exceptions
 
 CONF = config.CONF
@@ -29,39 +24,11 @@
 LOG = logging.getLogger(__name__)
 
 
-def debug_ssh(function):
-    """Decorator to generate extra debug info in case off SSH failure"""
-    def wrapper(self, *args, **kwargs):
-        try:
-            return function(self, *args, **kwargs)
-        except tempest.lib.exceptions.SSHTimeout:
-            try:
-                original_exception = sys.exc_info()
-                caller = test_utils.find_test_caller() or "not found"
-                if self.server:
-                    msg = 'Caller: %s. Timeout trying to ssh to server %s'
-                    LOG.debug(msg, caller, self.server)
-                    if self.log_console and self.servers_client:
-                        try:
-                            msg = 'Console log for server %s: %s'
-                            console_log = (
-                                self.servers_client.get_console_output(
-                                    self.server['id'])['output'])
-                            LOG.debug(msg, self.server['id'], console_log)
-                        except Exception:
-                            msg = 'Could not get console_log for server %s'
-                            LOG.debug(msg, self.server['id'])
-                # re-raise the original ssh timeout exception
-                six.reraise(*original_exception)
-            finally:
-                # Delete the traceback to avoid circular references
-                _, _, trace = original_exception
-                del trace
-    return wrapper
+class RemoteClient(remote_client.RemoteClient):
 
-
-class RemoteClient(object):
-
+    # TODO(oomichi): Make this class deprecated after migrating
+    #                necessary methods to tempest.lib and cleaning
+    #                unnecessary methods up from this class.
     def __init__(self, ip_address, username, password=None, pkey=None,
                  server=None, servers_client=None):
         """Executes commands in a VM over ssh
@@ -73,36 +40,18 @@
         :param server: server dict, used for debugging purposes
         :param servers_client: servers client, used for debugging purposes
         """
-        self.server = server
-        self.servers_client = servers_client
+        super(RemoteClient, self).__init__(
+            ip_address, username, password=password, pkey=pkey,
+            server=server, servers_client=servers_client,
+            ssh_timeout=CONF.validation.ssh_timeout,
+            connect_timeout=CONF.validation.connect_timeout,
+            console_output_enabled=CONF.compute_feature_enabled.console_output,
+            ssh_shell_prologue=CONF.validation.ssh_shell_prologue,
+            ping_count=CONF.validation.ping_count,
+            ping_size=CONF.validation.ping_size)
 
-        ssh_timeout = CONF.validation.ssh_timeout
-        connect_timeout = CONF.validation.connect_timeout
-        self.log_console = CONF.compute_feature_enabled.console_output
-        self.ssh_shell_prologue = CONF.validation.ssh_shell_prologue
-        self.ping_count = CONF.validation.ping_count
-        self.ping_size = CONF.validation.ping_size
-
-        self.ssh_client = ssh.Client(ip_address, username, password,
-                                     ssh_timeout, pkey=pkey,
-                                     channel_timeout=connect_timeout)
-
-    @debug_ssh
-    def exec_command(self, cmd):
-        # Shell options below add more clearness on failures,
-        # path is extended for some non-cirros guest oses (centos7)
-        cmd = self.ssh_shell_prologue + " " + cmd
-        LOG.debug("Remote command: %s", cmd)
-        return self.ssh_client.exec_command(cmd)
-
-    @debug_ssh
-    def validate_authentication(self):
-        """Validate ssh connection and authentication
-
-           This method raises an Exception when the validation fails.
-        """
-        self.ssh_client.test_connection_auth()
-
+    # Note that this method will not work on SLES11 guests, as they do
+    # not support the TYPE column on lsblk
     def get_disks(self):
         # Select root disk devices as shown by lsblk
         command = 'lsblk -lb --nodeps'
@@ -132,25 +81,6 @@
         cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
         return self.exec_command(cmd)
 
-    def ping_host(self, host, count=None, size=None, nic=None):
-        if count is None:
-            count = self.ping_count
-        if size is None:
-            size = self.ping_size
-
-        addr = netaddr.IPAddress(host)
-        cmd = 'ping6' if addr.version == 6 else 'ping'
-        if nic:
-            cmd = 'sudo {cmd} -I {nic}'.format(cmd=cmd, nic=nic)
-        cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host)
-        return self.exec_command(cmd)
-
-    def set_mac_address(self, nic, address):
-        self.set_nic_state(nic=nic, state="down")
-        cmd = "sudo ip link set dev {0} address {1}".format(nic, address)
-        self.exec_command(cmd)
-        self.set_nic_state(nic=nic, state="up")
-
     def get_mac_address(self, nic=""):
         show_nic = "show {nic} ".format(nic=nic) if nic else ""
         cmd = "ip addr %s| awk '/ether/ {print $2}'" % show_nic
@@ -166,15 +96,6 @@
         nic = self.exec_command(cmd)
         return nic.strip().strip(":").lower()
 
-    def assign_static_ip(self, nic, addr, network_mask_bits=28):
-        cmd = "sudo ip addr add {ip}/{mask} dev {nic}".format(
-            ip=addr, mask=network_mask_bits, nic=nic)
-        return self.exec_command(cmd)
-
-    def set_nic_state(self, nic, state="up"):
-        cmd = "sudo ip link set {nic} {state}".format(nic=nic, state=state)
-        return self.exec_command(cmd)
-
     def get_dns_servers(self):
         cmd = 'cat /etc/resolv.conf'
         resolve_file = self.exec_command(cmd).strip().split('\n')
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index 88697c4..b15796f 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -15,7 +15,7 @@
 
 from tempest import config
 
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 
 CONF = config.CONF
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 3e5600c..9c83c99 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -261,16 +261,16 @@
         time.sleep(client.build_interval)
 
 
-def wait_for_interface_status(client, server, port_id, status):
+def wait_for_interface_status(client, server_id, port_id, status):
     """Waits for an interface to reach a given status."""
-    body = (client.show_interface(server, port_id)
+    body = (client.show_interface(server_id, port_id)
             ['interfaceAttachment'])
     interface_status = body['port_state']
     start = int(time.time())
 
     while(interface_status != status):
         time.sleep(client.build_interval)
-        body = (client.show_interface(server, port_id)
+        body = (client.show_interface(server_id, port_id)
                 ['interfaceAttachment'])
         interface_status = body['port_state']
 
diff --git a/tempest/config.py b/tempest/config.py
index b79f502..00c69b0 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -217,14 +217,6 @@
                      "entry all which indicates every extension is enabled. "
                      "Empty list indicates all extensions are disabled. "
                      "To get the list of extensions run: 'keystone discover'"),
-    # 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"),
     # TODO(rodrigods): This is a feature flag for bug 1590578 which is fixed
     # in Newton and Ocata. This option can be removed after Mitaka is end of
     # life.
@@ -291,7 +283,9 @@
     cfg.StrOpt('volume_device_name',
                default='vdb',
                help="Expected device name when a volume is attached to "
-                    "an instance"),
+                    "an instance. Not all hypervisors guarantee that they "
+                    "will respect the user defined device name, tests may "
+                    "fail if inappropriate device name is set."),
     cfg.IntOpt('shelved_offload_time',
                default=0,
                help='Time in seconds before a shelved instance is eligible '
@@ -334,15 +328,6 @@
                                       title="Enabled Compute Service Features")
 
 ComputeFeaturesGroup = [
-    # 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=True,
-                help='Does the test environment support creating ports in a '
-                     '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"),
@@ -384,6 +369,11 @@
     cfg.BoolOpt('live_migration',
                 default=True,
                 help="Does the test environment support live migration?"),
+    cfg.BoolOpt('live_migrate_back_and_forth',
+                default=False,
+                help="Does the test environment support live migrating "
+                     "VM back and forth between different versions of "
+                     "nova-compute?"),
     cfg.BoolOpt('metadata_service',
                 default=True,
                 help="Does the test environment support metadata service? "
@@ -503,7 +493,7 @@
                      "users can specify."),
     cfg.ListOpt('disk_formats',
                 default=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2',
-                         'vdi', 'iso'],
+                         'vdi', 'iso', 'vhdx'],
                 help="A list of image's disk formats "
                      "users can specify.")
 ]
@@ -514,14 +504,27 @@
 ImageFeaturesGroup = [
     cfg.BoolOpt('api_v2',
                 default=True,
-                help="Is the v2 image API enabled"),
+                help="Is the v2 image API enabled",
+                deprecated_for_removal=True,
+                deprecated_reason='Glance v1 APIs are deprecated and v2 APIs '
+                                  'are current one. In future, Tempest will '
+                                  'test v2 APIs only so this config option '
+                                  'will be removed.'),
     cfg.BoolOpt('api_v1',
                 default=True,
-                help="Is the v1 image API enabled"),
+                help="Is the v1 image API enabled",
+                deprecated_for_removal=True,
+                deprecated_reason='Glance v1 APIs are deprecated and v2 APIs '
+                                  'are current one. In future, Tempest will '
+                                  'test v2 APIs only so this config option '
+                                  'will be removed.'),
     cfg.BoolOpt('deactivate_image',
                 default=False,
                 help="Is the deactivate-image feature enabled."
-                     " The feature has been integrated since Kilo."),
+                     " The feature has been integrated since Kilo.",
+                deprecated_for_removal=True,
+                deprecated_reason="All supported versions of OpenStack now "
+                                  "support the 'deactivate_image' feature"),
 ]
 
 network_group = cfg.OptGroup(name='network',
@@ -598,15 +601,6 @@
                 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,
-                help="Whether or not to create internal network, subnet, "
-                     "port and add network interface to distributed router "
-                     "in L3 agent scheduler test. Extra resources need to be "
-                     "provisioned in order to bind router to L3 agent in the "
-                     "Liberty release or older, and are not required since "
-                     "the Mitaka release.")
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -668,9 +662,7 @@
                help='Default IP version for ssh connections.'),
     cfg.IntOpt('ping_timeout',
                default=120,
-               help='Timeout in seconds to wait for ping to succeed.',
-               deprecated_opts=[cfg.DeprecatedOpt('ping_timeout',
-                                                  group='compute')]),
+               help='Timeout in seconds to wait for ping to succeed.'),
     cfg.IntOpt('connect_timeout',
                default=60,
                help='Timeout in seconds to wait for the TCP connection to be '
@@ -680,13 +672,7 @@
                help='Timeout in seconds to wait for the ssh banner.'),
     cfg.StrOpt('image_ssh_user',
                default="root",
-               help="User name used to authenticate to an instance.",
-               deprecated_opts=[cfg.DeprecatedOpt('image_ssh_user',
-                                                  group='compute'),
-                                cfg.DeprecatedOpt('ssh_user',
-                                                  group='compute'),
-                                cfg.DeprecatedOpt('ssh_user',
-                                                  group='scenario')]),
+               help="User name used to authenticate to an instance."),
     cfg.StrOpt('image_ssh_password',
                default="password",
                help="Password used to authenticate to an instance."),
@@ -711,9 +697,7 @@
     cfg.StrOpt('network_for_ssh',
                default='public',
                help="Network used for SSH connections. Ignored if "
-                    "connect_method=floating.",
-               deprecated_opts=[cfg.DeprecatedOpt('network_for_ssh',
-                                                  group='compute')]),
+                    "connect_method=floating."),
 ]
 
 volume_group = cfg.OptGroup(name='volume',
@@ -757,6 +741,12 @@
     cfg.IntOpt('volume_size',
                default=1,
                help='Default size in GB for volumes created by volumes tests'),
+    cfg.ListOpt('manage_volume_ref',
+                default=['source-name', 'volume-%s'],
+                help="A reference to existing volume for volume manage. "
+                     "It contains two elements, the first is ref type "
+                     "(like 'source-name', 'source-id', etc), the second is "
+                     "volume name template used in storage backend"),
     cfg.StrOpt('min_microversion',
                default=None,
                help="Lower version of the test target microversion range. "
@@ -796,14 +786,21 @@
     cfg.BoolOpt('manage_snapshot',
                 default=False,
                 help='Runs Cinder manage snapshot tests'),
+    cfg.BoolOpt('manage_volume',
+                default=False,
+                help='Runs Cinder manage volume tests'),
     cfg.ListOpt('api_extensions',
                 default=['all'],
                 help='A list of enabled volume extensions with a special '
                      'entry all which indicates every extension is enabled. '
                      'Empty list indicates all extensions are disabled'),
     cfg.BoolOpt('api_v1',
-                default=True,
-                help="Is the v1 volume API enabled"),
+                default=False,
+                help="Is the v1 volume API enabled",
+                deprecated_for_removal=True,
+                deprecated_reason="The v1 volume API has been deprecated "
+                                  "since Juno release, and the API will be "
+                                  "removed."),
     cfg.BoolOpt('api_v2',
                 default=True,
                 help="Is the v2 volume API enabled"),
@@ -984,9 +981,6 @@
     cfg.BoolOpt('heat',
                 default=False,
                 help="Whether or not Heat is expected to be available"),
-    cfg.BoolOpt('sahara',
-                default=False,
-                help="Whether or not Sahara is expected to be available"),
 ]
 
 debug_group = cfg.OptGroup(name="debug",
@@ -1090,6 +1084,12 @@
         return getattr(_CONF, attr)
 
     def _set_attrs(self):
+        # This methods ensures that config options in Tempest as well as
+        # in Tempest plugins can be accessed via:
+        #     CONF.<normalised_group_name>.<key_name>
+        # where:
+        #     normalised_group_name = group_name.replace('-', '_')
+        # Attributes are set at __init__ time *only* for known option groups
         self.auth = _CONF.auth
         self.compute = _CONF.compute
         self.compute_feature_enabled = _CONF['compute-feature-enabled']
@@ -1111,6 +1111,23 @@
         self.service_available = _CONF.service_available
         self.debug = _CONF.debug
         logging.tempest_set_log_file('tempest.log')
+        # Setting attributes for plugins
+        # NOTE(andreaf) Plugins have no access to the TempestConfigPrivate
+        # instance at discovery time, so they have no way of setting these
+        # aliases themselves.
+        ext_plugins = plugins.TempestTestPluginManager()
+        for group, _ in ext_plugins.get_plugin_options_list():
+            if isinstance(group, cfg.OptGroup):
+                # If we have an OptGroup
+                group_name = group.name
+                group_dest = group.dest
+            else:
+                # If we have a group name as a string
+                group_name = group
+                group_dest = group.replace('-', '_')
+            # NOTE(andreaf) We can set the attribute safely here since in
+            # case of name conflict we would not have reached this point.
+            setattr(self, group_dest, _CONF[group_name])
 
     def __init__(self, parse_conf=True, config_path=None):
         """Initialize a configuration from a conf directory and conf file."""
@@ -1188,6 +1205,12 @@
             # loaded, options registered, and _config is set.
             _register_tempest_service_clients()
 
+            # Registering service clients and pushing their configuration to
+            # the service clients register. Doing this in the config module
+            # ensures that the configuration is available by the time we
+            # discover tests from plugins.
+            plugins.TempestTestPluginManager()._register_service_clients()
+
         return getattr(self._config, attr)
 
     def set_config_path(self, path):
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index f48d7ac..a437761 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -17,10 +17,6 @@
 from tempest.lib import exceptions
 
 
-class InvalidServiceTag(exceptions.TempestException):
-    message = "Invalid service tag"
-
-
 class BuildErrorException(exceptions.TempestException):
     message = "Server %(server_id)s failed to build and is in ERROR status"
 
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index be875ee..0e7e894 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -1,4 +1 @@
 ./tempest/services/object_storage/object_client.py
-./tempest/services/volume/base/base_qos_client.py
-./tempest/services/volume/base/base_backups_client.py
-./tempest/services/baremetal/base.py
diff --git a/tempest/hacking/ignored_list_T111.txt b/tempest/hacking/ignored_list_T111.txt
deleted file mode 100644
index 8017e76..0000000
--- a/tempest/hacking/ignored_list_T111.txt
+++ /dev/null
@@ -1 +0,0 @@
-./tempest/services/baremetal/base.py
diff --git a/tempest/lib/api_schema/response/compute/v2_1/quotas.py b/tempest/lib/api_schema/response/compute/v2_1/quotas.py
index 7953983..44f5bdf 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/quotas.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/quotas.py
@@ -60,6 +60,124 @@
 get_quota_set['response_body']['properties']['quota_set']['required'].extend([
     'id'])
 
+get_quota_set_details = copy.deepcopy(get_quota_set)
+get_quota_set_details['response_body']['properties']['quota_set'][
+    'properties'] = {
+    'id': {'type': 'string'},
+    'instances': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'cores': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'ram': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'floating_ips': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'fixed_ips': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'metadata_items': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'key_pairs': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'security_groups': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'security_group_rules': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'server_group_members': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'server_groups': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_files': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_file_content_bytes': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    },
+    'injected_file_path_bytes': {
+        'type': 'object',
+        'properties': {
+            'reserved': {'type': 'integer'},
+            'limit': {'type': 'integer'},
+            'in_use': {'type': 'integer'}
+        }
+    }
+}
+
 delete_quota = {
     'status_code': [202]
 }
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 4ccca6f..33a7757 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -100,8 +100,10 @@
                 'id': {'type': 'string'},
                 'links': parameter_types.links
             },
-            'additionalProperties': False,
-            'required': ['id', 'links']
+            # NOTE(gmann): This will be empty object if there is no
+            # flavor info present in DB. This can happen when flavor info is
+            # deleted after server creation.
+            'additionalProperties': False
         },
         'fault': {
             'type': 'object',
@@ -564,3 +566,19 @@
 update_attached_volume = {
     'status_code': [202]
 }
+
+evacuate_server = {
+    'status_code': [200]
+}
+
+evacuate_server_with_admin_pass = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'adminPass': {'type': 'string'}
+        },
+        'additionalProperties': False,
+        'required': ['adminPass']
+    }
+}
diff --git a/tempest/lib/api_schema/response/compute/v2_26/servers.py b/tempest/lib/api_schema/response/compute/v2_26/servers.py
index d873402..b03bdf6 100644
--- a/tempest/lib/api_schema/response/compute/v2_26/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_26/servers.py
@@ -52,12 +52,7 @@
     'response_body': {
         'type': 'object',
         'properties': {
-            'tags': {
-                'type': 'array',
-                'items': {
-                    'type': 'string'
-                }
-            }
+            'tags': tag_items,
         },
         'additionalProperties': False,
         'required': ['tags']
diff --git a/tempest/api/volume/admin/v2/__init__.py b/tempest/lib/api_schema/response/volume/__init__.py
similarity index 100%
copy from tempest/api/volume/admin/v2/__init__.py
copy to tempest/lib/api_schema/response/volume/__init__.py
diff --git a/tempest/lib/api_schema/response/volume/versions.py b/tempest/lib/api_schema/response/volume/versions.py
new file mode 100644
index 0000000..2391a8c
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/versions.py
@@ -0,0 +1,60 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+list_versions = {
+    'status_code': [300],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'versions': {
+                'type': 'array',
+                'items': {
+                    'type': 'object',
+                    'properties': {
+                        'status': {'type': 'string'},
+                        'updated': {'type': 'string'},
+                        'id': {'type': 'string'},
+                        'links': {
+                            'type': 'array',
+                            'items': {
+                                'type': 'object',
+                                'properties': {
+                                    'href': {'type': 'string',
+                                             'format': 'uri'},
+                                    'rel': {'type': 'string'},
+                                    'type': {'type': 'string'},
+                                },
+                                'required': ['href', 'rel']
+                            }
+                        },
+                        'min_version': {'type': 'string'},
+                        'version': {'type': 'string'},
+                        'media-types': {
+                            'type': 'array',
+                            'properties': {
+                                'base': {'type': 'string'},
+                                'type': {'type': 'string'}
+                            },
+                            'required': ['base', 'type']
+                        }
+                    },
+                    'required': ['status', 'updated', 'id', 'links',
+                                 'min_version', 'version', 'media-types']
+                }
+            }
+        },
+        'required': ['versions'],
+    }
+}
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 83aa405..ab4308f 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -539,18 +539,18 @@
 
         # Select entries with matching service type
         service_catalog = [ep for ep in catalog if ep['type'] == service]
-        if len(service_catalog) > 0:
+        if service_catalog:
             if name is not None:
                 service_catalog = (
                     [ep for ep in service_catalog if ep['name'] == name])
-                if len(service_catalog) > 0:
+                if service_catalog:
                     service_catalog = service_catalog[0]['endpoints']
                 else:
                     raise exceptions.EndpointNotFound(name)
             else:
                 service_catalog = service_catalog[0]['endpoints']
         else:
-            if len(catalog) == 0 and service == 'identity':
+            if not catalog and service == 'identity':
                 # NOTE(andreaf) If there's no catalog at all and the service
                 # is identity, it's a valid use case. Having a non-empty
                 # catalog with no identity in it is not valid instead.
@@ -571,13 +571,13 @@
         # Filter by endpoint type (interface)
         filtered_catalog = [ep for ep in service_catalog if
                             ep['interface'] == endpoint_type]
-        if len(filtered_catalog) == 0:
+        if not filtered_catalog:
             # No matching type, keep all and try matching by region at least
             filtered_catalog = service_catalog
         # Filter by region
         filtered_catalog = [ep for ep in filtered_catalog if
                             ep['region'] == region]
-        if len(filtered_catalog) == 0:
+        if not filtered_catalog:
             # No matching region (or name), take the first endpoint
             filtered_catalog = [service_catalog[0]]
         # There should be only one match. If not take the first.
diff --git a/tempest/lib/cli/output_parser.py b/tempest/lib/cli/output_parser.py
index 716f374..2edd5c1 100644
--- a/tempest/lib/cli/output_parser.py
+++ b/tempest/lib/cli/output_parser.py
@@ -114,7 +114,7 @@
                 label = line
             else:
                 LOG.warning('Invalid line between tables: %s', line)
-    if len(table_) > 0:
+    if table_:
         LOG.warning('Missing end of table')
 
     return tables_
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index eafde44..101d692 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -29,7 +29,7 @@
 DECORATOR_MODULE = 'decorators'
 DECORATOR_NAME = 'idempotent_id'
 DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
-IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
+IMPORT_LINE = 'from tempest.lib import %s' % DECORATOR_MODULE
 DECORATOR_TEMPLATE = "@%s.%s('%%s')" % (DECORATOR_MODULE,
                                         DECORATOR_NAME)
 UNIT_TESTS_EXCLUDE = 'tempest.tests'
@@ -355,7 +355,7 @@
     if errors:
         sys.exit("@decorators.idempotent_id existence and uniqueness checks "
                  "failed\n"
-                 "Run 'tox -v -euuidgen' to automatically fix tests with\n"
+                 "Run 'tox -v -e uuidgen' to automatically fix tests with\n"
                  "missing @decorators.idempotent_id decorators.")
 
 if __name__ == '__main__':
diff --git a/tempest/lib/common/cred_client.py b/tempest/lib/common/cred_client.py
index ea06011..a81f53c 100644
--- a/tempest/lib/common/cred_client.py
+++ b/tempest/lib/common/cred_client.py
@@ -59,7 +59,8 @@
     def _check_role_exists(self, role_name):
         try:
             roles = self._list_roles()
-            role = next(r for r in roles if r['name'] == role_name)
+            lc_role_name = role_name.lower()
+            role = next(r for r in roles if r['name'].lower() == lc_role_name)
         except StopIteration:
             return None
         return role
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 3246d6a..99ba6ab 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -732,12 +732,21 @@
         if resp.status < 400:
             return
 
-        JSON_ENC = ['application/json', 'application/json; charset=utf-8']
+        # NOTE(zhipengh): There is a purposefully duplicate of content-type
+        # with the only difference is with or without spaces, as specified
+        # in RFC7231.
+        JSON_ENC = ['application/json', 'application/json; charset=utf-8',
+                    'application/json;charset=utf-8']
+
         # NOTE(mtreinish): This is for compatibility with Glance and swift
         # APIs. These are the return content types that Glance api v1
         # (and occasionally swift) are using.
+        # NOTE(zhipengh): There is a purposefully duplicate of content-type
+        # with the only difference is with or without spaces, as specified
+        # in RFC7231.
         TXT_ENC = ['text/plain', 'text/html', 'text/html; charset=utf-8',
-                   'text/plain; charset=utf-8']
+                   'text/plain; charset=utf-8', 'text/html;charset=utf-8',
+                   'text/plain;charset=utf-8']
 
         if ctype.lower() in JSON_ENC:
             parse_resp = True
diff --git a/tempest/api/volume/admin/v2/__init__.py b/tempest/lib/common/utils/linux/__init__.py
similarity index 100%
rename from tempest/api/volume/admin/v2/__init__.py
rename to tempest/lib/common/utils/linux/__init__.py
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
new file mode 100644
index 0000000..64d6be2
--- /dev/null
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -0,0 +1,117 @@
+#    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 sys
+
+import netaddr
+from oslo_log import log as logging
+import six
+
+from tempest.lib.common import ssh
+from tempest.lib.common.utils import test_utils
+import tempest.lib.exceptions
+
+LOG = logging.getLogger(__name__)
+
+
+def debug_ssh(function):
+    """Decorator to generate extra debug info in case off SSH failure"""
+    def wrapper(self, *args, **kwargs):
+        try:
+            return function(self, *args, **kwargs)
+        except tempest.lib.exceptions.SSHTimeout:
+            try:
+                original_exception = sys.exc_info()
+                caller = test_utils.find_test_caller() or "not found"
+                if self.server:
+                    msg = 'Caller: %s. Timeout trying to ssh to server %s'
+                    LOG.debug(msg, caller, self.server)
+                    if self.console_output_enabled and self.servers_client:
+                        try:
+                            msg = 'Console log for server %s: %s'
+                            console_log = (
+                                self.servers_client.get_console_output(
+                                    self.server['id'])['output'])
+                            LOG.debug(msg, self.server['id'], console_log)
+                        except Exception:
+                            msg = 'Could not get console_log for server %s'
+                            LOG.debug(msg, self.server['id'])
+                # re-raise the original ssh timeout exception
+                six.reraise(*original_exception)
+            finally:
+                # Delete the traceback to avoid circular references
+                _, _, trace = original_exception
+                del trace
+    return wrapper
+
+
+class RemoteClient(object):
+
+    def __init__(self, ip_address, username, password=None, pkey=None,
+                 server=None, servers_client=None, ssh_timeout=300,
+                 connect_timeout=60, console_output_enabled=True,
+                 ssh_shell_prologue="set -eu -o pipefail; PATH=$$PATH:/sbin;",
+                 ping_count=1, ping_size=56):
+        """Executes commands in a VM over ssh
+
+        :param ip_address: IP address to ssh to
+        :param username: Ssh username
+        :param password: Ssh password
+        :param pkey: Ssh public key
+        :param server: Server dict, used for debugging purposes
+        :param servers_client: Servers client, used for debugging purposes
+        :param ssh_timeout: Timeout in seconds to wait for the ssh banner
+        :param connect_timeout: Timeout in seconds to wait for TCP connection
+        :param console_output_enabled: Support serial console output?
+        :param ssh_shell_prologue: Shell fragments to use before command
+        :param ping_count: Number of ping packets
+        :param ping_size: Packet size for ping packets
+        """
+        self.server = server
+        self.servers_client = servers_client
+        self.console_output_enabled = console_output_enabled
+        self.ssh_shell_prologue = ssh_shell_prologue
+        self.ping_count = ping_count
+        self.ping_size = ping_size
+
+        self.ssh_client = ssh.Client(ip_address, username, password,
+                                     ssh_timeout, pkey=pkey,
+                                     channel_timeout=connect_timeout)
+
+    @debug_ssh
+    def exec_command(self, cmd):
+        # Shell options below add more clearness on failures,
+        # path is extended for some non-cirros guest oses (centos7)
+        cmd = self.ssh_shell_prologue + " " + cmd
+        LOG.debug("Remote command: %s", cmd)
+        return self.ssh_client.exec_command(cmd)
+
+    @debug_ssh
+    def validate_authentication(self):
+        """Validate ssh connection and authentication
+
+           This method raises an Exception when the validation fails.
+        """
+        self.ssh_client.test_connection_auth()
+
+    def ping_host(self, host, count=None, size=None, nic=None):
+        if count is None:
+            count = self.ping_count
+        if size is None:
+            size = self.ping_size
+
+        addr = netaddr.IPAddress(host)
+        cmd = 'ping6' if addr.version == 6 else 'ping'
+        if nic:
+            cmd = 'sudo {cmd} -I {nic}'.format(cmd=cmd, nic=nic)
+        cmd += ' -c{0} -w{0} -s{1} {2}'.format(count, size, host)
+        return self.exec_command(cmd)
diff --git a/tempest/lib/decorators.py b/tempest/lib/decorators.py
index 92f9698..f82f707 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -16,9 +16,12 @@
 import uuid
 
 import debtcollector.removals
+from oslo_log import log as logging
 import six
 import testtools
 
+LOG = logging.getLogger(__name__)
+
 
 def skip_because(*args, **kwargs):
     """A decorator useful to skip tests hitting known bugs
@@ -45,6 +48,28 @@
     return decorator
 
 
+def related_bug(bug, status_code=None):
+    """A decorator useful to know solutions from launchpad bug reports
+
+    @param bug: The launchpad bug number causing the test
+    @param status_code: The status code related to the bug report
+    """
+    def decorator(f):
+        @functools.wraps(f)
+        def wrapper(self, *func_args, **func_kwargs):
+            try:
+                return f(self, *func_args, **func_kwargs)
+            except Exception as exc:
+                exc_status_code = getattr(exc, 'status_code', None)
+                if status_code is None or status_code == exc_status_code:
+                    LOG.error('Hints: This test was made for the bug %s. '
+                              'The failure could be related to '
+                              'https://launchpad.net/bugs/%s', bug, bug)
+                raise exc
+        return wrapper
+    return decorator
+
+
 def idempotent_id(id):
     """Stub for metadata decorator"""
     if not isinstance(id, six.string_types):
@@ -79,3 +104,21 @@
                 raise testtools.TestCase.skipException(self.message)
             func(*args, **kw)
         return _skipper
+
+
+def attr(**kwargs):
+    """A decorator which applies the testtools attr decorator
+
+    This decorator applies the testtools.testcase.attr if it is in the list of
+    attributes to testtools we want to apply.
+    """
+
+    def decorator(f):
+        if 'type' in kwargs and isinstance(kwargs['type'], str):
+            f = testtools.testcase.attr(kwargs['type'])(f)
+        elif 'type' in kwargs and isinstance(kwargs['type'], list):
+            for attr in kwargs['type']:
+                f = testtools.testcase.attr(attr)(f)
+        return f
+
+    return decorator
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index dea3289..68ce57a 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -32,7 +32,7 @@
         except Exception:
             # at least get the core message out if something happened
             self._error_string = self.message
-        if len(args) > 0:
+        if args:
             # If there is a non-kwarg parameter, assume it's the error
             # message or reason description and tack it on to the end
             # of the exception message
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index eefac66..cd3bab0 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -17,7 +17,9 @@
 import copy
 import importlib
 import inspect
+import warnings
 
+from debtcollector import removals
 from oslo_log import log as logging
 
 from tempest.lib import auth
@@ -29,7 +31,7 @@
 from tempest.lib.services import network
 from tempest.lib.services import volume
 
-
+warnings.simplefilter("once")
 LOG = logging.getLogger(__name__)
 
 
@@ -70,15 +72,15 @@
     :raise PluginRegistrationException: if a plugin exposes a service_version
         already defined by Tempest or another plugin.
 
-    Examples:
+    Examples::
 
-        >>> from tempest import config
-        >>> params = {}
-        >>> for service_version in available_modules():
-        >>>     service = service_version.split('.')[0]
-        >>>     params[service] = config.service_client_config(service)
-        >>> service_clients = ServiceClients(creds, identity_uri,
-        >>>                                  client_parameters=params)
+        from tempest import config
+        params = {}
+        for service_version in available_modules():
+            service = service_version.split('.')[0]
+            params[service] = config.service_client_config(service)
+        service_clients = ServiceClients(creds, identity_uri,
+                                         client_parameters=params)
     """
     extra_service_versions = set([])
     _tempest_modules = set(tempest_modules())
@@ -161,17 +163,17 @@
             parameters cannot be deleted.
         :raise ImportError if the specified module_path cannot be imported
 
-        Example:
+        Example::
 
-            >>> # Get credentials and an auth_provider
-            >>> clients = ClientsFactory(
-            >>>     module_path='my_service.my_service_clients',
-            >>>     client_names=['ServiceClient1', 'ServiceClient2'],
-            >>>     auth_provider=auth_provider,
-            >>>     service='my_service',
-            >>>     region='region1')
-            >>> my_api_client = clients.MyApiClient()
-            >>> my_api_client_region2 = clients.MyApiClient(region='region2')
+            # Get credentials and an auth_provider
+            clients = ClientsFactory(
+                module_path='my_service.my_service_clients',
+                client_names=['ServiceClient1', 'ServiceClient2'],
+                auth_provider=auth_provider,
+                service='my_service',
+                region='region1')
+            my_api_client = clients.MyApiClient()
+            my_api_client_region2 = clients.MyApiClient(region='region2')
 
         """
         # Import the module. If it's not importable, the raised exception
@@ -242,13 +244,19 @@
     It hides some of the complexity from the authorization and configuration
     layers.
 
-    Examples:
+    Examples::
 
-        >>> from tempest.lib.services import clients
-        >>> johndoe = cred_provider.get_creds_by_role(['johndoe'])
-        >>> johndoe_clients = clients.ServiceClients(johndoe,
-        >>>                                                  identity_uri)
-        >>> johndoe_servers = johndoe_clients.servers_client.list_servers()
+        # johndoe is a tempest.lib.auth.Credentials type instance
+        johndoe_clients = clients.ServiceClients(johndoe, identity_uri)
+
+        # List servers in default region
+        johndoe_servers_client = johndoe_clients.compute.ServersClient()
+        johndoe_servers = johndoe_servers_client.list_servers()
+
+        # List servers in Region B
+        johndoe_servers_client_B = johndoe_clients.compute.ServersClient(
+            region='B')
+        johndoe_servers = johndoe_servers_client_B.list_servers()
 
     """
     # NOTE(andreaf) This class does not depend on tempest configuration
@@ -257,6 +265,7 @@
     # initialises this class using values from tempest CONF object. The wrapper
     # class should only be used by tests hosted in Tempest.
 
+    @removals.removed_kwarg('client_parameters')
     def __init__(self, credentials, identity_uri, region=None, scope='project',
                  disable_ssl_certificate_validation=True, ca_certs=None,
                  trace_requests='', client_parameters=None):
@@ -272,7 +281,12 @@
         Parameters dscv, ca_certs and trace_requests all apply to the auth
         provider as well as any service clients provided by this manager.
 
-        Any other client parameter must be set via client_parameters.
+        Any other client parameter should be set via ClientsRegistry.
+
+        Client parameter used to be set via client_parameters, but this is
+        deprecated, and it is actually already not honoured
+        anymore: https://launchpad.net/bugs/1680915.
+
         The list of available parameters is defined in the service clients
         interfaces. For reference, most clients will accept 'region',
         'service', 'endpoint_type', 'build_timeout' and 'build_interval', which
@@ -287,14 +301,18 @@
         - Volume client for 'volume' accepts 'default_volume_size'
         - Servers client from 'compute' accepts 'enable_instance_password'
 
-        Examples:
+        If Tempest configuration is used, parameters will be loaded in the
+        Registry automatically for all service client (Tempest stable ones
+        and plugins).
 
-            >>> identity_params = config.service_client_config('identity')
-            >>> params = {
-            >>>     'identity': identity_params,
-            >>>     'compute': {'region': 'region2'}}
-            >>> manager = lib_manager.Manager(
-            >>>     my_creds, identity_uri, client_parameters=params)
+        Examples::
+
+            identity_params = config.service_client_config('identity')
+            params = {
+                'identity': identity_params,
+                'compute': {'region': 'region2'}}
+            manager = lib_manager.Manager(
+                my_creds, identity_uri, client_parameters=params)
 
         :param credentials: An instance of `auth.Credentials`
         :param identity_uri: URI of the identity API. This should be a
@@ -310,15 +328,6 @@
             name, as declared in `service_clients.available_modules()` except
             for the version. Values are dictionaries of parameters that are
             going to be passed to all clients in the service client module.
-
-        Examples:
-
-            >>> params_service_x = {'param_name': 'param_value'}
-            >>> client_parameters = { 'service_x': params_service_x }
-
-            >>> params_service_y = config.service_client_config('service_y')
-            >>> client_parameters['service_y'] = params_service_y
-
         """
         self._registered_services = set([])
         self.credentials = credentials
diff --git a/tempest/lib/services/compute/quota_classes_client.py b/tempest/lib/services/compute/quota_classes_client.py
index 523a306..0fe9868 100644
--- a/tempest/lib/services/compute/quota_classes_client.py
+++ b/tempest/lib/services/compute/quota_classes_client.py
@@ -35,9 +35,8 @@
     def update_quota_class_set(self, quota_class_id, **kwargs):
         """Update the quota class's limits for one or more resources.
 
-        For a full list of available parameters, please refer to the official
-        API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updatequota
+        # NOTE: Current api-site doesn't contain this API description.
+        # LP: https://bugs.launchpad.net/nova/+bug/1602400
         """
         post_body = json.dumps({'quota_class_set': kwargs})
 
diff --git a/tempest/lib/services/compute/quotas_client.py b/tempest/lib/services/compute/quotas_client.py
index 265969a..daf4bc0 100644
--- a/tempest/lib/services/compute/quotas_client.py
+++ b/tempest/lib/services/compute/quotas_client.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.lib.api_schema.response.compute.v2_1 import quotas as schema
 from tempest.lib.common import rest_client
@@ -22,15 +23,29 @@
 
 class QuotasClient(base_compute_client.BaseComputeClient):
 
-    def show_quota_set(self, tenant_id, user_id=None):
-        """List the quota set for a tenant."""
+    def show_quota_set(self, tenant_id, user_id=None, detail=False):
+        """List the quota set for a tenant.
 
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-compute-v2.1.html/#show-a-quota
+        http://developer.openstack.org/api-ref-compute-v2.1.html/#show-the-detail-of-quota
+        """
+
+        params = {}
         url = 'os-quota-sets/%s' % tenant_id
+        if detail:
+            url += '/detail'
         if user_id:
-            url += '?user_id=%s' % user_id
+            params.update({'user_id': user_id})
+        if params:
+            url += '?%s' % urllib.urlencode(params)
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.get_quota_set, resp, body)
+        if detail:
+            self.validate_response(schema.get_quota_set_details, resp, body)
+        else:
+            self.validate_response(schema.get_quota_set, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def show_default_quota_set(self, tenant_id):
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index b37afb3..0d355a1 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -814,3 +814,19 @@
         schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.delete_tag, resp, body)
         return rest_client.ResponseBody(resp, body)
+
+    def evacuate_server(self, server_id, **kwargs):
+        """Evacuate the given server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#evacuate-server-evacuate-action
+        """
+        if self.enable_instance_password:
+            evacuate_schema = schema.evacuate_server_with_admin_pass
+        else:
+            evacuate_schema = schema.evacuate_server
+
+        return self.action(server_id, 'evacuate',
+                           evacuate_schema,
+                           **kwargs)
diff --git a/tempest/lib/services/compute/tenant_usages_client.py b/tempest/lib/services/compute/tenant_usages_client.py
index d0eb1c9..ade60e5 100644
--- a/tempest/lib/services/compute/tenant_usages_client.py
+++ b/tempest/lib/services/compute/tenant_usages_client.py
@@ -28,7 +28,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/compute/#list-tenant-usage-for-all-tenants
+        https://developer.openstack.org/api-ref/compute/#list-tenant-usage-statistics-for-all-tenants
         """
         url = 'os-simple-tenant-usage'
         if params:
@@ -44,7 +44,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/compute/#show-usage-details-for-tenant
+        https://developer.openstack.org/api-ref/compute/#show-usage-statistics-for-tenant
         """
         url = 'os-simple-tenant-usage/%s' % tenant_id
         if params:
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index 75984ec..8fbb136 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import time
+
 from oslo_serialization import jsonutils as json
 
 from tempest.lib.api_schema.response.compute.v2_1 import versions as schema
@@ -23,7 +25,13 @@
 
     def list_versions(self):
         version_url = self._get_base_version_url()
+
+        start = time.time()
         resp, body = self.raw_request(version_url, 'GET')
+        end = time.time()
+        self._log_request('GET', version_url, resp, secs=(end - start),
+                          resp_body=body)
+
         self._error_checker(resp, body)
         body = json.loads(body)
         self.validate_response(schema.list_versions, resp, body)
diff --git a/tempest/lib/services/identity/v2/endpoints_client.py b/tempest/lib/services/identity/v2/endpoints_client.py
index 770e8ae..db8d7cc 100644
--- a/tempest/lib/services/identity/v2/endpoints_client.py
+++ b/tempest/lib/services/identity/v2/endpoints_client.py
@@ -25,7 +25,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-identity-v2-ext.html#createEndpoint
+        https://developer.openstack.org/api-ref/identity/v2-admin/index.html#create-endpoint-template
         """
 
         post_body = json.dumps({'endpoint': kwargs})
diff --git a/tempest/lib/services/identity/v2/users_client.py b/tempest/lib/services/identity/v2/users_client.py
index cfd97bb..44bb5fd 100644
--- a/tempest/lib/services/identity/v2/users_client.py
+++ b/tempest/lib/services/identity/v2/users_client.py
@@ -88,7 +88,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-identity-v2-ext.html#enableUser
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#enable-disable-user
         """
         # NOTE: The URL (users/<id>/enabled) is different from the api-site
         # one (users/<id>/OS-KSADM/enabled) , but they are the same API
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 88801e7..1489b50 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -20,6 +20,8 @@
 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.oauth_consumers_client import \
+    OAUTHConsumerClient
 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
@@ -36,4 +38,5 @@
            'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
            'PoliciesClient', 'ProjectsClient', 'RegionsClient',
            'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
-           'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']
+           'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient',
+           'OAUTHConsumerClient']
diff --git a/tempest/lib/services/identity/v3/identity_client.py b/tempest/lib/services/identity/v3/identity_client.py
index 8177e35..755c14b 100644
--- a/tempest/lib/services/identity/v3/identity_client.py
+++ b/tempest/lib/services/identity/v3/identity_client.py
@@ -43,3 +43,10 @@
         resp, body = self.delete("auth/tokens", headers=headers)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def list_auth_projects(self):
+        """Get available project scopes."""
+        resp, body = self.get("auth/projects")
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/oauth_consumers_client.py b/tempest/lib/services/identity/v3/oauth_consumers_client.py
new file mode 100644
index 0000000..97fb141
--- /dev/null
+++ b/tempest/lib/services/identity/v3/oauth_consumers_client.py
@@ -0,0 +1,95 @@
+# Copyright 2017 AT&T 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_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class OAUTHConsumerClient(rest_client.RestClient):
+    api_version = "v3"
+
+    def create_consumer(self, description=None):
+        """Creates a consumer.
+
+        :param str description: Optional field to add notes about the consumer
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#create-consumer
+        """
+        post_body = {"description": description}
+        post_body = json.dumps({'consumer': post_body})
+        resp, body = self.post('OS-OAUTH1/consumers', post_body)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_consumer(self, consumer_id):
+        """Deletes a consumer.
+
+        :param str consumer_id: The ID of the consumer that will be deleted
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#delete-consumer
+        """
+        resp, body = self.delete('OS-OAUTH1/consumers/%s' % consumer_id)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_consumer(self, consumer_id, description=None):
+        """Updates a consumer.
+
+        :param str consumer_id: The ID of the consumer that will be updated
+        :param str description: Optional field to add notes about the consumer
+
+        For more information, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/identity/v3-ext/#update-consumer
+        """
+        post_body = {"description": description}
+        post_body = json.dumps({'consumer': post_body})
+        resp, body = self.patch('OS-OAUTH1/consumers/%s' % consumer_id,
+                                post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_consumer(self, consumer_id):
+        """Show consumer details.
+
+        :param str consumer_id: The ID of the consumer that will be shown
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#show-consumer-details
+        """
+        resp, body = self.get('OS-OAUTH1/consumers/%s' % consumer_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_consumers(self):
+        """List all consumers.
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#list-consumers
+        """
+        resp, body = self.get('OS-OAUTH1/consumers')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/roles_client.py b/tempest/lib/services/identity/v3/roles_client.py
index 0df23ce..43e3c01 100644
--- a/tempest/lib/services/identity/v3/roles_client.py
+++ b/tempest/lib/services/identity/v3/roles_client.py
@@ -214,6 +214,18 @@
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
+    def list_all_role_inference_rules(self):
+        """Lists all role inference rules.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#list-all-role-inference-rules
+        """
+        resp, body = self.get('role_inferences')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
     def check_role_inference_rule(self, prior_role, implies_role):
         """Check a role inference rule."""
         resp, body = self.head('roles/%s/implies/%s' %
diff --git a/tempest/lib/services/image/v1/images_client.py b/tempest/lib/services/image/v1/images_client.py
index faafb4a..42f8cf2 100644
--- a/tempest/lib/services/image/v1/images_client.py
+++ b/tempest/lib/services/image/v1/images_client.py
@@ -118,7 +118,7 @@
         if 'changes_since' in kwargs:
             kwargs['changes-since'] = kwargs.pop('changes_since')
 
-        if len(kwargs) > 0:
+        if kwargs:
             url += '?%s' % urllib.urlencode(kwargs)
 
         resp, body = self.get(url)
diff --git a/tempest/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index 7d973e5..99a5321 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -25,7 +25,9 @@
 from tempest.lib.services.image.v2.resource_types_client import \
     ResourceTypesClient
 from tempest.lib.services.image.v2.schemas_client import SchemasClient
+from tempest.lib.services.image.v2.versions_client import VersionsClient
 
 __all__ = ['ImageMembersClient', 'ImagesClient', 'NamespaceObjectsClient',
            'NamespacePropertiesClient', 'NamespaceTagsClient',
-           'NamespacesClient', 'ResourceTypesClient', 'SchemasClient']
+           'NamespacesClient', 'ResourceTypesClient', 'SchemasClient',
+           'VersionsClient']
diff --git a/tempest/lib/services/image/v2/namespace_tags_client.py b/tempest/lib/services/image/v2/namespace_tags_client.py
index a7f8c39..61cc33d 100644
--- a/tempest/lib/services/image/v2/namespace_tags_client.py
+++ b/tempest/lib/services/image/v2/namespace_tags_client.py
@@ -41,7 +41,7 @@
 
         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
+        https://developer.openstack.org/api-ref/image/v2/metadefs-index.html#get-tag-definition
         """
         url = 'metadefs/namespaces/%s/tags/%s' % (namespace,
                                                   tag_name)
diff --git a/tempest/lib/services/image/v2/versions_client.py b/tempest/lib/services/image/v2/versions_client.py
new file mode 100644
index 0000000..1adc466
--- /dev/null
+++ b/tempest/lib/services/image/v2/versions_client.py
@@ -0,0 +1,38 @@
+# Copyright 2017 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 time
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class VersionsClient(rest_client.RestClient):
+    api_version = "v2"
+
+    def list_versions(self):
+        """List API versions"""
+        version_url = self._get_base_version_url()
+
+        start = time.time()
+        resp, body = self.raw_request(version_url, 'GET')
+        end = time.time()
+        self._log_request('GET', version_url, resp, secs=(end - start),
+                          resp_body=body)
+        self._error_checker(resp, body)
+
+        self.expected_success(300, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/__init__.py b/tempest/lib/services/volume/v2/__init__.py
index 8acad0f..9434896 100644
--- a/tempest/lib/services/volume/v2/__init__.py
+++ b/tempest/lib/services/volume/v2/__init__.py
@@ -30,11 +30,14 @@
 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.transfers_client import TransfersClient
 from tempest.lib.services.volume.v2.types_client import TypesClient
+from tempest.lib.services.volume.v2.volume_manage_client import \
+    VolumeManageClient
 from tempest.lib.services.volume.v2.volumes_client import VolumesClient
 
 __all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
            'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
            'ServicesClient', 'SnapshotsClient', 'TypesClient', 'VolumesClient',
            'LimitsClient', 'CapabilitiesClient', 'SchedulerStatsClient',
-           'SnapshotManageClient']
+           'SnapshotManageClient', 'VolumeManageClient', 'TransfersClient']
diff --git a/tempest/lib/services/volume/v2/capabilities_client.py b/tempest/lib/services/volume/v2/capabilities_client.py
index b6de5b9..240be13 100644
--- a/tempest/lib/services/volume/v2/capabilities_client.py
+++ b/tempest/lib/services/volume/v2/capabilities_client.py
@@ -19,13 +19,14 @@
 
 
 class CapabilitiesClient(rest_client.RestClient):
+    api_version = "v2"
 
     def show_backend_capabilities(self, host):
         """Shows capabilities for a storage back end.
 
-         Output params: see http://developer.openstack.org/
-                            api-ref-blockstorage-v2.html
-                            #showBackendCapabilities
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/index.html#show-back-end-capabilities
         """
         url = 'capabilities/%s' % host
         resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/encryption_types_client.py b/tempest/lib/services/volume/v2/encryption_types_client.py
index 8b01f11..eeff537 100755
--- a/tempest/lib/services/volume/v2/encryption_types_client.py
+++ b/tempest/lib/services/volume/v2/encryption_types_client.py
@@ -67,3 +67,17 @@
             "/types/%s/encryption/provider" % volume_type_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def update_encryption_type(self, volume_type_id, **kwargs):
+        """Update an encryption type for an existing volume type.
+
+        TODO: Current api-site doesn't contain this API description.
+        After fixing the api-site, we need to fix here also for putting
+        the link to api-site.
+        """
+        url = "/types/%s/encryption/provider" % volume_type_id
+        put_body = json.dumps({'encryption': kwargs})
+        resp, body = self.put(url, put_body)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/scheduler_stats_client.py b/tempest/lib/services/volume/v2/scheduler_stats_client.py
index 637254b..0d04f85 100644
--- a/tempest/lib/services/volume/v2/scheduler_stats_client.py
+++ b/tempest/lib/services/volume/v2/scheduler_stats_client.py
@@ -19,12 +19,14 @@
 
 
 class SchedulerStatsClient(rest_client.RestClient):
+    api_version = "v2"
 
     def list_pools(self, detail=False):
         """List all the volumes pools (hosts).
 
-        Output params: see http://developer.openstack.org/
-                           api-ref-blockstorage-v2.html#listPools
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/index.html#list-back-end-storage-pools
         """
         url = 'scheduler-stats/get_pools'
         if detail:
diff --git a/tempest/lib/services/volume/v2/snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
index 2bdf1b1..983ed89 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -27,7 +27,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-with-details
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots
         """
         url = 'snapshots'
         if detail:
@@ -45,7 +46,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-details
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -71,7 +72,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -84,7 +85,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -136,7 +137,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -149,7 +150,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v2/transfers_client.py b/tempest/lib/services/volume/v2/transfers_client.py
new file mode 100644
index 0000000..853948e
--- /dev/null
+++ b/tempest/lib/services/volume/v2/transfers_client.py
@@ -0,0 +1,80 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest.lib.common import rest_client
+
+
+class TransfersClient(rest_client.RestClient):
+    """Client class to send CRUD Volume Transfer V2 API requests"""
+    api_version = "v2"
+
+    def create_volume_transfer(self, **kwargs):
+        """Create a volume transfer.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer
+        """
+        post_body = json.dumps({'transfer': kwargs})
+        resp, body = self.post('os-volume-transfer', post_body)
+        body = json.loads(body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_volume_transfer(self, transfer_id):
+        """Returns the details of a volume transfer."""
+        url = "os-volume-transfer/%s" % transfer_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_volume_transfers(self, **params):
+        """List all the volume transfers created.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers
+        """
+        url = 'os-volume-transfer'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_volume_transfer(self, transfer_id):
+        """Delete a volume transfer."""
+        resp, body = self.delete("os-volume-transfer/%s" % transfer_id)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def accept_volume_transfer(self, transfer_id, **kwargs):
+        """Accept a volume transfer.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer
+        """
+        url = 'os-volume-transfer/%s/accept' % transfer_id
+        post_body = json.dumps({'accept': kwargs})
+        resp, body = self.post(url, post_body)
+        body = json.loads(body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/types_client.py b/tempest/lib/services/volume/v2/types_client.py
index 31597d7..5d30615 100644
--- a/tempest/lib/services/volume/v2/types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -41,7 +41,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types
         """
         url = 'types'
         if params:
@@ -57,7 +57,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-details
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -70,7 +70,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -83,7 +83,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -138,7 +138,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -156,7 +156,7 @@
                      updated value.
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-extra-specs-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-extra-specs-for-a-volume-type
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
@@ -170,7 +170,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#add-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#add-private-volume-type-access
         """
         post_body = json.dumps({'addProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -183,7 +183,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#remove-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#remove-private-volume-type-access
         """
         post_body = json.dumps({'removeProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -196,7 +196,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-private-volume-type-access-details
         """
         url = 'types/%s/os-volume-type-access' % volume_type_id
         resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/volume_manage_client.py b/tempest/lib/services/volume/v2/volume_manage_client.py
new file mode 100644
index 0000000..12f4240
--- /dev/null
+++ b/tempest/lib/services/volume/v2/volume_manage_client.py
@@ -0,0 +1,37 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# 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 VolumeManageClient(rest_client.RestClient):
+    """Volume manage V2 client."""
+
+    api_version = "v2"
+
+    def manage_volume(self, **kwargs):
+        """Manage existing volume.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#manage-existing-volume
+        """
+        post_body = json.dumps({'volume': kwargs})
+        resp, body = self.post('os-volume-manage', 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/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index 8b8e249..c67ddfb 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from debtcollector import moves
 from debtcollector import removals
 from oslo_serialization import jsonutils as json
 import six
@@ -20,12 +21,43 @@
 
 from tempest.lib.common import rest_client
 from tempest.lib import exceptions as lib_exc
+from tempest.lib.services.volume.v2 import transfers_client
 
 
 class VolumesClient(rest_client.RestClient):
     """Client class to send CRUD Volume V2 API requests"""
     api_version = "v2"
 
+    create_volume_transfer = moves.moved_function(
+        transfers_client.TransfersClient.create_volume_transfer,
+        'VolumesClient.create_volume_transfer', __name__,
+        message='Use create_volume_transfer from new location.',
+        version='Pike', removal_version='Queens')
+
+    show_volume_transfer = moves.moved_function(
+        transfers_client.TransfersClient.show_volume_transfer,
+        'VolumesClient.show_volume_transfer', __name__,
+        message='Use show_volume_transfer from new location.',
+        version='Pike', removal_version='Queens')
+
+    list_volume_transfers = moves.moved_function(
+        transfers_client.TransfersClient.list_volume_transfers,
+        'VolumesClient.list_volume_transfers', __name__,
+        message='Use list_volume_transfer from new location.',
+        version='Pike', removal_version='Queens')
+
+    delete_volume_transfer = moves.moved_function(
+        transfers_client.TransfersClient.delete_volume_transfer,
+        'VolumesClient.delete_volume_transfer', __name__,
+        message='Use delete_volume_transfer from new location.',
+        version='Pike', removal_version='Queens')
+
+    accept_volume_transfer = moves.moved_function(
+        transfers_client.TransfersClient.accept_volume_transfer,
+        'VolumesClient.accept_volume_transfer', __name__,
+        message='Use accept_volume_transfer from new location.',
+        version='Pike', removal_version='Queens')
+
     def _prepare_params(self, params):
         """Prepares params for use in get or _ext_get methods.
 
@@ -65,7 +97,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -78,7 +110,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -86,9 +118,12 @@
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def delete_volume(self, volume_id):
+    def delete_volume(self, volume_id, cascade=False):
         """Deletes the Specified Volume."""
-        resp, body = self.delete("volumes/%s" % volume_id)
+        url = 'volumes/%s' % volume_id
+        if cascade:
+            url += '?cascade=True'
+        resp, body = self.delete(url)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
@@ -106,7 +141,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-to-server
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -163,7 +198,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-size
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -176,69 +211,13 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-status-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-statuses
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
 
-    def create_volume_transfer(self, **kwargs):
-        """Create a volume transfer.
-
-        For a full list of available parameters, please refer to the official
-        API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer-v2
-        """
-        post_body = json.dumps({'transfer': kwargs})
-        resp, body = self.post('os-volume-transfer', post_body)
-        body = json.loads(body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def show_volume_transfer(self, transfer_id):
-        """Returns the details of a volume transfer."""
-        url = "os-volume-transfer/%s" % transfer_id
-        resp, body = self.get(url)
-        body = json.loads(body)
-        self.expected_success(200, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def list_volume_transfers(self, **params):
-        """List all the volume transfers created.
-
-        For a full list of available parameters, please refer to the official
-        API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers-v2
-        """
-        url = 'os-volume-transfer'
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-        resp, body = self.get(url)
-        body = json.loads(body)
-        self.expected_success(200, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def delete_volume_transfer(self, transfer_id):
-        """Delete a volume transfer."""
-        resp, body = self.delete("os-volume-transfer/%s" % transfer_id)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
-    def accept_volume_transfer(self, transfer_id, **kwargs):
-        """Accept a volume transfer.
-
-        For a full list of available parameters, please refer to the official
-        API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer-v2
-        """
-        url = 'os-volume-transfer/%s/accept' % transfer_id
-        post_body = json.dumps({'accept': kwargs})
-        resp, body = self.post(url, post_body)
-        body = json.loads(body)
-        self.expected_success(202, resp.status)
-        return rest_client.ResponseBody(resp, body)
-
     def update_volume_readonly(self, volume_id, **kwargs):
         """Update the Specified Volume readonly."""
         post_body = json.dumps({'os-update_readonly_flag': kwargs})
@@ -307,7 +286,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-image-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#set-image-metadata-for-volume
         """
         post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
         url = "volumes/%s/action" % (volume_id)
@@ -344,10 +323,22 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show_backend_capabilities-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-back-end-capabilities
         """
         url = 'capabilities/%s' % host
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def unmanage_volume(self, volume_id):
+        """Unmanage volume.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#unmanage-volume
+        """
+        post_body = json.dumps({'os-unmanage': {}})
+        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v3/__init__.py b/tempest/lib/services/volume/v3/__init__.py
index a4600a8..72ab785 100644
--- a/tempest/lib/services/volume/v3/__init__.py
+++ b/tempest/lib/services/volume/v3/__init__.py
@@ -14,5 +14,6 @@
 
 from tempest.lib.services.volume.v3.base_client import BaseClient
 from tempest.lib.services.volume.v3.messages_client import MessagesClient
+from tempest.lib.services.volume.v3.versions_client import VersionsClient
 
-__all__ = ['MessagesClient', 'BaseClient']
+__all__ = ['MessagesClient', 'BaseClient', 'VersionsClient']
diff --git a/tempest/lib/services/volume/v3/versions_client.py b/tempest/lib/services/volume/v3/versions_client.py
new file mode 100644
index 0000000..e2941c4
--- /dev/null
+++ b/tempest/lib/services/volume/v3/versions_client.py
@@ -0,0 +1,47 @@
+# Copyright 2017 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 time
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.api_schema.response.volume import versions as schema
+from tempest.lib.common import rest_client
+from tempest.lib.services.volume.v3 import base_client
+
+
+class VersionsClient(base_client.BaseClient):
+
+    def list_versions(self):
+        """List API versions
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v3/#list-all-api-versions
+        """
+        version_url = self._get_base_version_url()
+
+        start = time.time()
+        resp, body = self.raw_request(version_url, 'GET')
+        end = time.time()
+        # NOTE: We need a raw_request() here instead of request() call because
+        # "list API versions" API doesn't require an authentication and we can
+        # skip it with raw_request() call.
+        self._log_request('GET', version_url, resp, secs=(end - start),
+                          resp_body=body)
+        self._error_checker(resp, body)
+
+        body = json.loads(body)
+        self.validate_response(schema.list_versions, resp, body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index ff48abe..3418a2f 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -23,12 +23,12 @@
 
 from tempest.common import compute
 from tempest.common import image as common_image
-from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest.common.utils import net_utils
 from tempest.common import waiters
 from tempest import config
 from tempest import exceptions
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions as lib_exc
 import tempest.test
@@ -79,13 +79,8 @@
         cls.security_groups_client = cls.manager.security_groups_client
         cls.security_group_rules_client = (
             cls.manager.security_group_rules_client)
-
-        if CONF.volume_feature_enabled.api_v2:
-            cls.volumes_client = cls.manager.volumes_v2_client
-            cls.snapshots_client = cls.manager.snapshots_v2_client
-        else:
-            cls.volumes_client = cls.manager.volumes_client
-            cls.snapshots_client = cls.manager.snapshots_client
+        cls.volumes_client = cls.manager.volumes_v2_client
+        cls.snapshots_client = cls.manager.snapshots_v2_client
 
     # ## Test functions library
     #
@@ -235,12 +230,7 @@
                         volume['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.volumes_client.delete_volume, volume['id'])
-
-        # NOTE(e0ne): Cinder API v2 uses name instead of display_name
-        if 'display_name' in volume:
-            self.assertEqual(name, volume['display_name'])
-        else:
-            self.assertEqual(name, volume['name'])
+        self.assertEqual(name, volume['name'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
         # The volume retrieved on creation has a non-up-to-date status.
@@ -421,16 +411,17 @@
 
         return image
 
-    def _log_console_output(self, servers=None):
+    def _log_console_output(self, servers=None, client=None):
         if not CONF.compute_feature_enabled.console_output:
             LOG.debug('Console output not supported, cannot log')
             return
+        client = client or self.servers_client
         if not servers:
-            servers = self.servers_client.list_servers()
+            servers = client.list_servers()
             servers = servers['servers']
         for server in servers:
             try:
-                console_output = self.servers_client.get_console_output(
+                console_output = client.get_console_output(
                     server['id'])['output']
                 LOG.debug('Console output for %s\nbody=\n%s',
                           server['id'], console_output)
@@ -888,16 +879,16 @@
                       show_floatingip(floatingip_id)['floatingip'])
             return status == result['status']
 
-        test_utils.call_until_true(refresh,
-                                   CONF.network.build_timeout,
-                                   CONF.network.build_interval)
-        floating_ip = self.floating_ips_client.show_floatingip(
-            floatingip_id)['floatingip']
-        self.assertEqual(status, floating_ip['status'],
-                         message="FloatingIP: {fp} is at status: {cst}. "
-                                 "failed  to reach status: {st}"
-                         .format(fp=floating_ip, cst=floating_ip['status'],
-                                 st=status))
+        if not test_utils.call_until_true(refresh,
+                                          CONF.network.build_timeout,
+                                          CONF.network.build_interval):
+            floating_ip = self.floating_ips_client.show_floatingip(
+                floatingip_id)['floatingip']
+            self.assertEqual(status, floating_ip['status'],
+                             message="FloatingIP: {fp} is at status: {cst}. "
+                                     "failed  to reach status: {st}"
+                             .format(fp=floating_ip, cst=floating_ip['status'],
+                                     st=status))
         LOG.info("FloatingIP: {fp} is at status: {st}"
                  .format(fp=floating_ip, st=status))
 
@@ -1251,14 +1242,9 @@
     @classmethod
     def setup_clients(cls):
         super(EncryptionScenarioTest, cls).setup_clients()
-        if CONF.volume_feature_enabled.api_v2:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
-            cls.admin_encryption_types_client =\
-                cls.os_adm.encryption_types_v2_client
-        else:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_client
-            cls.admin_encryption_types_client =\
-                cls.os_adm.encryption_types_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+        cls.admin_encryption_types_client =\
+            cls.os_adm.encryption_types_v2_client
 
     def create_encryption_type(self, client=None, type_id=None, provider=None,
                                key_size=None, cipher=None,
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index b0b516a..8408a1e 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.common import tempest_fixtures as fixtures
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
@@ -96,7 +96,7 @@
         return aggregate
 
     @decorators.idempotent_id('cb2b4c4f-0c7c-4164-bdde-6285b302a081')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute')
     def test_aggregate_basic_ops(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index a05b1b1..d7b86f6 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -62,7 +62,7 @@
         self.nova_volume_detach(server, attached_volume)
 
     @decorators.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_luks(self):
         server = self.launch_instance()
@@ -72,7 +72,7 @@
         self.attach_detach_volume(server, volume)
 
     @decorators.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_cryptsetup(self):
         server = self.launch_instance()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 6665fa7..ae2ba2f 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -104,7 +104,7 @@
         return body['OS-EXT-SRV-ATTR:host']
 
     @decorators.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
         keypair = self.create_keypair()
@@ -130,7 +130,7 @@
             server, keypair, floating_ip)
 
     @decorators.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_rebuild(self):
         keypair = self.create_keypair()
@@ -145,7 +145,7 @@
     @decorators.idempotent_id('2b2642db-6568-4b35-b812-eceed3fa20ce')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_pause_unpause(self):
         keypair = self.create_keypair()
@@ -163,7 +163,7 @@
     @decorators.idempotent_id('5cdf9499-541d-4923-804e-b9a60620a7f0')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_suspend_resume(self):
         keypair = self.create_keypair()
@@ -181,7 +181,7 @@
     @decorators.idempotent_id('719eb59d-2f42-4b66-b8b1-bb1254473967')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_resize(self):
         resize_flavor = CONF.compute.flavor_ref_alt
@@ -205,7 +205,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_cold_migration(self):
         keypair = self.create_keypair()
@@ -231,7 +231,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_cold_migration_revert(self):
         keypair = self.create_keypair()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 5bbc039..756ca4d 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -104,7 +104,6 @@
 
     def _setup_network_and_servers(self, **kwargs):
         boot_with_port = kwargs.pop('boot_with_port', False)
-        self.security_group = self._create_security_group()
         self.network, self.subnet, self.router = self.create_networks(**kwargs)
         self.check_networks()
 
@@ -152,7 +151,9 @@
     def _create_server(self, network, port_id=None):
         keypair = self.create_keypair()
         self.keypairs[keypair['name']] = keypair
-        security_groups = [{'name': self.security_group['name']}]
+        security_groups = [
+            {'name': self._create_security_group()['name']}
+        ]
         network = {'uuid': network['id']}
         if port_id is not None:
             network['port'] = port_id
@@ -285,10 +286,11 @@
                                               % CONF.network.build_timeout)
 
         num, new_nic = self.diff_list[0]
-        ssh_client.assign_static_ip(
-            nic=new_nic, addr=new_port['fixed_ips'][0]['ip_address'],
-            network_mask_bits=CONF.network.project_network_mask_bits)
-        ssh_client.set_nic_state(nic=new_nic)
+        ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
+                                new_port['fixed_ips'][0]['ip_address'],
+                                CONF.network.project_network_mask_bits,
+                                new_nic))
+        ssh_client.exec_command("sudo ip link set %s up" % new_nic)
 
     def _get_server_nics(self, ssh_client):
         reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
@@ -350,7 +352,7 @@
             self.check_remote_connectivity(ssh_source, remote_ip,
                                            should_connect)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
     @test.services('compute', 'network')
     def test_network_basic_ops(self):
@@ -406,7 +408,7 @@
     @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
     @testtools.skipUnless(test.is_extension_enabled('net-mtu', 'network'),
                           'No way to calculate MTU for networks')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_mtu_sized_frames(self):
         """Validate that network MTU sized frames fit through."""
@@ -419,7 +421,7 @@
                       'Connectivity can only be tested when in a '
                       'multitenant network environment')
     @decorators.skip_because(bug="1610994")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
         """Test connectivity between VMs on different networks
@@ -495,7 +497,7 @@
     @testtools.skipIf(CONF.network.shared_physical_network,
                       'Router state can be altered only with multitenant '
                       'networks capabilities')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_update_router_admin_state(self):
         """Test to update admin state up of router
@@ -529,7 +531,7 @@
                       'network isolation not available')
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_subnet_details(self):
         """Tests that subnet's extra configuration details are affecting VMs.
@@ -613,7 +615,7 @@
     @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
                           "Changing a port's admin state is not supported "
                           "by the test environment")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_update_instance_port_admin_state(self):
         """Test to update admin_state_up attribute of instance port
@@ -659,7 +661,7 @@
                                        should_succeed=True)
 
     @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_preserve_preexisting_port(self):
         """Test preserve pre-existing port
@@ -711,7 +713,7 @@
 
     @test.requires_ext(service='network', extension='l3_agent_scheduler')
     @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_router_rescheduling(self):
         """Tests that router can be removed from agent and add to a new agent.
@@ -791,7 +793,7 @@
     @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                           'NIC hotplug not available')
     @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_port_security_macspoofing_port(self):
         """Tests port_security extension enforces mac spoofing
@@ -832,7 +834,13 @@
         peer_address = peer['addresses'][self.new_net['name']][0]['addr']
         self.check_remote_connectivity(ssh_client, dest=peer_address,
                                        nic=spoof_nic, should_succeed=True)
-        ssh_client.set_mac_address(spoof_nic, spoof_mac)
+        # Set a mac address by making nic down temporary
+        cmd = ("sudo ip link set {nic} down;"
+               "sudo ip link set dev {nic} address {mac};"
+               "sudo ip link set {nic} up").format(nic=spoof_nic,
+                                                   mac=spoof_mac)
+        ssh_client.exec_command(cmd)
+
         new_mac = ssh_client.get_mac_address(nic=spoof_nic)
         self.assertEqual(spoof_mac, new_mac)
         self.check_remote_connectivity(ssh_client, dest=peer_address,
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index d9b93fe..daf4d13 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -72,11 +72,11 @@
         if dualnet - create IPv6 subnets on a different network
         :return: list of created networks
         """
-        self.network = self._create_network()
+        network = self._create_network()
         if dualnet:
-            self.network_v6 = self._create_network()
+            network_v6 = self._create_network()
 
-        sub4 = self._create_subnet(network=self.network,
+        sub4 = self._create_subnet(network=network,
                                    namestart='sub4',
                                    ip_version=4)
 
@@ -90,7 +90,7 @@
 
         self.subnets_v6 = []
         for _ in range(n_subnets6):
-            net6 = self.network_v6 if dualnet else self.network
+            net6 = network_v6 if dualnet else network
             sub6 = self._create_subnet(network=net6,
                                        namestart='sub6',
                                        ip_version=6,
@@ -105,7 +105,7 @@
                             router['id'], subnet_id=sub6['id'])
 
             self.subnets_v6.append(sub6)
-        return [self.network, self.network_v6] if dualnet else [self.network]
+        return [network, network_v6] if dualnet else [network]
 
     @staticmethod
     def define_server_ips(srv):
@@ -121,8 +121,6 @@
     def prepare_server(self, networks=None):
         username = CONF.validation.image_ssh_user
 
-        networks = networks or [self.network]
-
         srv = self.create_server(
             key_name=self.keypair['name'],
             security_groups=[{'name': self.sec_grp['name']}],
@@ -134,7 +132,7 @@
             username=username)
         return ssh, ips, srv["id"]
 
-    def turn_nic6_on(self, ssh, sid):
+    def turn_nic6_on(self, ssh, sid, network_id):
         """Turns the IPv6 vNIC on
 
         Required because guest images usually set only the first vNIC on boot.
@@ -142,18 +140,21 @@
 
         @param ssh: RemoteClient ssh instance to server
         @param sid: server uuid
+        @param network_id: the network id the NIC is connected to
         """
         ports = [
             p["mac_address"] for p in
             self.admin_manager.ports_client.list_ports(
-                device_id=sid, network_id=self.network_v6['id'])['ports']
+                device_id=sid, network_id=network_id)['ports']
         ]
+
         self.assertEqual(1, len(ports),
                          message=("Multiple IPv6 ports found on network %s. "
                                   "ports: %s")
-                         % (self.network_v6, ports))
+                         % (network_id, ports))
         mac6 = ports[0]
-        ssh.set_nic_state(ssh.get_nic_name_by_mac(mac6))
+        nic = ssh.get_nic_name_by_mac(mac6)
+        ssh.exec_command("sudo ip link set %s up" % nic)
 
     def _prepare_and_test(self, address6_mode, n_subnets6=1, dualnet=False):
         net_list = self.prepare_network(address6_mode=address6_mode,
@@ -168,8 +169,9 @@
 
         # Turn on 2nd NIC for Cirros when dualnet
         if dualnet:
-            self.turn_nic6_on(sshv4_1, sid1)
-            self.turn_nic6_on(sshv4_2, sid2)
+            network, network_v6 = net_list
+            self.turn_nic6_on(sshv4_1, sid1, network_v6['id'])
+            self.turn_nic6_on(sshv4_2, sid2, network_v6['id'])
 
         # get addresses assigned to vNIC as reported by 'ip address' utility
         ips_from_ip_1 = sshv4_1.exec_command("ip address")
@@ -204,43 +206,43 @@
             self.check_remote_connectivity(sshv4_2,
                                            self.subnets_v6[i]['gateway_ip'])
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('2c92df61-29f0-4eaa-bee3-7c65bef62a43')
     @test.services('compute', 'network')
     def test_slaac_from_os(self):
         self._prepare_and_test(address6_mode='slaac')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('d7e1f858-187c-45a6-89c9-bdafde619a9f')
     @test.services('compute', 'network')
     def test_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('7ab23f41-833b-4a16-a7c9-5b42fe6d4123')
     @test.services('compute', 'network')
     def test_multi_prefix_dhcpv6_stateless(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('dec222b1-180c-4098-b8c5-cc1b8342d611')
     @test.services('compute', 'network')
     def test_multi_prefix_slaac(self):
         self._prepare_and_test(address6_mode='slaac', n_subnets6=2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('b6399d76-4438-4658-bcf5-0d6c8584fde2')
     @test.services('compute', 'network')
     def test_dualnet_slaac_from_os(self):
         self._prepare_and_test(address6_mode='slaac', dualnet=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('76f26acd-9688-42b4-bc3e-cd134c4cb09e')
     @test.services('compute', 'network')
     def test_dualnet_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless', dualnet=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('cf1c4425-766b-45b8-be35-e2959728eb00')
     @test.services('compute', 'network')
     def test_dualnet_multi_prefix_dhcpv6_stateless(self):
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 7fd8c91..25e9f5c 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -46,7 +46,7 @@
         self.delete_container(container_name)
 
     @decorators.idempotent_id('916c7111-cb1f-44b2-816d-8f760e4ea910')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('object_storage')
     def test_swift_acl_anonymous_download(self):
         """This test will cover below steps:
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index fa12f33..2116fe8 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -15,9 +15,9 @@
 from oslo_log import log
 import testtools
 
-from tempest.common.utils import data_utils
 from tempest.common.utils import net_info
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
@@ -122,6 +122,7 @@
             self.router = None
             self.security_groups = {}
             self.servers = list()
+            self.access_point = None
 
         def set_network(self, network, subnet, router):
             self.network = network
@@ -458,6 +459,14 @@
         subnet_id = tenant.subnet['id']
         self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list)
 
+    def _log_console_output_for_all_tenants(self):
+        for tenant in self.tenants.values():
+            client = tenant.manager.servers_client
+            self._log_console_output(servers=tenant.servers, client=client)
+            if tenant.access_point is not None:
+                self._log_console_output(
+                    servers=[tenant.access_point], client=client)
+
     @decorators.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
     @test.services('compute', 'network')
     def test_cross_tenant_traffic(self):
@@ -475,8 +484,7 @@
             self._test_cross_tenant_block(source_tenant, dest_tenant)
             self._test_cross_tenant_allow(source_tenant, dest_tenant)
         except Exception:
-            for tenant in self.tenants.values():
-                self._log_console_output(servers=tenant.servers)
+            self._log_console_output_for_all_tenants()
             raise
 
     @decorators.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
@@ -489,12 +497,11 @@
             self._test_in_tenant_block(self.primary_tenant)
             self._test_in_tenant_allow(self.primary_tenant)
         except Exception:
-            for tenant in self.tenants.values():
-                self._log_console_output(servers=tenant.servers)
+            self._log_console_output_for_all_tenants()
             raise
 
     @decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_port_update_new_security_group(self):
         """Verifies the traffic after updating the vm port
@@ -544,12 +551,11 @@
                 source=access_point_ssh,
                 dest=self._get_server_ip(server))
         except Exception:
-            for tenant in self.tenants.values():
-                self._log_console_output(servers=tenant.servers)
+            self._log_console_output_for_all_tenants()
             raise
 
     @decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_multiple_security_groups(self):
         """Verify multiple security groups and checks that rules
@@ -581,7 +587,7 @@
                                    private_key=private_key,
                                    should_connect=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
     @test.services('compute', 'network')
@@ -618,16 +624,12 @@
                 source=access_point_ssh,
                 dest=self._get_server_ip(server))
         except Exception:
-            for tenant in self.tenants.values():
-                self._log_console_output(servers=tenant.servers)
+            self._log_console_output_for_all_tenants()
             raise
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
-    @testtools.skipUnless(
-        CONF.compute_feature_enabled.allow_port_security_disabled,
-        'Port security must be enabled.')
     # TODO(mriedem): We shouldn't actually need to check this since neutron
     # disables the port_security extension by default, but the problem is nova
     # assumes port_security_enabled=True if it's not set on the network
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 1960e9a..6005e28 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -37,21 +37,19 @@
     """
 
     @classmethod
-    def skip_checks(cls):
-        super(TestServerAdvancedOps, cls).skip_checks()
-        if CONF.compute.flavor_ref_alt == CONF.compute.flavor_ref:
-            msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
-            raise cls.skipException(msg)
-
-    @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
         super(TestServerAdvancedOps, cls).setup_credentials()
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
+    @testtools.skipUnless(CONF.compute.flavor_ref !=
+                          CONF.compute.flavor_ref_alt
+                          and CONF.compute.flavor_ref_alt != "",
+                          'The flavor_ref_alt option should not be empty and '
+                          'should not be identical with flavor_ref')
     @test.services('compute', 'volume')
     def test_resize_volume_backed_server_confirm(self):
         # We create an instance for use in this test
@@ -70,7 +68,7 @@
         waiters.wait_for_server_status(self.servers_client, instance_id,
                                        'ACTIVE')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index ddbaf5a..2be9e06 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -124,7 +124,7 @@
             # instance info and do direct comparison.
 
     @decorators.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute', 'network')
     def test_server_basic_ops(self):
         keypair = self.create_keypair()
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index db91a21..bf2858b 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -45,7 +45,7 @@
         cls.servers_client = cls.admin_manager.servers_client
 
     @decorators.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute', 'network')
     def test_schedule_to_all_nodes(self):
         available_zone = \
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 9e763f8..fc04b44 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -74,7 +74,7 @@
                                         private_key=keypair['private_key'])
         self.assertEqual(timestamp, timestamp2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
@@ -82,7 +82,7 @@
     def test_shelve_instance(self):
         self._create_server_then_shelve_and_unshelve()
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index a699de2..52767dc 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -41,7 +41,7 @@
             raise cls.skipException("Snapshotting is not available.")
 
     @decorators.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
     @test.services('compute', 'network', 'image')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index aabb767..debd664 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -16,9 +16,9 @@
 from oslo_log import log as logging
 import testtools
 
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -68,10 +68,7 @@
                                                 volume['id'], 'available')
         waiters.wait_for_volume_resource_status(self.snapshots_client,
                                                 snapshot['id'], 'available')
-        if 'display_name' in snapshot:
-            self.assertEqual(snapshot_name, snapshot['display_name'])
-        else:
-            self.assertEqual(snapshot_name, snapshot['name'])
+        self.assertEqual(snapshot_name, snapshot['name'])
         return snapshot
 
     def _wait_for_volume_available_on_the_system(self, ip_address,
@@ -88,7 +85,7 @@
                                           CONF.compute.build_interval):
             raise lib_exc.TimeoutException
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.skip_because(bug="1664793")
     @decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 8cab19c..3dfbf18 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -13,9 +13,9 @@
 from oslo_log import log as logging
 import testtools
 
-from tempest.common.utils import data_utils
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.scenario import manager
 from tempest import test
@@ -81,13 +81,7 @@
         self.addCleanup(self.snapshots_client.delete_snapshot, snap['id'])
         waiters.wait_for_volume_resource_status(self.snapshots_client,
                                                 snap['id'], 'available')
-
-        # NOTE(e0ne): Cinder API v2 uses name instead of display_name
-        if 'display_name' in snap:
-            self.assertEqual(snap_name, snap['display_name'])
-        else:
-            self.assertEqual(snap_name, snap['name'])
-
+        self.assertEqual(snap_name, snap['name'])
         return snap
 
     def _delete_server(self, server):
@@ -176,7 +170,7 @@
         self.assertEqual(timestamp, timestamp3)
 
     @decorators.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'image', 'volume')
     def test_create_server_from_volume_snapshot(self):
         # Create a volume from an image
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index f580ea6..a3cb3eb 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -40,10 +40,7 @@
     @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
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
 
     @classmethod
     def skip_checks(cls):
@@ -91,7 +88,7 @@
         waiters.wait_for_volume_retype(self.volumes_client,
                                        volume_id, new_volume_type)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('deadd2c2-beef-4dce-98be-f86765ff311b')
     @test.services('compute', 'volume')
     def test_volume_migrate_attached(self):
diff --git a/tempest/services/object_storage/__init__.py b/tempest/services/object_storage/__init__.py
index d1a61d6..1738566 100644
--- a/tempest/services/object_storage/__init__.py
+++ b/tempest/services/object_storage/__init__.py
@@ -13,10 +13,12 @@
 # the License.
 
 from tempest.services.object_storage.account_client import AccountClient
+from tempest.services.object_storage.bulk_middleware_client import \
+    BulkMiddlewareClient
 from tempest.services.object_storage.capabilities_client import \
     CapabilitiesClient
 from tempest.services.object_storage.container_client import ContainerClient
 from tempest.services.object_storage.object_client import ObjectClient
 
-__all__ = ['AccountClient', 'CapabilitiesClient', 'ContainerClient',
-           'ObjectClient']
+__all__ = ['AccountClient', 'BulkMiddlewareClient', 'CapabilitiesClient',
+           'ContainerClient', 'ObjectClient']
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 4859e75..5a1737e 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -23,39 +23,30 @@
 
 class AccountClient(rest_client.RestClient):
 
-    def create_account(self, data=None,
-                       params=None,
-                       metadata=None,
-                       remove_metadata=None,
-                       metadata_prefix='X-Account-Meta-',
-                       remove_metadata_prefix='X-Remove-Account-Meta-'):
-        """Create an account."""
-        if metadata is None:
-            metadata = {}
-        if remove_metadata is None:
-            remove_metadata = {}
-        url = ''
-        if params:
-            url += '?%s' % urllib.urlencode(params)
+    def create_update_or_delete_account_metadata(
+            self,
+            create_update_metadata=None,
+            delete_metadata=None,
+            create_update_metadata_prefix='X-Account-Meta-',
+            delete_metadata_prefix='X-Remove-Account-Meta-'):
+        """Creates, Updates or deletes an account metadata entry.
 
+        Account Metadata can be created, updated or deleted based on
+        metadata header or value. For detailed info, please refer to the
+        official API reference:
+        http://developer.openstack.org/api-ref/object-storage/?expanded=create-update-or-delete-account-metadata-detail
+        """
         headers = {}
-        for key in metadata:
-            headers[metadata_prefix + key] = metadata[key]
-        for key in remove_metadata:
-            headers[remove_metadata_prefix + key] = remove_metadata[key]
+        if create_update_metadata:
+            for key in create_update_metadata:
+                metadata_header_name = create_update_metadata_prefix + key
+                headers[metadata_header_name] = create_update_metadata[key]
+        if delete_metadata:
+            for key in delete_metadata:
+                headers[delete_metadata_prefix + key] = delete_metadata[key]
 
-        resp, body = self.put(url, data, headers)
-        self.expected_success(200, resp.status)
-        return resp, body
-
-    def delete_account(self, data=None, params=None):
-        """Delete an account."""
-        url = ''
-        if params:
-            url = '?%s%s' % (url, urllib.urlencode(params))
-
-        resp, body = self.delete(url, headers={}, body=data)
-        self.expected_success(200, resp.status)
+        resp, body = self.post('', headers=headers, body=None)
+        self.expected_success([200, 204], resp.status)
         return resp, body
 
     def list_account_metadata(self):
@@ -67,51 +58,6 @@
         self.expected_success(204, resp.status)
         return resp, body
 
-    def create_account_metadata(self, metadata,
-                                metadata_prefix='X-Account-Meta-',
-                                data=None, params=None):
-        """Creates an account metadata entry."""
-        headers = {}
-        if metadata:
-            for key in metadata:
-                headers[metadata_prefix + key] = metadata[key]
-
-        url = ''
-        if params:
-            url = '?%s%s' % (url, urllib.urlencode(params))
-
-        resp, body = self.post(url, headers=headers, body=data)
-        self.expected_success([200, 204], resp.status)
-        return resp, body
-
-    def delete_account_metadata(self, metadata,
-                                metadata_prefix='X-Remove-Account-Meta-'):
-        """Deletes an account metadata entry."""
-
-        headers = {}
-        for item in metadata:
-            headers[metadata_prefix + item] = metadata[item]
-        resp, body = self.post('', headers=headers, body=None)
-        self.expected_success(204, resp.status)
-        return resp, body
-
-    def create_and_delete_account_metadata(
-            self,
-            create_metadata=None,
-            delete_metadata=None,
-            create_metadata_prefix='X-Account-Meta-',
-            delete_metadata_prefix='X-Remove-Account-Meta-'):
-        """Creates and deletes an account metadata entry."""
-        headers = {}
-        for key in create_metadata:
-            headers[create_metadata_prefix + key] = create_metadata[key]
-        for key in delete_metadata:
-            headers[delete_metadata_prefix + key] = delete_metadata[key]
-
-        resp, body = self.post('', headers=headers, body=None)
-        self.expected_success(204, resp.status)
-        return resp, body
-
     def list_account_containers(self, params=None):
         """GET on the (base) storage URL
 
diff --git a/tempest/services/object_storage/bulk_middleware_client.py b/tempest/services/object_storage/bulk_middleware_client.py
new file mode 100644
index 0000000..c194ea9
--- /dev/null
+++ b/tempest/services/object_storage/bulk_middleware_client.py
@@ -0,0 +1,62 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common import rest_client
+
+
+class BulkMiddlewareClient(rest_client.RestClient):
+
+    def upload_archive(self, upload_path, data,
+                       archive_file_format='tar', headers=None):
+        """Expand tar files into a Swift cluster.
+
+        To extract containers and objects on Swift cluster from
+        uploaded archived file. For More information please check:
+        http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+        """
+        url = '%s?extract-archive=%s' % (upload_path, archive_file_format)
+        if headers is None:
+            headers = {}
+        resp, body = self.put(url, data, headers)
+        self.expected_success(200, resp.status)
+        return resp, body
+
+    def delete_bulk_data(self, data=None, headers=None):
+        """Delete multiple objects or containers from their account.
+
+        For More information please check:
+        http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+        """
+        url = '?bulk-delete'
+
+        if headers is None:
+            headers = {}
+        resp, body = self.delete(url, headers=headers, body=data)
+        self.expected_success(200, resp.status)
+        return resp, body
+
+    def delete_bulk_data_with_post(self, data=None, headers=None):
+        """Delete multiple objects or containers with POST request.
+
+        For More information please check:
+        http://docs.openstack.org/developer/swift/middleware.html#module-swift.common.middleware.bulk
+        """
+        url = '?bulk-delete'
+
+        if headers is None:
+            headers = {}
+        resp, body = self.post(url, headers=headers, body=data)
+        self.expected_success([200, 204], resp.status)
+        return resp, body
diff --git a/tempest/test.py b/tempest/test.py
index 52994ac..2ebdc60 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -29,7 +29,6 @@
 from tempest.common import fixed_network
 import tempest.common.validation_resources as vresources
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common import cred_client
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
@@ -45,22 +44,18 @@
     version='Mitaka', removal_version='?')
 
 
-def attr(**kwargs):
-    """A decorator which applies the testtools attr decorator
+related_bug = debtcollector.moves.moved_function(
+    decorators.related_bug, 'related_bug', __name__,
+    version='Pike', removal_version='?')
 
-    This decorator applies the testtools.testcase.attr if it is in the list of
-    attributes to testtools we want to apply.
-    """
 
-    def decorator(f):
-        if 'type' in kwargs and isinstance(kwargs['type'], str):
-            f = testtools.testcase.attr(kwargs['type'])(f)
-        elif 'type' in kwargs and isinstance(kwargs['type'], list):
-            for attr in kwargs['type']:
-                f = testtools.testcase.attr(attr)(f)
-        return f
+attr = debtcollector.moves.moved_function(
+    decorators.attr, 'attr', __name__,
+    version='Pike', removal_version='?')
 
-    return decorator
+
+class InvalidServiceTag(lib_exc.TempestException):
+    message = "Invalid service tag"
 
 
 def get_service_list():
@@ -82,13 +77,12 @@
     exercised by a test case.
     """
     def decorator(f):
-        services = ['compute', 'image', 'baremetal', 'volume',
-                    'network', 'identity', 'object_storage']
+        known_services = get_service_list()
+
         for service in args:
-            if service not in services:
-                raise exceptions.InvalidServiceTag('%s is not a valid '
-                                                   'service' % service)
-        attr(type=list(args))(f)
+            if service not in known_services:
+                raise InvalidServiceTag('%s is not a valid service' % service)
+        decorators.attr(type=list(args))(f)
 
         @functools.wraps(f)
         def wrapper(self, *func_args, **func_kwargs):
@@ -134,7 +128,7 @@
         'object': CONF.object_storage_feature_enabled.discoverable_apis,
         'identity': CONF.identity_feature_enabled.api_extensions
     }
-    if len(config_dict[service]) == 0:
+    if not config_dict[service]:
         return False
     if config_dict[service][0] == 'all':
         return True
@@ -143,28 +137,6 @@
     return False
 
 
-def related_bug(bug, status_code=None):
-    """A decorator useful to know solutions from launchpad bug reports
-
-    @param bug: The launchpad bug number causing the test
-    @param status_code: The status code related to the bug report
-    """
-    def decorator(f):
-        @functools.wraps(f)
-        def wrapper(self, *func_args, **func_kwargs):
-            try:
-                return f(self, *func_args, **func_kwargs)
-            except Exception as exc:
-                exc_status_code = getattr(exc, 'status_code', None)
-                if status_code is None or status_code == exc_status_code:
-                    LOG.error('Hints: This test was made for the bug %s. '
-                              'The failure could be related to '
-                              'https://launchpad.net/bugs/%s', bug, bug)
-                raise exc
-        return wrapper
-    return decorator
-
-
 def is_scheduler_filter_enabled(filter_name):
     """Check the list of enabled compute scheduler filters from config.
 
@@ -177,7 +149,7 @@
     """
 
     filters = CONF.compute_feature_enabled.scheduler_available_filters
-    if len(filters) == 0:
+    if not filters:
         return False
     if 'all' in filters:
         return True
@@ -642,12 +614,24 @@
         return fixed_network.get_tenant_network(
             cred_provider, networks_client, CONF.compute.fixed_network_name)
 
-    def assertEmpty(self, list, msg=None):
-        if msg is None:
-            msg = "list is not empty: %s" % list
-        self.assertEqual(0, len(list), msg)
+    def assertEmpty(self, items, msg=None):
+        """Asserts whether a sequence or collection is empty
 
-    def assertNotEmpty(self, list, msg=None):
+        :param items: sequence or collection to be tested
+        :param msg: message to be passed to the AssertionError
+        :raises AssertionError: when items is not empty
+        """
         if msg is None:
-            msg = "list is empty."
-        self.assertGreater(len(list), 0, msg)
+            msg = "sequence or collection is not empty: %s" % items
+        self.assertFalse(items, msg)
+
+    def assertNotEmpty(self, items, msg=None):
+        """Asserts whether a sequence or collection is not empty
+
+        :param items: sequence or collection to be tested
+        :param msg: message to be passed to the AssertionError
+        :raises AssertionError: when items is empty
+        """
+        if msg is None:
+            msg = "sequence or collection is empty."
+        self.assertTrue(items, msg)
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index abe2b73..9f75962 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -46,10 +46,42 @@
         """Add additional configuration options to tempest.
 
         This method will be run for the plugin during the register_opts()
-        function in tempest.config
+        function in tempest.config.
 
         :param ConfigOpts conf: The conf object that can be used to register
             additional options on.
+
+        Example::
+
+            # Config options are defined in a config.py module
+            service_option = cfg.BoolOpt(
+                "my_service",
+                default=True,
+                help="Whether or not my service is available")
+
+            # Note: as long as the group is listed in get_opt_lists,
+            # it will be possible to access its optins in the plugin code
+            # via ("-" in the group name are replaces with "_"):
+            #     CONF.my_service.<option_name>
+            my_service_group = cfg.OptGroup(name="my-service",
+                                            title="My service options")
+
+            MyServiceGroup = [<list of options>]
+            # (...) More groups and options...
+
+            # Plugin is implemented in a plugin.py module
+            from my_plugin import config as my_config
+
+            def register_opts(self, conf):
+                conf.register_opt(my_config.service_option,
+                                  group='service_available')
+                conf.register_group(my_config.my_service_group)
+                conf.register_opts(my_config.MyService +
+                                   my_config.my_service_group)
+
+                conf.register_group(my_config.my_service_feature_group)
+                conf.register_opts(my_config.MyServiceFeaturesGroup,
+                                   my_config.my_service_feature_group)
         """
         return
 
@@ -71,43 +103,46 @@
         in any ServiceClients object instantiated by tests.
         The default implementation returns an empty list.
 
-        :return list of dictionaries. Each element of the list represents
-            the service client for an API. Each dict must define all
-            parameters required for the invocation of
-            `service_clients.ServiceClients.register_service_client_module`.
-        :rtype: list
+        :returns: Each element of the list represents the service client for an
+          API. Each dict must define all parameters required for the invocation
+          of `service_clients.ServiceClients.register_service_client_module`.
+        :rtype: list of dictionaries
 
-        Example:
+        Example implementation with one service client::
 
-            >>>  # Example implementation with one service client
-            >>>  myservice_config = config.service_client_config('myservice')
-            >>>  params = {
-            >>>     'name': 'myservice',
-            >>>     'service_version': 'myservice',
-            >>>     'module_path': 'myservice_tempest_tests.services',
-            >>>     'client_names': ['API1Client', 'API2Client'],
-            >>>  }
-            >>>  params.update(myservice_config)
-            >>>  return [params]
+            def get_service_clients(self):
+                # Example implementation with one service client
+                myservice_config = config.service_client_config('myservice')
+                params = {
+                    'name': 'myservice',
+                    'service_version': 'myservice',
+                    'module_path': 'myservice_tempest_tests.services',
+                    'client_names': ['API1Client', 'API2Client'],
+                }
+                params.update(myservice_config)
+                return [params]
 
-            >>>  # Example implementation with two service clients
-            >>>  foo1_config = config.service_client_config('foo')
-            >>>  params_foo1 = {
-            >>>     'name': 'foo_v1',
-            >>>     'service_version': 'foo.v1',
-            >>>     'module_path': 'bar_tempest_tests.services.foo.v1',
-            >>>     'client_names': ['API1Client', 'API2Client'],
-            >>>  }
-            >>>  params_foo1.update(foo_config)
-            >>>  foo2_config = config.service_client_config('foo')
-            >>>  params_foo2 = {
-            >>>     'name': 'foo_v2',
-            >>>     'service_version': 'foo.v2',
-            >>>     'module_path': 'bar_tempest_tests.services.foo.v2',
-            >>>     'client_names': ['API1Client', 'API2Client'],
-            >>>  }
-            >>>  params_foo2.update(foo2_config)
-            >>>  return [params_foo1, params_foo2]
+        Example implementation with two service clients::
+
+            def get_service_clients(self):
+                # Example implementation with two service clients
+                foo1_config = config.service_client_config('foo')
+                params_foo1 = {
+                    'name': 'foo_v1',
+                    'service_version': 'foo.v1',
+                    'module_path': 'bar_tempest_tests.services.foo.v1',
+                    'client_names': ['API1Client', 'API2Client'],
+                }
+                params_foo1.update(foo_config)
+                foo2_config = config.service_client_config('foo')
+                params_foo2 = {
+                    'name': 'foo_v2',
+                    'service_version': 'foo.v2',
+                    'module_path': 'bar_tempest_tests.services.foo.v2',
+                    'client_names': ['API1Client', 'API2Client'],
+                }
+                params_foo2.update(foo2_config)
+                return [params_foo1, params_foo2]
         """
         return []
 
@@ -124,7 +159,6 @@
             'tempest.test_plugins', invoke_on_load=True,
             propagate_map_exceptions=True,
             on_load_failure_callback=self.failure_hook)
-        self._register_service_clients()
 
     @staticmethod
     def failure_hook(_, ep, err):
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 1af0d95..98bf145 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -192,7 +192,7 @@
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, '_get_unversioned_endpoint',
             return_value='http://fake_endpoint:5000'))
-        fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v2.0'}]}
+        fake_resp = {'versions': [{'id': 'v2.0'}]}
         fake_resp = json.dumps(fake_resp)
         mock_request.return_value = (None, fake_resp)
         fake_os = mock.MagicMock()
@@ -206,7 +206,7 @@
         self.useFixture(mockpatch.PatchObject(
             verify_tempest_config, '_get_unversioned_endpoint',
             return_value='http://fake_endpoint:5000'))
-        fake_resp = {'versions': [{'id': 'v1.0'}, {'id': 'v3.0'}]}
+        fake_resp = {'versions': [{'id': 'v3.0'}]}
         fake_resp = json.dumps(fake_resp)
         mock_request.return_value = (None, fake_resp)
         fake_os = mock.MagicMock()
@@ -231,11 +231,9 @@
         with mock.patch.object(verify_tempest_config,
                                'print_and_or_update') as print_mock:
             verify_tempest_config.verify_cinder_api_versions(fake_os, True)
-        print_mock.assert_any_call('api_v1', 'volume-feature-enabled',
-                                   False, True)
         print_mock.assert_any_call('api_v3', 'volume-feature-enabled',
                                    True, True)
-        self.assertEqual(2, print_mock.call_count)
+        self.assertEqual(1, print_mock.call_count)
 
     def test_verify_glance_version_no_v2_with_v1_1(self):
         def fake_get_versions():
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 7199206..ecb8e64 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -139,23 +139,6 @@
         self._assert_exec_called_with(
             "ip addr | awk '/ether/ {print $2}'")
 
-    def test_assign_static_ip(self):
-        self.ssh_mock.mock.exec_command.return_value = ''
-        ip = '10.0.0.2'
-        nic = 'eth0'
-        self.assertEqual(self.conn.assign_static_ip(nic, ip), '')
-        self._assert_exec_called_with(
-            "sudo ip addr add %s/%s dev %s" % (ip, '28', nic))
-
-    def test_set_nic_state(self):
-        nic = 'eth0'
-        self.conn.set_nic_state(nic)
-        self._assert_exec_called_with(
-            'sudo ip link set %s up' % nic)
-        self.conn.set_nic_state(nic, "down")
-        self._assert_exec_called_with(
-            'sudo ip link set %s down' % nic)
-
 
 class TestRemoteClientWithServer(base.TestCase):
 
@@ -182,7 +165,7 @@
                                            user='user',
                                            password='pass')))
         self.log = self.useFixture(fixtures.FakeLogger(
-            name='tempest.common.utils.linux.remote_client',
+            name='tempest.lib.common.utils.linux.remote_client',
             level='DEBUG'))
 
     def test_validate_debug_ssh_console(self):
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index 71a4c81..ee63684 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -93,12 +93,6 @@
         self.conf.set_default('ca_certificates_file', '/fake/certificates',
                               group='identity')
         self.conf.set_default('region', 'fake_region', 'identity')
-        # Identity endpoints
-        self.conf.set_default('v3_endpoint_type', 'fake_v3_uri', 'identity')
-        self.conf.set_default('v2_public_endpoint_type', 'fake_v2_public_uri',
-                              'identity')
-        self.conf.set_default('v2_admin_endpoint_type', 'fake_v2_admin_uri',
-                              'identity')
         # Compute default values
         self.conf.set_default('build_interval', 88, group='compute')
         self.conf.set_default('build_timeout', 8, group='compute')
@@ -109,5 +103,4 @@
         self._set_attrs()
         self.fake_service1 = cfg.CONF['fake-service1']
         self.fake_service2 = cfg.CONF['fake-service2']
-        print('Services registered')
         self.lock_path = cfg.CONF.oslo_concurrency.lock_path
diff --git a/tempest/tests/lib/common/test_cred_client.py b/tempest/tests/lib/common/test_cred_client.py
index 1cb3103..3dff16f 100644
--- a/tempest/tests/lib/common/test_cred_client.py
+++ b/tempest/tests/lib/common/test_cred_client.py
@@ -73,6 +73,5 @@
 
     def test_delete_project(self):
         self.creds_client.delete_project('fake_id')
-        print(self.projects_client.calls)
         self.projects_client.delete_project.assert_called_once_with(
             'fake_id')
diff --git a/tempest/api/volume/admin/v2/__init__.py b/tempest/tests/lib/common/utils/linux/__init__.py
similarity index 100%
copy from tempest/api/volume/admin/v2/__init__.py
copy to tempest/tests/lib/common/utils/linux/__init__.py
diff --git a/tempest/tests/lib/common/utils/linux/test_remote_client.py b/tempest/tests/lib/common/utils/linux/test_remote_client.py
new file mode 100644
index 0000000..cf312f4
--- /dev/null
+++ b/tempest/tests/lib/common/utils/linux/test_remote_client.py
@@ -0,0 +1,67 @@
+# Copyright 2017 NEC Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+
+from tempest.lib.common import ssh
+from tempest.lib.common.utils.linux import remote_client
+from tempest.lib import exceptions as lib_exc
+from tempest.tests import base
+
+
+class FakeServersClient(object):
+
+    def get_console_output(self, server_id):
+        return {"output": "fake_output"}
+
+
+class TestRemoteClient(base.TestCase):
+
+    @mock.patch.object(ssh.Client, 'exec_command', return_value='success')
+    def test_exec_command(self, mock_ssh_exec_command):
+        client = remote_client.RemoteClient('192.168.1.10', 'username')
+        client.exec_command('ls')
+        mock_ssh_exec_command.assert_called_once_with(
+            'set -eu -o pipefail; PATH=$$PATH:/sbin; ls')
+
+    @mock.patch.object(ssh.Client, 'test_connection_auth')
+    def test_validate_authentication(self, mock_test_connection_auth):
+        client = remote_client.RemoteClient('192.168.1.10', 'username')
+        client.validate_authentication()
+        mock_test_connection_auth.assert_called_once_with()
+
+    @mock.patch.object(remote_client.LOG, 'debug')
+    @mock.patch.object(ssh.Client, 'exec_command')
+    def test_debug_ssh_without_console(self, mock_exec_command, mock_debug):
+        mock_exec_command.side_effect = lib_exc.SSHTimeout
+        server = {'id': 'fake_id'}
+        client = remote_client.RemoteClient('192.168.1.10', 'username',
+                                            server=server)
+        self.assertRaises(lib_exc.SSHTimeout, client.exec_command, 'ls')
+        mock_debug.assert_called_with(
+            'Caller: %s. Timeout trying to ssh to server %s',
+            'TestRemoteClient:test_debug_ssh_without_console', server)
+
+    @mock.patch.object(remote_client.LOG, 'debug')
+    @mock.patch.object(ssh.Client, 'exec_command')
+    def test_debug_ssh_with_console(self, mock_exec_command, mock_debug):
+        mock_exec_command.side_effect = lib_exc.SSHTimeout
+        server = {'id': 'fake_id'}
+        client = remote_client.RemoteClient('192.168.1.10', 'username',
+                                            server=server,
+                                            servers_client=FakeServersClient())
+        self.assertRaises(lib_exc.SSHTimeout, client.exec_command, 'ls')
+        mock_debug.assert_called_with(
+            'Console log for server %s: %s', server['id'], 'fake_output')
diff --git a/tempest/tests/lib/services/compute/test_quotas_client.py b/tempest/tests/lib/services/compute/test_quotas_client.py
index 4c49e8d..bbb8eb7 100644
--- a/tempest/tests/lib/services/compute/test_quotas_client.py
+++ b/tempest/tests/lib/services/compute/test_quotas_client.py
@@ -49,22 +49,35 @@
         self.client = quotas_client.QuotasClient(
             fake_auth, 'compute', 'regionOne')
 
-    def _test_show_quota_set(self, bytes_body=False, user_id=None):
+    def _get_quota_set(self, detail):
+        if not detail:
+            return self.FAKE_QUOTA_SET
+        fake_quota_set = {"quota_set": {}}
+        for key, val in self.FAKE_QUOTA_SET['quota_set'].items():
+            fake_quota_set['quota_set'][key] = \
+                {'limit': val, 'reserved': 0, 'in_use': 0}
+        fake_quota_set['quota_set']['id'] = "8421f7be61064f50b680465c07f334af"
+        return fake_quota_set
+
+    def _test_show_quota_set(self, bytes_body=False, detail=False,
+                             user_id=None):
         if user_id:
             self.check_service_client_function(
                 self.client.show_quota_set,
                 'tempest.lib.common.rest_client.RestClient.get',
-                self.FAKE_QUOTA_SET,
+                self._get_quota_set(detail),
                 to_utf=bytes_body,
                 tenant_id=self.project_id,
+                detail=detail,
                 user_id=user_id)
         else:
             self.check_service_client_function(
                 self.client.show_quota_set,
                 'tempest.lib.common.rest_client.RestClient.get',
-                self.FAKE_QUOTA_SET,
+                self._get_quota_set(detail),
                 to_utf=bytes_body,
-                tenant_id=self.project_id)
+                tenant_id=self.project_id,
+                detail=detail)
 
     def test_show_quota_set_with_str_body(self):
         self._test_show_quota_set()
@@ -78,6 +91,9 @@
     def test_show_quota_set_for_user_with_bytes_body(self):
         self._test_show_quota_set(bytes_body=True, user_id=self.fake_user_id)
 
+    def test_show_quota_set_with_details(self):
+        self._test_show_quota_set(detail=True)
+
     def _test_show_default_quota_set(self, bytes_body=False):
         self.check_service_client_function(
             self.client.show_default_quota_set,
diff --git a/tempest/tests/lib/services/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index 8d391c1..a277dfe 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -168,6 +168,10 @@
         "url": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19"
     }
 
+    FAKE_SERVER_PASSWORD = {
+        "adminPass": "fake-password",
+    }
+
     FAKE_INSTANCE_ACTION_EVENTS = {
         "event": "fake-event",
         "start_time": "2016-10-02T10:00:00-05:00",
@@ -322,6 +326,21 @@
             name='fake-name'
             )
 
+    def test_evacuate_server_with_str_body(self):
+        self._test_evacuate_server()
+
+    def test_evacuate_server_with_bytes_body(self):
+        self._test_evacuate_server(bytes_body=True)
+
+    def _test_evacuate_server(self, bytes_body=False):
+        kwargs = {'server_id': self.server_id,
+                  'host': 'fake-target-host'}
+        self.check_service_client_function(
+            self.client.evacuate_server,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_SERVER_PASSWORD,
+            **kwargs)
+
     def test_change_password_with_str_body(self):
         self._test_change_password()
 
diff --git a/tempest/tests/lib/services/identity/v3/test_identity_client.py b/tempest/tests/lib/services/identity/v3/test_identity_client.py
index 9eaaaaf..e435fe2 100644
--- a/tempest/tests/lib/services/identity/v3/test_identity_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_identity_client.py
@@ -32,6 +32,34 @@
         "description": "test_description"
     }
 
+    FAKE_AUTH_PROJECTS = {
+        "projects": [
+            {
+                "domain_id": "1789d1",
+                "enabled": True,
+                "id": "263fd9",
+                "links": {
+                    "self": "https://example.com/identity/v3/projects/263fd9"
+                },
+                "name": "Test Group"
+            },
+            {
+                "domain_id": "1789d1",
+                "enabled": True,
+                "id": "50ef01",
+                "links": {
+                    "self": "https://example.com/identity/v3/projects/50ef01"
+                },
+                "name": "Build Group"
+            }
+        ],
+        "links": {
+            "self": "https://example.com/identity/v3/auth/projects",
+            "previous": None,
+            "next": None
+        }
+    }
+
     def setUp(self):
         super(TestIdentityClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -54,6 +82,13 @@
             bytes_body,
             resp_token="cbc36478b0bd8e67e89")
 
+    def _test_list_auth_projects(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_auth_projects,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_AUTH_PROJECTS,
+            bytes_body)
+
     def test_show_api_description_with_str_body(self):
         self._test_show_api_description()
 
@@ -73,3 +108,9 @@
             {},
             resp_token="cbc36478b0bd8e67e89",
             status=204)
+
+    def test_list_auth_projects_with_str_body(self):
+        self._test_list_auth_projects()
+
+    def test_list_auth_projects_with_bytes_body(self):
+        self._test_list_auth_projects(bytes_body=True)
diff --git a/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
new file mode 100644
index 0000000..8d53792
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
@@ -0,0 +1,160 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.services.identity.v3 import oauth_consumers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestOAUTHConsumerClient(base.BaseServiceTest):
+    FAKE_CREATE_CONSUMER = {
+        "consumer": {
+            'description': 'A fake description 1'
+        }
+
+    }
+
+    FAKE_CONSUMER_INFO = {
+        "consumer": {
+            'id': '6392c7d3b7a2062e09a07aa377',
+            'links': {
+                'self': 'http://example.com/identity/v3/' +
+                        'OS-OAUTH1/consumers/g6f2l9'
+            },
+            'description': 'A description that is fake'
+        }
+
+    }
+
+    FAKE_LIST_CONSUMERS = {
+        'links': {
+            'self': 'http://example.com/identity/v3/OS-OAUTH1/consumers/',
+            'next': None,
+            'previous': None
+        },
+        'consumers': [
+            {
+                'id': '6392c7d3b7a2062e09a07aa377',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/6b9f2g5'
+                },
+                'description': 'A description that is fake'
+            },
+            {
+                'id': '677a855c9e3eb3a3954b36aca6',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/6a9f2366'
+                },
+                'description': 'A very fake description 2'
+            },
+            {
+                'id': '9d3ac57b08d65e07826b5e506',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/626b5e506'
+                },
+                'description': 'A very fake description 3'
+            },
+            {
+                'id': 'b522d163b1a18e928aca9y426',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/g7ca9426'
+                },
+                'description': 'A very fake description 4'
+            },
+            {
+                'id': 'b7e47321b5ef9051f93c2049e',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/23d82049e'
+                },
+                'description': 'A very fake description 5'
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestOAUTHConsumerClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = oauth_consumers_client.OAUTHConsumerClient(fake_auth,
+                                                                 'identity',
+                                                                 'regionOne')
+
+    def _test_create_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_consumer,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_CONSUMER,
+            bytes_body,
+            description=self.FAKE_CREATE_CONSUMER["consumer"]["description"],
+            status=201)
+
+    def _test_show_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_consumer,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CONSUMER_INFO,
+            bytes_body,
+            consumer_id="6392c7d3b7a2062e09a07aa377")
+
+    def _test_list_consumers(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_consumers,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_CONSUMERS,
+            bytes_body)
+
+    def _test_update_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_consumer,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_CONSUMER_INFO,
+            bytes_body,
+            consumer_id="6392c7d3b7a2062e09a07aa377")
+
+    def test_create_consumer_with_str_body(self):
+        self._test_create_consumer()
+
+    def test_create_consumer_with_bytes_body(self):
+        self._test_create_consumer(bytes_body=True)
+
+    def test_show_consumer_with_str_body(self):
+        self._test_show_consumer()
+
+    def test_show_consumer_with_bytes_body(self):
+        self._test_show_consumer(bytes_body=True)
+
+    def test_list_consumers_with_str_body(self):
+        self._test_list_consumers()
+
+    def test_list_consumers_with_bytes_body(self):
+        self._test_list_consumers(bytes_body=True)
+
+    def test_update_consumer_with_str_body(self):
+        self._test_update_consumer()
+
+    def test_update_consumer_with_bytes_body(self):
+        self._test_update_consumer(bytes_body=True)
+
+    def test_delete_consumer(self):
+        self.check_service_client_function(
+            self.client.delete_consumer,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            consumer_id="6392c7d3b7a2062e09a07aa377",
+            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 41cea85..8d6bb42 100644
--- a/tempest/tests/lib/services/identity/v3/test_roles_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_roles_client.py
@@ -26,6 +26,18 @@
     FAKE_ROLE_ID_2 = "2"
     FAKE_ROLE_NAME_2 = "test2"
 
+    FAKE_ROLE_ID_3 = "3"
+    FAKE_ROLE_NAME_3 = "test3"
+
+    FAKE_ROLE_ID_4 = "4"
+    FAKE_ROLE_NAME_4 = "test4"
+
+    FAKE_ROLE_ID_5 = "5"
+    FAKE_ROLE_NAME_5 = "test5"
+
+    FAKE_ROLE_ID_6 = "6"
+    FAKE_ROLE_NAME_6 = "test6"
+
     FAKE_ROLE_INFO = {
         "role": {
             "domain_id": FAKE_DOMAIN_ID,
@@ -77,8 +89,8 @@
         }
     }
 
-    FAKE_LIST_ROLE_INFERENCES_RULES = {
-        "role_inference": {
+    COMMON_FAKE_LIST_ROLE_INFERENCE_RULES = [
+        {
             "prior_role": {
                 "id": FAKE_ROLE_ID,
                 "name": FAKE_ROLE_NAME,
@@ -97,20 +109,60 @@
                     }
                 },
                 {
-                    "id": "3",
-                    "name": "test3",
+                    "id": FAKE_ROLE_ID_3,
+                    "name": FAKE_ROLE_NAME_3,
                     "links": {
-                        "self": "http://example.com/identity/v3/roles/3"
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_3)
                     }
                 }
             ]
         },
+        {
+            "prior_role": {
+                "id": FAKE_ROLE_ID_4,
+                "name": FAKE_ROLE_NAME_4,
+                "links": {
+                    "self": "http://example.com/identity/v3/roles/%s" % (
+                        FAKE_ROLE_ID_4)
+                }
+            },
+            "implies": [
+                {
+                    "id": FAKE_ROLE_ID_5,
+                    "name": FAKE_ROLE_NAME_5,
+                    "links": {
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_5)
+                    }
+                },
+                {
+                    "id": FAKE_ROLE_ID_6,
+                    "name": FAKE_ROLE_NAME_6,
+                    "links": {
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_6)
+                    }
+                }
+            ]
+        }
+    ]
+
+    FAKE_LIST_ROLE_INFERENCE_RULES = {
+        "role_inference": COMMON_FAKE_LIST_ROLE_INFERENCE_RULES[0],
         "links": {
             "self": "http://example.com/identity/v3/roles/"
                     "%s/implies" % FAKE_ROLE_ID
         }
     }
 
+    FAKE_LIST_ALL_ROLE_INFERENCE_RULES = {
+        "role_inferences": COMMON_FAKE_LIST_ROLE_INFERENCE_RULES,
+        "links": {
+            "self": "http://example.com/identity/v3/role_inferences"
+        }
+    }
+
     def setUp(self):
         super(TestRolesClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -254,10 +306,17 @@
         self.check_service_client_function(
             self.client.list_role_inferences_rules,
             'tempest.lib.common.rest_client.RestClient.get',
-            self.FAKE_LIST_ROLE_INFERENCES_RULES,
+            self.FAKE_LIST_ROLE_INFERENCE_RULES,
             bytes_body,
             prior_role=self.FAKE_ROLE_ID)
 
+    def _test_list_all_role_inference_rules(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_all_role_inference_rules,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_ALL_ROLE_INFERENCE_RULES,
+            bytes_body)
+
     def test_create_role_with_str_body(self):
         self._test_create_role()
 
@@ -441,3 +500,9 @@
             status=204,
             prior_role=self.FAKE_ROLE_ID,
             implies_role=self.FAKE_ROLE_ID_2)
+
+    def test_list_all_role_inference_rules_with_str_body(self):
+        self._test_list_all_role_inference_rules()
+
+    def test_list_all_role_inference_rules_with_bytes_body(self):
+        self._test_list_all_role_inference_rules(bytes_body=True)
diff --git a/tempest/tests/lib/services/image/v2/test_versions_client.py b/tempest/tests/lib/services/image/v2/test_versions_client.py
new file mode 100644
index 0000000..6234b06
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_versions_client.py
@@ -0,0 +1,94 @@
+# Copyright 2017 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.image.v2 import versions_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestVersionsClient(base.BaseServiceTest):
+
+    FAKE_VERSIONS_INFO = {
+        "versions": [
+            {
+                "status": "CURRENT", "id": "v2.5",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "SUPPORTED", "id": "v2.4",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "SUPPORTED", "id": "v2.3",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "SUPPORTED", "id": "v2.2",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "SUPPORTED", "id": "v2.1",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "SUPPORTED", "id": "v2.0",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v2/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "DEPRECATED", "id": "v1.1",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v1/", "rel": "self"}
+                ]
+            },
+            {
+                "status": "DEPRECATED", "id": "v1.0",
+                "links": [
+                    {"href": "https://10.220.1.21:9292/v1/", "rel": "self"}
+                ]
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestVersionsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = versions_client.VersionsClient(fake_auth,
+                                                     'image',
+                                                     'regionOne')
+
+    def _test_list_versions(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_versions,
+            'tempest.lib.common.rest_client.RestClient.raw_request',
+            self.FAKE_VERSIONS_INFO,
+            bytes_body,
+            300)
+
+    def test_list_versions_with_str_body(self):
+        self._test_list_versions()
+
+    def test_list_versions_with_bytes_body(self):
+        self._test_list_versions(bytes_body=True)
diff --git a/tempest/tests/lib/services/test_clients.py b/tempest/tests/lib/services/test_clients.py
index a3b390e..a837199 100644
--- a/tempest/tests/lib/services/test_clients.py
+++ b/tempest/tests/lib/services/test_clients.py
@@ -100,9 +100,8 @@
     def test___init___no_module(self):
         auth_provider = fake_auth_provider.FakeAuthProvider()
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
-        with testtools.ExpectedException(ImportError, '.*fake_module.*'):
-            clients.ClientsFactory('fake_module', class_names,
-                                   auth_provider)
+        self.assertRaises(ImportError, clients.ClientsFactory,
+                          'fake_module', class_names, auth_provider)
 
     def test___init___not_a_class(self):
         class_names = ['FakeServiceClient1', 'FakeServiceClient2']
diff --git a/tempest/tests/lib/services/volume/v3/test_versions_client.py b/tempest/tests/lib/services/volume/v3/test_versions_client.py
new file mode 100644
index 0000000..9627b9a
--- /dev/null
+++ b/tempest/tests/lib/services/volume/v3/test_versions_client.py
@@ -0,0 +1,91 @@
+# Copyright 2017 NEC Corporation.  All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.volume.v3 import versions_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestVersionsClient(base.BaseServiceTest):
+
+    FAKE_VERSIONS_INFO = {
+        "versions": [
+            {
+                "status": "DEPRECATED", "updated": "2016-05-02T20:25:19Z",
+                "links": [
+                    {"href": "http://docs.openstack.org/", "type": "text/html",
+                     "rel": "describedby"},
+                    {"href": "https://10.30.197.39:8776/v1/", "rel": "self"}
+                ],
+                "min_version": "",
+                "version": "",
+                "media-types": [
+                    {"base": "application/json",
+                     "type": "application/vnd.openstack.volume+json;version=1"}
+                ],
+                "id": "v1.0"
+            },
+            {
+                "status": "DEPRECATED", "updated": "2017-02-25T12:00:00Z",
+                "links": [
+                    {"href": "http://docs.openstack.org/", "type": "text/html",
+                     "rel": "describedby"},
+                    {"href": "https://10.30.197.39:8776/v2/", "rel": "self"}
+                ],
+                "min_version": "",
+                "version": "",
+                "media-types": [
+                    {"base": "application/json",
+                     "type": "application/vnd.openstack.volume+json;version=1"}
+                ],
+                "id": "v2.0"
+            },
+            {
+                "status": "CURRENT", "updated": "2016-02-08T12:20:21Z",
+                "links": [
+                    {"href": "http://docs.openstack.org/", "type": "text/html",
+                     "rel": "describedby"},
+                    {"href": "https://10.30.197.39:8776/v3/", "rel": "self"}
+                ],
+                "min_version": "3.0",
+                "version": "3.28",
+                "media-types": [
+                    {"base": "application/json",
+                     "type": "application/vnd.openstack.volume+json;version=1"}
+                ],
+                "id": "v3.0"
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestVersionsClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = versions_client.VersionsClient(fake_auth,
+                                                     'volume',
+                                                     'regionOne')
+
+    def _test_list_versions(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_versions,
+            'tempest.lib.common.rest_client.RestClient.raw_request',
+            self.FAKE_VERSIONS_INFO,
+            bytes_body,
+            300)
+
+    def test_list_versions_with_str_body(self):
+        self._test_list_versions()
+
+    def test_list_versions_with_bytes_body(self):
+        self._test_list_versions(bytes_body=True)
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index f3a4e9c..bbebcd3 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import mock
 import testtools
 
 from tempest.lib import base as test
@@ -21,6 +22,34 @@
 from tempest.tests import base
 
 
+class TestAttrDecorator(base.TestCase):
+    def _test_attr_helper(self, expected_attrs, **decorator_args):
+        @decorators.attr(**decorator_args)
+        def foo():
+            pass
+
+        # By our decorators.attr decorator the attribute __testtools_attrs
+        # will be set only for 'type' argument, so we test it first.
+        if 'type' in decorator_args:
+            # this is what testtools sets
+            self.assertEqual(getattr(foo, '__testtools_attrs'),
+                             set(expected_attrs))
+
+    def test_attr_without_type(self):
+        self._test_attr_helper(expected_attrs='baz', bar='baz')
+
+    def test_attr_decorator_with_list_type(self):
+        # if type is 'smoke' we'll get the original list of types
+        self._test_attr_helper(expected_attrs=['smoke', 'foo'],
+                               type=['smoke', 'foo'])
+
+    def test_attr_decorator_with_unknown_type(self):
+        self._test_attr_helper(expected_attrs=['foo'], type='foo')
+
+    def test_attr_decorator_with_duplicated_type(self):
+        self._test_attr_helper(expected_attrs=['foo'], type=['foo', 'foo'])
+
+
 class TestSkipBecauseDecorator(base.TestCase):
     def _test_skip_because_helper(self, expected_to_skip=True,
                                   **decorator_args):
@@ -123,3 +152,33 @@
 
     def test_no_skip_for_attr_exist_and_true(self):
         self._test_skip_unless_attr('expected_attr', expected_to_skip=False)
+
+
+class TestRelatedBugDecorator(base.TestCase):
+    def test_relatedbug_when_no_exception(self):
+        f = mock.Mock()
+        sentinel = object()
+
+        @decorators.related_bug(bug="1234", status_code=500)
+        def test_foo(self):
+            f(self)
+
+        test_foo(sentinel)
+        f.assert_called_once_with(sentinel)
+
+    def test_relatedbug_when_exception(self):
+        class MyException(Exception):
+            def __init__(self, status_code):
+                self.status_code = status_code
+
+        def f(self):
+            raise MyException(status_code=500)
+
+        @decorators.related_bug(bug="1234", status_code=500)
+        def test_foo(self):
+            f(self)
+
+        with mock.patch.object(decorators.LOG, 'error') as m_error:
+            self.assertRaises(MyException, test_foo, object())
+
+        m_error.assert_called_once_with(mock.ANY, '1234', '1234')
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index ae2f2a3..8b6472b 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -17,7 +17,6 @@
 import testtools
 
 from tempest import config
-from tempest import exceptions
 from tempest.lib.common.utils import data_utils
 from tempest import test
 from tempest.tests import base
@@ -32,34 +31,6 @@
                          fake_config.FakePrivate)
 
 
-class TestAttrDecorator(BaseDecoratorsTest):
-    def _test_attr_helper(self, expected_attrs, **decorator_args):
-        @test.attr(**decorator_args)
-        def foo():
-            pass
-
-        # By our test.attr decorator the attribute __testtools_attrs will be
-        # set only for 'type' argument, so we test it first.
-        if 'type' in decorator_args:
-            # this is what testtools sets
-            self.assertEqual(getattr(foo, '__testtools_attrs'),
-                             set(expected_attrs))
-
-    def test_attr_without_type(self):
-        self._test_attr_helper(expected_attrs='baz', bar='baz')
-
-    def test_attr_decorator_with_list_type(self):
-        # if type is 'smoke' we'll get the original list of types
-        self._test_attr_helper(expected_attrs=['smoke', 'foo'],
-                               type=['smoke', 'foo'])
-
-    def test_attr_decorator_with_unknown_type(self):
-        self._test_attr_helper(expected_attrs=['foo'], type='foo')
-
-    def test_attr_decorator_with_duplicated_type(self):
-        self._test_attr_helper(expected_attrs=['foo'], type=['foo', 'foo'])
-
-
 class TestIdempotentIdDecorator(BaseDecoratorsTest):
 
     def _test_helper(self, _id, **decorator_args):
@@ -119,7 +90,7 @@
         self._test_services_helper('compute', 'compute')
 
     def test_services_decorator_with_invalid_service(self):
-        self.assertRaises(exceptions.InvalidServiceTag,
+        self.assertRaises(test.InvalidServiceTag,
                           self._test_services_helper, 'compute',
                           'bad_service')
 
@@ -135,7 +106,7 @@
         for service in service_list:
             try:
                 self._test_services_helper(service)
-            except exceptions.InvalidServiceTag:
+            except test.InvalidServiceTag:
                 self.fail('%s is not listed in the valid service tag list'
                           % service)
             except KeyError:
diff --git a/tools/generate-tempest-plugins-list.sh b/tools/generate-tempest-plugins-list.sh
index ecff508..e6aad86 100755
--- a/tools/generate-tempest-plugins-list.sh
+++ b/tools/generate-tempest-plugins-list.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -ex
+#!/usr/bin/env bash
 
 # Copyright 2016 Hewlett Packard Enterprise Development Company, L.P.
 #
@@ -38,6 +38,8 @@
 # current working directory, it will be prepended or appended to
 # the generated reStructuredText plugins table respectively.
 
+set -ex
+
 (
 declare -A plugins
 
diff --git a/tools/with_venv.sh b/tools/with_venv.sh
index 165c883..408b5f1 100755
--- a/tools/with_venv.sh
+++ b/tools/with_venv.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)/../}
 VENV_PATH=${VENV_PATH:-${TOOLS_PATH}}
 VENV_DIR=${VENV_DIR:-/.venv}
diff --git a/tox.ini b/tox.ini
index dfa8332..892f834 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = pep8,py35,py34,py27,pip-check-reqs
+envlist = pep8,py35,py27,pip-check-reqs
 minversion = 2.3.1
 skipsdist = True
 
@@ -11,7 +11,6 @@
     BRANCH_NAME=master
     CLIENT_NAME=tempest
 deps =
-    setuptools
     -r{toxinidir}/requirements.txt
 
 [testenv]
@@ -37,7 +36,6 @@
 commands = oslo-config-generator --config-file tempest/cmd/config-generator.tempest.conf
 
 [testenv:cover]
-setenv = OS_TEST_PATH=./tempest/tests
 commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}'
 
 [testenv:all]