Merge "keystone roles are case insensitive"
diff --git a/HACKING.rst b/HACKING.rst
index a209b3f..910a977 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -313,7 +313,7 @@
 qualified test name and track test functionality through refactoring. The
 format of the metadata looks like::
 
-    @test.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
+    @decorators.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
     def test_list_servers_with_detail(self):
         # The created server should be in the detailed list of all servers
         ...
diff --git a/README.rst b/README.rst
index 281516b..c1c6a10 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
@@ -209,15 +208,9 @@
 Python 3.x
 ----------
 
-Starting during the Liberty release development cycle work began on enabling
-Tempest to run under both Python 2.7 and Python 3.4. Tempest strives to fully
-support running with Python 3.4 and newer. A gating unit test job was added to
-also run Tempest's unit tests under Python 3. This means that the Tempest
-code at least imports under Python 3.4 and things that have unit test coverage
-will work on Python 3.4. However, because large parts of Tempest are
-self-verifying there might be uncaught issues running on Python 3. So until
-there is a gating job which does a full Tempest run using Python 3 there
-isn't any guarantee that running Tempest under Python 3 is bug free.
+Starting during the Pike cycle Tempest has a gating CI job that runs tempest
+with Python 3. Any tempest release after 15.0.0 should fully support running
+under Python 3 as well as Python 2.7.
 
 Legacy run method
 -----------------
@@ -263,9 +256,7 @@
 
     $ testr run tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server
 
-Alternatively, you can use the run_tempest.sh script which will create a venv
-and run the tests or use tox to do the same. Tox also contains several existing
-job configurations. For example::
+Tox also contains several existing job configurations. For example::
 
     $ tox -efull
 
diff --git a/doc/source/microversion_testing.rst b/doc/source/microversion_testing.rst
index 572d425..adbd2dc 100644
--- a/doc/source/microversion_testing.rst
+++ b/doc/source/microversion_testing.rst
@@ -247,3 +247,9 @@
  * `2.42`_
 
  .. _2.42: http://docs.openstack.org/developer/nova/api_microversion_history.html#maximum-in-ocata
+
+* Volume
+
+ * `3.3`_
+
+ .. _3.3:  https://docs.openstack.org/developer/cinder/devref/api_microversion_history.html#id4
diff --git a/doc/source/test-removal.rst b/doc/source/test-removal.rst
index 79a5846..d06e4ba 100644
--- a/doc/source/test-removal.rst
+++ b/doc/source/test-removal.rst
@@ -38,8 +38,10 @@
  #. The test proposed for removal has a failure rate <  0.50% in the gate over
     the past release (the value and interval will likely be adjusted in the
     future)
- #. There must not be an external user/consumer of tempest that depends on the
-    test proposed for removal
+
+    .. _`prong #3`:
+ #. There must not be an external user/consumer of tempest
+    that depends on the test proposed for removal
 
 The answers to 1 and 2 are easy to verify. For 1 just provide a link to the new
 test location. If you are linking to the tempest removal patch please also put
@@ -62,7 +64,7 @@
 
 SELECT * from tests where test_id like "%test_id%";
 (where $test_id is the full test_id, but truncated to the class because of
-setupClass or tearDownClass failures)
+setUpClass or tearDownClass failures)
 
 You can access the infra mysql subunit2sql db w/ read-only permissions with:
 
@@ -80,7 +82,7 @@
  #. run the query: MySQL [subunit2sql]> select * from tests where test_id like
     "tempest.api.compute.admin.test_flavors_negative.FlavorsAdminNegativeTestJSON%";
     which will return a table of all the tests in the class (but it will also
-    catch failures in setupClass and tearDownClass)
+    catch failures in setUpClass and tearDownClass)
  #. paste the output table with numbers and the mysql command you ran to
     generate it into the etherpad.
 
@@ -133,6 +135,10 @@
  #. A revert for a patch which added a broken test, or testing which didn't
     actually run in the gate (basically any revert for something which
     shouldn't have been added)
+ #. Tests that would become out of scope as a consequence of an API change,
+    as described in `API Compatibility`_.
+    Such tests cannot live in Tempest because of the branchless nature of
+    Tempest. Such test must still honor `prong #3`_.
 
 For the first exception type the only types of testing in tree which have been
 declared out of scope at this point are:
@@ -149,7 +155,7 @@
 Tempest Scope
 ^^^^^^^^^^^^^
 
-Also starting in the liberty cycle tempest has defined a set of projects which
+Starting in the liberty cycle tempest has defined a set of projects which
 are defined as in scope for direct testing in tempest. As of today that list
 is:
 
@@ -166,3 +172,17 @@
 to maintain continuity after migrating the tests out of tempest.
 
 .. _tempest plugin mechanism: http://docs.openstack.org/developer/tempest/plugin.html
+
+API Compatibility
+"""""""""""""""""
+
+If an API introduces a non-discoverable, backward incompatible change, and
+such change is not backported to all versions supported by Tempest, tests for
+that API cannot live in Tempest anymore.
+This is because tests would not be able to know or control which API response
+to expect, and thus would not be able to enforce a specific behavior.
+
+If a test exists in Tempest that would meet this criteria as consequence of a
+change, the test must be removed according to the procedure discussed into
+this document. The API change should not be merged until all conditions
+required for test removal can be met.
diff --git a/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml b/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
index aa3a78e..389b29f 100644
--- a/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
+++ b/releasenotes/notes/14.0.0-remo-stress-tests-81052b211ad95d2e.yaml
@@ -1,4 +1,13 @@
 ---
+prelude: >
+  This release is marking the end of Liberty release support in Tempest
 upgrade:
   - The Stress tests framework and all the stress tests have been removed.
+other:
+  - |
+    OpenStack releases supported at this time are **Mitaka** and **Newton**.
 
+    The release under current development as of this tag is Ocata, meaning that
+    every Tempest commit is also tested against master during the Ocata cycle.
+    However, this does not necessarily mean that using Tempest as of this tag
+    will work against a Ocata (or future releases) cloud.
diff --git a/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml b/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
index 8665b8b..104bf27 100644
--- a/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
+++ b/releasenotes/notes/15.0.0-remove-deprecated-compute-validation-config-options-e3d1b89ce074d71c.yaml
@@ -1,4 +1,6 @@
 ---
+prelude: >
+    This release is marking the start of Ocata release support in Tempest
 upgrade:
   - |
     Below deprecated config options from compute group have been removed.
@@ -11,4 +13,13 @@
     - ``compute.ping_size `` (available as ``validation.ping_size``)
     - ``compute.ping_count `` (available as ``validation.ping_count``)
     - ``compute.floating_ip_range `` (available as ``validation.floating_ip_range``)
+other:
+  - |
+    OpenStack releases supported at this time are **Mitaka**, **Newton**,
+    and **Ocata**.
 
+    The release under current development as of this tag is Pike,
+    meaning that every Tempest commit is also tested against master during
+    the Pike cycle. However, this does not necessarily mean that using
+    Tempest as of this tag will work against a Pike (or future releases)
+    cloud.
diff --git a/releasenotes/notes/15.0.0-start-of-pike-support-4925678d477b0745.yaml b/releasenotes/notes/15.0.0-start-of-pike-support-4925678d477b0745.yaml
deleted file mode 100644
index 5555949..0000000
--- a/releasenotes/notes/15.0.0-start-of-pike-support-4925678d477b0745.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-prelude: >
-    This release is marking the start of Ocata release support in Tempest
-other:
-  - |
-    OpenStack releases supported at this time are **Mitaka**, **Newton**,
-    and **Ocata**.
-
-    The release under current development as of this tag is Pike,
-    meaning that every Tempest commit is also tested against master during
-    the Pike cycle. However, this does not necessarily mean that using
-    Tempest as of this tag will work against a Pike (or future releases)
-    cloud.
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-identity-client-944cb7396088a575.yaml b/releasenotes/notes/add-list-version-to-identity-client-944cb7396088a575.yaml
new file mode 100644
index 0000000..dd66ff5
--- /dev/null
+++ b/releasenotes/notes/add-list-version-to-identity-client-944cb7396088a575.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add versions_client module for identity service.
+    This new module provides list_versions() method which shows API versions
+    from Identity 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-tempest-run-combine-option-e94c1049ba8985d5.yaml b/releasenotes/notes/add-tempest-run-combine-option-e94c1049ba8985d5.yaml
new file mode 100644
index 0000000..73900ca
--- /dev/null
+++ b/releasenotes/notes/add-tempest-run-combine-option-e94c1049ba8985d5.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Adds a new cli option to tempest run, --combine, which is used to indicate
+    you want the subunit stream output combined with the previous run's in
+    the testr repository
diff --git a/releasenotes/notes/create-server-tags-client-8c0042a77e859af6.yaml b/releasenotes/notes/create-server-tags-client-8c0042a77e859af6.yaml
new file mode 100644
index 0000000..9927971
--- /dev/null
+++ b/releasenotes/notes/create-server-tags-client-8c0042a77e859af6.yaml
@@ -0,0 +1,8 @@
+---
+features:
+  - |
+    Add server tags APIs to the servers_client library.
+    This feature enables the possibility of upating, deleting
+    and checking existence of a tag on a server, as well
+    as updating and deleting all tags on a server.
+
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/deprecate-resources-prefix-option-ad490c0a30a0266b.yaml b/releasenotes/notes/deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
new file mode 100644
index 0000000..f679208
--- /dev/null
+++ b/releasenotes/notes/deprecate-resources-prefix-option-ad490c0a30a0266b.yaml
@@ -0,0 +1,10 @@
+---
+upgrade:
+  - The default value of rand_name()'s prefix argument is changed
+    to 'tempest' from None to identify resources are created by
+    Tempest.
+deprecations:
+  - The resources_prefix is marked as deprecated because it is
+    enough to set 'tempest' as the prefix on rand_name() to
+    ideintify resources which are created by Tempest and no
+    projects set this option on OpenStack dev community.
diff --git a/releasenotes/notes/deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml b/releasenotes/notes/deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml
new file mode 100644
index 0000000..4d8b941
--- /dev/null
+++ b/releasenotes/notes/deprecate-skip_unless_attr-decorator-450a1ed727494724.yaml
@@ -0,0 +1,5 @@
+---
+deprecations:
+  - The ``skip_unless_attr`` decorator in lib/decorators.py has been deprecated,
+    please use the standard ``testtools.skipUnless`` and ``testtools.skipIf``
+    decorators.
diff --git a/releasenotes/notes/deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml b/releasenotes/notes/deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml
new file mode 100644
index 0000000..6285ea6
--- /dev/null
+++ b/releasenotes/notes/deprecate-skip_unless_config-decorator-64c32d588043ab12.yaml
@@ -0,0 +1,5 @@
+---
+deprecations:
+  - The ``skip_unless_config`` and ``skip_if_config`` decorators in the
+    ``config`` module have been deprecated and will be removed in the Queens
+    dev cycle. Use the ``testtools.skipUnless`` (or a variation of) instead.
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/remove-call_until_true-of-test-de9c13bc8f969921.yaml b/releasenotes/notes/remove-call_until_true-of-test-de9c13bc8f969921.yaml
new file mode 100644
index 0000000..5670821
--- /dev/null
+++ b/releasenotes/notes/remove-call_until_true-of-test-de9c13bc8f969921.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+  - The *call_until_true* of *test* module is removed because it was marked
+    as deprecated and Tempest provides it from *test_utils* as a stable
+    interface instead. Please switch to use *test_utils.call_until_true* if
+    necessary.
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/remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml b/releasenotes/notes/remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml
new file mode 100644
index 0000000..fc15995
--- /dev/null
+++ b/releasenotes/notes/remove-volume_feature_enabled.volume_services-c6aa142cc1021297.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - |
+    The deprecated ``volume_services`` option in the ``volume_feature_enabled``
+    section has now been removed.
diff --git a/releasenotes/notes/use-keystone-v3-api-935860d30ddbb8e9.yaml b/releasenotes/notes/use-keystone-v3-api-935860d30ddbb8e9.yaml
new file mode 100644
index 0000000..dd6e924
--- /dev/null
+++ b/releasenotes/notes/use-keystone-v3-api-935860d30ddbb8e9.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+  - Tempest now defaults to using Keystone v3 API for the
+    authentication, because Keystone v3 API is CURRENT and
+    the v2 API is deprecated.
diff --git a/requirements.txt b/requirements.txt
index d9a9ebb..92825a7 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>=1.8 # Apache-2.0
+pbr>=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,15 +9,15 @@
 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.config>=3.22.0 # Apache-2.0
 oslo.log>=3.11.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils>=3.18.0 # Apache-2.0
+oslo.utils>=3.20.0 # Apache-2.0
 six>=1.9.0 # MIT
 fixtures>=3.0.0 # Apache-2.0/BSD
 PyYAML>=3.10.0 # MIT
 python-subunit>=0.0.18 # Apache-2.0/BSD
-stevedore>=1.17.1 # Apache-2.0
+stevedore>=1.20.0 # Apache-2.0
 PrettyTable<0.8,>=0.7.1 # BSD
 os-testr>=0.8.0 # Apache-2.0
 urllib3>=1.15.1 # MIT
diff --git a/run_tempest.sh b/run_tempest.sh
deleted file mode 100755
index 414146b..0000000
--- a/run_tempest.sh
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env bash
-
-echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
-
-function usage {
-  echo "Usage: $0 [OPTION]..."
-  echo "Run Tempest test suite"
-  echo ""
-  echo "  -V, --virtual-env        Always use virtualenv.  Install automatically if not present"
-  echo "  -N, --no-virtual-env     Don't use virtualenv.  Run tests in local environment"
-  echo "  -n, --no-site-packages   Isolate the virtualenv from the global Python environment"
-  echo "  -f, --force              Force a clean re-build of the virtual environment. Useful when dependencies have been added."
-  echo "  -u, --update             Update the virtual environment with any newer package versions"
-  echo "  -s, --smoke              Only run smoke tests"
-  echo "  -t, --serial             Run testr serially"
-  echo "  -C, --config             Config file location"
-  echo "  -h, --help               Print this usage message"
-  echo "  -d, --debug              Run tests with testtools instead of testr. This allows you to use PDB"
-  echo "  -- [TESTROPTIONS]        After the first '--' you can pass arbitrary arguments to testr "
-}
-
-testrargs=""
-venv=${VENV:-.venv}
-with_venv=tools/with_venv.sh
-serial=0
-always_venv=0
-never_venv=0
-no_site_packages=0
-debug=0
-force=0
-wrapper=""
-config_file=""
-update=0
-
-if ! options=$(getopt -o VNnfusthdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,help,debug,config: -- "$@")
-then
-    # parse error
-    usage
-    exit 1
-fi
-
-eval set -- $options
-first_uu=yes
-while [ $# -gt 0 ]; do
-  case "$1" in
-    -h|--help) usage; exit;;
-    -V|--virtual-env) always_venv=1; never_venv=0;;
-    -N|--no-virtual-env) always_venv=0; never_venv=1;;
-    -n|--no-site-packages) no_site_packages=1;;
-    -f|--force) force=1;;
-    -u|--update) update=1;;
-    -d|--debug) debug=1;;
-    -C|--config) config_file=$2; shift;;
-    -s|--smoke) testrargs+="smoke";;
-    -t|--serial) serial=1;;
-    --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no  ;;
-    *) testrargs="$testrargs $1";;
-  esac
-  shift
-done
-
-if [ -n "$config_file" ]; then
-    config_file=`readlink -f "$config_file"`
-    export TEMPEST_CONFIG_DIR=`dirname "$config_file"`
-    export TEMPEST_CONFIG=`basename "$config_file"`
-fi
-
-cd `dirname "$0"`
-
-if [ $no_site_packages -eq 1 ]; then
-  installvenvopts="--no-site-packages"
-fi
-
-function testr_init {
-  if [ ! -d .testrepository ]; then
-      ${wrapper} testr init
-  fi
-}
-
-function run_tests {
-  testr_init
-  ${wrapper} find . -type f -name "*.pyc" -delete
-  export OS_TEST_PATH=./tempest/test_discover
-  if [ $debug -eq 1 ]; then
-      if [ "$testrargs" = "" ]; then
-           testrargs="discover ./tempest/test_discover"
-      fi
-      ${wrapper} python -m testtools.run $testrargs
-      return $?
-  fi
-
-  if [ $serial -eq 1 ]; then
-      ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-trace -n -f
-  else
-      ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-trace -n -f
-  fi
-}
-
-if [ $never_venv -eq 0 ]
-then
-  # Remove the virtual environment if --force used
-  if [ $force -eq 1 ]; then
-    echo "Cleaning virtualenv..."
-    rm -rf ${venv}
-  fi
-  if [ $update -eq 1 ]; then
-      echo "Updating virtualenv..."
-      virtualenv $installvenvopts $venv
-      $venv/bin/pip install -U -r requirements.txt
-  fi
-  if [ -e ${venv} ]; then
-    wrapper="${with_venv}"
-  else
-    if [ $always_venv -eq 1 ]; then
-      # Automatically install the virtualenv
-      virtualenv $installvenvopts $venv
-      wrapper="${with_venv}"
-      ${wrapper} pip install -U -r requirements.txt
-    else
-      echo -e "No virtual environment found...create one? (Y/n) \c"
-      read use_ve
-      if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
-        # Install the virtualenv and run the test suite in it
-        virtualenv $installvenvopts $venv
-        wrapper=${with_venv}
-        ${wrapper} pip install -U -r requirements.txt
-      fi
-    fi
-  fi
-fi
-
-run_tests
-retval=$?
-
-exit $retval
diff --git a/run_tests.sh b/run_tests.sh
deleted file mode 100755
index a856bb4..0000000
--- a/run_tests.sh
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/env bash
-
-function usage {
-  echo "Usage: $0 [OPTION]..."
-  echo "Run Tempest unit tests"
-  echo ""
-  echo "  -V, --virtual-env        Always use virtualenv.  Install automatically if not present"
-  echo "  -N, --no-virtual-env     Don't use virtualenv.  Run tests in local environment"
-  echo "  -n, --no-site-packages   Isolate the virtualenv from the global Python environment"
-  echo "  -f, --force              Force a clean re-build of the virtual environment. Useful when dependencies have been added."
-  echo "  -u, --update             Update the virtual environment with any newer package versions"
-  echo "  -t, --serial             Run testr serially"
-  echo "  -p, --pep8               Just run pep8"
-  echo "  -c, --coverage           Generate coverage report"
-  echo "  -h, --help               Print this usage message"
-  echo "  -d, --debug              Run tests with testtools instead of testr. This allows you to use PDB"
-  echo "  -- [TESTROPTIONS]        After the first '--' you can pass arbitrary arguments to testr "
-}
-
-function deprecation_warning {
-  cat <<EOF
--------------------------------------------------------------------------
-WARNING: run_tests.sh is deprecated and this script will be removed after
-the Newton release. All tests should be run through testr/ostestr or tox.
-
-To run style checks:
-
- tox -e pep8
-
-To run python 2.7 unit tests
-
- tox -e py27
-
-To run unit tests and generate coverage report
-
- tox -e cover
-
-To run a subset of any of these tests:
-
- tox -e py27 someregex
-
- i.e.: tox -e py27 test_servers
-
-Additional tox targets are available in tox.ini. For more information
-see:
-http://docs.openstack.org/project-team-guide/project-setup/python.html
-
-NOTE: if you want to use testr to run tests, you can instead use:
-
- OS_TEST_PATH=./tempest/tests testr run
-
-Documentation on using testr directly can be found at
-http://testrepository.readthedocs.org/en/latest/MANUAL.html
--------------------------------------------------------------------------
-EOF
-}
-
-testrargs=""
-just_pep8=0
-venv=${VENV:-.venv}
-with_venv=tools/with_venv.sh
-serial=0
-always_venv=0
-never_venv=0
-no_site_packages=0
-debug=0
-force=0
-coverage=0
-wrapper=""
-config_file=""
-update=0
-
-deprecation_warning
-
-if ! options=$(getopt -o VNnfuctphd -l virtual-env,no-virtual-env,no-site-packages,force,update,serial,coverage,pep8,help,debug -- "$@")
-then
-    # parse error
-    usage
-    exit 1
-fi
-
-eval set -- $options
-first_uu=yes
-while [ $# -gt 0 ]; do
-  case "$1" in
-    -h|--help) usage; exit;;
-    -V|--virtual-env) always_venv=1; never_venv=0;;
-    -N|--no-virtual-env) always_venv=0; never_venv=1;;
-    -n|--no-site-packages) no_site_packages=1;;
-    -f|--force) force=1;;
-    -u|--update) update=1;;
-    -d|--debug) debug=1;;
-    -p|--pep8) let just_pep8=1;;
-    -c|--coverage) coverage=1;;
-    -t|--serial) serial=1;;
-    --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no  ;;
-    *) testrargs="$testrargs $1";;
-  esac
-  shift
-done
-
-
-cd `dirname "$0"`
-
-if [ $no_site_packages -eq 1 ]; then
-  installvenvopts="--no-site-packages"
-fi
-
-function testr_init {
-  if [ ! -d .testrepository ]; then
-      ${wrapper} testr init
-  fi
-}
-
-function run_tests {
-  testr_init
-  ${wrapper} find . -type f -name "*.pyc" -delete
-  export OS_TEST_PATH=./tempest/tests
-  if [ $debug -eq 1 ]; then
-      if [ "$testrargs" = "" ]; then
-          testrargs="discover ./tempest/tests"
-      fi
-      ${wrapper} python -m testtools.run $testrargs
-      return $?
-  fi
-
-  if [ $coverage -eq 1 ]; then
-      ${wrapper} python setup.py test --coverage
-      return $?
-  fi
-
-  if [ $serial -eq 1 ]; then
-      ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-trace -n -f
-  else
-      ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-trace -n -f
-  fi
-}
-
-function run_pep8 {
-  echo "Running flake8 ..."
-  if [ $never_venv -eq 1 ]; then
-      echo "**WARNING**:" >&2
-      echo "Running flake8 without virtual env may miss OpenStack HACKING detection" >&2
-  fi
-  ${wrapper} flake8
-}
-
-if [ $never_venv -eq 0 ]
-then
-  # Remove the virtual environment if --force used
-  if [ $force -eq 1 ]; then
-    echo "Cleaning virtualenv..."
-    rm -rf ${venv}
-  fi
-  if [ $update -eq 1 ]; then
-      echo "Updating virtualenv..."
-      virtualenv $installvenvopts $venv
-      $venv/bin/pip install -U -r requirements.txt -r test-requirements.txt
-  fi
-  if [ -e ${venv} ]; then
-    wrapper="${with_venv}"
-  else
-    if [ $always_venv -eq 1 ]; then
-      # Automatically install the virtualenv
-      virtualenv $installvenvopts $venv
-      wrapper="${with_venv}"
-      ${wrapper} pip install -U -r requirements.txt -r test-requirements.txt
-    else
-      echo -e "No virtual environment found...create one? (Y/n) \c"
-      read use_ve
-      if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
-        # Install the virtualenv and run the test suite in it
-        virtualenv $installvenvopts $venv
-        wrapper=${with_venv}
-        ${wrapper} pip install -U -r requirements.txt -r test-requirements.txt
-      fi
-    fi
-  fi
-fi
-
-if [ $just_pep8 -eq 1 ]; then
-    run_pep8
-    exit
-fi
-
-run_tests
-retval=$?
-
-if [ -z "$testrargs" ]; then
-    run_pep8
-fi
-
-exit $retval
diff --git a/setup.py b/setup.py
index 782bb21..566d844 100644
--- a/setup.py
+++ b/setup.py
@@ -25,5 +25,5 @@
     pass
 
 setuptools.setup(
-    setup_requires=['pbr>=1.8'],
+    setup_requires=['pbr>=2.0.0'],
     pbr=True)
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..e682570 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -15,7 +15,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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
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.py b/tempest/api/compute/admin/test_flavors_access.py
index 04b0c2d..5a38acc 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import decorators
 from tempest import test
 
@@ -38,7 +37,6 @@
 
         # Non admin tenant ID
         cls.tenant_id = cls.flavors_client.tenant_id
-        cls.flavor_name_prefix = 'test_flavor_access_'
         cls.ram = 512
         cls.vcpus = 1
         cls.disk = 10
@@ -47,51 +45,37 @@
     def test_flavor_access_list_with_private_flavor(self):
         # Test to make sure that list flavor access on a newly created
         # private flavor will return an empty access list
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
+
         flavor_access = (self.admin_flavors_client.list_flavor_access(
-            new_flavor_id)['flavor_access'])
+                         flavor['id'])['flavor_access'])
         self.assertEqual(len(flavor_access), 0, str(flavor_access))
 
     @decorators.idempotent_id('59e622f6-bdf6-45e3-8ba8-fedad905a6b4')
     def test_flavor_access_add_remove(self):
         # Test to add and remove flavor access to a given tenant.
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
+
         # Add flavor access to a tenant.
         resp_body = {
             "tenant_id": str(self.tenant_id),
-            "flavor_id": str(new_flavor['id']),
+            "flavor_id": str(flavor['id']),
         }
         add_body = (self.admin_flavors_client.add_flavor_access(
-            new_flavor['id'], self.tenant_id)['flavor_access'])
+            flavor['id'], self.tenant_id)['flavor_access'])
         self.assertIn(resp_body, add_body)
 
         # The flavor is present in list.
         flavors = self.flavors_client.list_flavors(detail=True)['flavors']
-        self.assertIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+        self.assertIn(flavor['id'], map(lambda x: x['id'], flavors))
 
         # Remove flavor access from a tenant.
         remove_body = (self.admin_flavors_client.remove_flavor_access(
-            new_flavor['id'], self.tenant_id)['flavor_access'])
+            flavor['id'], self.tenant_id)['flavor_access'])
         self.assertNotIn(resp_body, remove_body)
 
         # The flavor is not present in list.
         flavors = self.flavors_client.list_flavors(detail=True)['flavors']
-        self.assertNotIn(new_flavor['id'], map(lambda x: x['id'], flavors))
+        self.assertNotIn(flavor['id'], map(lambda x: x['id'], flavors))
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 9fe1f74..12e4587 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -40,7 +39,6 @@
         super(FlavorsAccessNegativeTestJSON, cls).resource_setup()
 
         cls.tenant_id = cls.flavors_client.tenant_id
-        cls.flavor_name_prefix = 'test_flavor_access_'
         cls.ram = 512
         cls.vcpus = 1
         cls.disk = 10
@@ -49,108 +47,69 @@
     @decorators.idempotent_id('0621c53e-d45d-40e7-951d-43e5e257b272')
     def test_flavor_access_list_with_public_flavor(self):
         # Test to list flavor access with exceptions by querying public flavor
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='True')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='True')
         self.assertRaises(lib_exc.NotFound,
                           self.admin_flavors_client.list_flavor_access,
-                          new_flavor_id)
+                          flavor['id'])
 
     @test.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.
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
         self.assertRaises(lib_exc.Forbidden,
                           self.flavors_client.add_flavor_access,
-                          new_flavor['id'],
+                          flavor['id'],
                           self.tenant_id)
 
     @test.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.
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
+
         # Add flavor access to a tenant.
-        self.admin_flavors_client.add_flavor_access(new_flavor['id'],
+        self.admin_flavors_client.add_flavor_access(flavor['id'],
                                                     self.tenant_id)
         self.addCleanup(self.admin_flavors_client.remove_flavor_access,
-                        new_flavor['id'], self.tenant_id)
+                        flavor['id'], self.tenant_id)
         self.assertRaises(lib_exc.Forbidden,
                           self.flavors_client.remove_flavor_access,
-                          new_flavor['id'],
+                          flavor['id'],
                           self.tenant_id)
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
     def test_add_flavor_access_duplicate(self):
         # Create a new flavor.
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
 
         # Add flavor access to a tenant.
-        self.admin_flavors_client.add_flavor_access(new_flavor['id'],
+        self.admin_flavors_client.add_flavor_access(flavor['id'],
                                                     self.tenant_id)
         self.addCleanup(self.admin_flavors_client.remove_flavor_access,
-                        new_flavor['id'], self.tenant_id)
+                        flavor['id'], self.tenant_id)
 
         # An exception should be raised when adding flavor access to the same
         # tenant
         self.assertRaises(lib_exc.Conflict,
                           self.admin_flavors_client.add_flavor_access,
-                          new_flavor['id'],
+                          flavor['id'],
                           self.tenant_id)
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
     def test_remove_flavor_access_not_found(self):
         # Create a new flavor.
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = data_utils.rand_int_id(start=1000)
-        new_flavor = self.admin_flavors_client.create_flavor(
-            name=flavor_name,
-            ram=self.ram, vcpus=self.vcpus,
-            disk=self.disk,
-            id=new_flavor_id,
-            is_public='False')['flavor']
-        self.addCleanup(self.admin_flavors_client.delete_flavor,
-                        new_flavor['id'])
+        flavor = self.create_flavor(ram=self.ram, vcpus=self.vcpus,
+                                    disk=self.disk, is_public='False')
 
         # An exception should be raised when flavor access is not found
         self.assertRaises(lib_exc.NotFound,
                           self.admin_flavors_client.remove_flavor_access,
-                          new_flavor['id'],
+                          flavor['id'],
                           self.os_alt.servers_client.tenant_id)
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..a728711 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
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index 1a37312..b8a67b9 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.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.lib import exceptions as lib_exc
 from tempest import test
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_migrations.py b/tempest/api/compute/admin/test_migrations.py
index aa75348..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
 
@@ -30,7 +30,6 @@
     def setup_clients(cls):
         super(MigrationsAdminTest, cls).setup_clients()
         cls.client = cls.os_adm.migrations_client
-        cls.flavors_admin_client = cls.os_adm.flavors_client
 
     @decorators.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
     def test_list_migrations(self):
@@ -54,8 +53,8 @@
 
     def _flavor_clean_up(self, flavor_id):
         try:
-            self.flavors_admin_client.delete_flavor(flavor_id)
-            self.flavors_admin_client.wait_for_resource_deletion(flavor_id)
+            self.admin_flavors_client.delete_flavor(flavor_id)
+            self.admin_flavors_client.wait_for_resource_deletion(flavor_id)
         except exceptions.NotFound:
             pass
 
@@ -68,9 +67,9 @@
 
         # First we have to create a flavor that we can delete so make a copy
         # of the normal flavor from which we'd create a server.
-        flavor = self.flavors_admin_client.show_flavor(
+        flavor = self.admin_flavors_client.show_flavor(
             self.flavor_ref)['flavor']
-        flavor = self.flavors_admin_client.create_flavor(
+        flavor = self.admin_flavors_client.create_flavor(
             name=data_utils.rand_name('test_resize_flavor_'),
             ram=flavor['ram'],
             disk=flavor['disk'],
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..a1dd2e7 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
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..79777d0 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -15,8 +15,8 @@
 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
 
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 5220c97..ebdceef 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -16,9 +16,9 @@
 
 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
@@ -34,7 +34,6 @@
         super(ServersAdminNegativeTestJSON, cls).setup_clients()
         cls.client = cls.os_adm.servers_client
         cls.non_adm_client = cls.servers_client
-        cls.flavors_client = cls.os_adm.flavors_client
         cls.quotas_client = cls.os_adm.quotas_client
 
     @classmethod
@@ -45,16 +44,6 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.s1_id = server['id']
 
-    def _get_unused_flavor_id(self):
-        flavor_id = data_utils.rand_int_id(start=1000)
-        while True:
-            try:
-                self.flavors_client.show_flavor(flavor_id)
-            except lib_exc.NotFound:
-                break
-            flavor_id = data_utils.rand_int_id(start=1000)
-        return flavor_id
-
     @decorators.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
@@ -62,8 +51,6 @@
     def test_resize_server_using_overlimit_ram(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
-        flavor_name = data_utils.rand_name("flavor")
-        flavor_id = self._get_unused_flavor_id()
         quota_set = self.quotas_client.show_quota_set(
             self.tenant_id)['quota_set']
         ram = quota_set['ram']
@@ -73,11 +60,7 @@
         ram += 1
         vcpus = 1
         disk = 5
-        flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
-                                                       ram=ram, vcpus=vcpus,
-                                                       disk=disk,
-                                                       id=flavor_id)['flavor']
-        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+        flavor_ref = self.create_flavor(ram=ram, vcpus=vcpus, disk=disk)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.client.resize_server,
                           self.servers[0]['id'],
@@ -90,8 +73,6 @@
     def test_resize_server_using_overlimit_vcpus(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
-        flavor_name = data_utils.rand_name("flavor")
-        flavor_id = self._get_unused_flavor_id()
         quota_set = self.quotas_client.show_quota_set(
             self.tenant_id)['quota_set']
         vcpus = quota_set['cores']
@@ -101,11 +82,7 @@
         vcpus += 1
         ram = 512
         disk = 5
-        flavor_ref = self.flavors_client.create_flavor(name=flavor_name,
-                                                       ram=ram, vcpus=vcpus,
-                                                       disk=disk,
-                                                       id=flavor_id)['flavor']
-        self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
+        flavor_ref = self.create_flavor(ram=ram, vcpus=vcpus, disk=disk)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.client.resize_server,
                           self.servers[0]['id'],
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 45472df..984f1a9 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -30,6 +30,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
@@ -58,13 +61,21 @@
                                                 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'])
         # 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')
+        # 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..06b0893 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_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
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 706b859..ef13eef 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
@@ -295,20 +295,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 +328,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
@@ -445,8 +447,8 @@
         attach_kwargs = dict(volumeId=volume['id'])
         if device:
             attach_kwargs['device'] = device
-        self.servers_client.attach_volume(
-            server['id'], **attach_kwargs)
+        attachment = self.servers_client.attach_volume(
+            server['id'], **attach_kwargs)['volumeAttachment']
         # On teardown detach the volume and wait for it to be available. This
         # is so we don't error out when trying to delete the volume during
         # teardown.
@@ -459,6 +461,7 @@
                         server['id'], volume['id'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'in-use')
+        return attachment
 
 
 class BaseV2ComputeAdminTest(BaseV2ComputeTest):
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index a70c0a9..eee6bd2 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -19,8 +19,9 @@
 
 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
 
@@ -43,7 +44,7 @@
 
     @test.attr(type=['negative'])
     @test.services('image')
-    @test.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
+    @decorators.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
     def test_boot_with_low_ram(self):
         """Try boot a vm with lower than min ram
 
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..b3c3e17 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
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..388db0b 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
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..9cb4b57 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.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.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index a0c860a..ceac56b 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -13,9 +13,9 @@
 #    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
 
 CONF = config.CONF
@@ -64,3 +64,35 @@
                                               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')
+    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')
+    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..86013d4 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -13,9 +13,9 @@
 #    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
@@ -54,7 +54,7 @@
         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.idempotent_id('82c5b0c4-9dbd-463c-872b-20c4755aae7f')
@@ -63,7 +63,7 @@
         # 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.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
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..68563bd 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.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 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
@@ -33,9 +33,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,25 +77,21 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-        cls.image_ids = []
-
     @test.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.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.idempotent_id('0460efcf-ee88-4f94-acef-1bf658695456')
@@ -106,16 +99,16 @@
         # 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)
+
+        image_id = data_utils.parse_image_id(image.response['location'])
+        self.client.delete_image(image_id)
+        self.images.remove(image_id)
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
@@ -131,14 +124,13 @@
     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..403961f 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_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
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..8b5a35b 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -15,7 +15,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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
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/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_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 0312736..6b8dfdf 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
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 349bfda..ed0e722 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
@@ -145,7 +145,7 @@
         self.assertEqual(s_new_name, fetched_group['name'])
         self.assertEqual(s_new_des, fetched_group['description'])
 
-    @test.idempotent_id('79517d60-535a-438f-af3d-e6feab1cbea7')
+    @decorators.idempotent_id('79517d60-535a-438f-af3d-e6feab1cbea7')
     @test.services('network')
     def test_list_security_groups_by_server(self):
         # Create a couple security groups that we will use
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..3593237 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
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index a94c20b..eb23e4b 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
 
@@ -122,7 +122,8 @@
             self.validation_resources['keypair']['private_key'],
             server=self.server,
             servers_client=self.client)
-        self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
+        output = linux_client.exec_command('grep -c ^processor /proc/cpuinfo')
+        self.assertEqual(flavor['vcpus'], int(output))
 
     @decorators.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
     @testtools.skipUnless(CONF.validation.run_validation,
@@ -136,7 +137,7 @@
             self.validation_resources['keypair']['private_key'],
             server=self.server,
             servers_client=self.client)
-        hostname = linux_client.get_hostname()
+        hostname = linux_client.exec_command("hostname").rstrip()
         msg = ('Failed while verifying servername equals hostname. Expected '
                'hostname "%s" but got "%s".' % (self.name, hostname))
         self.assertEqual(self.name.lower(), hostname, msg)
@@ -236,7 +237,6 @@
     @classmethod
     def setup_clients(cls):
         super(ServersWithSpecificFlavorTestJSON, cls).setup_clients()
-        cls.flavor_client = cls.os_adm.flavors_client
         cls.client = cls.servers_client
 
     @classmethod
@@ -254,7 +254,6 @@
             self.flavor_ref)['flavor']
 
         def create_flavor_with_ephemeral(ephem_disk):
-            flavor_id = data_utils.rand_int_id(start=1000)
             name = 'flavor_with_ephemeral_%s' % ephem_disk
             flavor_name = data_utils.rand_name(name)
 
@@ -263,17 +262,10 @@
             disk = flavor_base['disk']
 
             # Create a flavor with ephemeral disk
-            flavor = self.flavor_client.create_flavor(
-                name=flavor_name, ram=ram, vcpus=vcpus, disk=disk,
-                id=flavor_id, ephemeral=ephem_disk)['flavor']
-            self.addCleanup(flavor_clean_up, flavor['id'])
-
+            flavor = self.create_flavor(name=flavor_name, ram=ram, vcpus=vcpus,
+                                        disk=disk, ephemeral=ephem_disk)
             return flavor['id']
 
-        def flavor_clean_up(flavor_id):
-            self.flavor_client.delete_flavor(flavor_id)
-            self.flavor_client.wait_for_resource_deletion(flavor_id)
-
         flavor_with_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=1)
         flavor_no_eph_disk_id = create_flavor_with_ephemeral(ephem_disk=0)
 
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..512bd1e 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.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.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index c0a8eae..12eb5e1 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -12,13 +12,17 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import testtools
 
 from tempest.api.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
-from tempest.lib import exceptions as lib_exc
+
+
+CONF = config.CONF
 
 
 class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
@@ -37,31 +41,6 @@
     def resource_setup(cls):
         super(ListServerFiltersTestJSON, cls).resource_setup()
 
-        # Check to see if the alternate image ref actually exists...
-        images_client = cls.compute_images_client
-        images = images_client.list_images()['images']
-
-        if cls.image_ref != cls.image_ref_alt and \
-            any([image for image in images
-                 if image['id'] == cls.image_ref_alt]):
-            cls.multiple_images = True
-        else:
-            cls.image_ref_alt = cls.image_ref
-
-        # Do some sanity checks here. If one of the images does
-        # not exist, fail early since the tests won't work...
-        try:
-            cls.compute_images_client.show_image(cls.image_ref)
-        except lib_exc.NotFound:
-            raise RuntimeError("Image %s (image_ref) was not found!" %
-                               cls.image_ref)
-
-        try:
-            cls.compute_images_client.show_image(cls.image_ref_alt)
-        except lib_exc.NotFound:
-            raise RuntimeError("Image %s (image_ref_alt) was not found!" %
-                               cls.image_ref_alt)
-
         network = cls.get_tenant_network()
         if network:
             cls.fixed_network_name = network.get('name')
@@ -74,9 +53,12 @@
                                         **network_kwargs)
 
         cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
-        cls.s2 = cls.create_test_server(name=cls.s2_name,
-                                        image_id=cls.image_ref_alt,
-                                        wait_until='ACTIVE')
+        # 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')
 
         cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
         cls.s3 = cls.create_test_server(name=cls.s3_name,
@@ -84,7 +66,8 @@
                                         wait_until='ACTIVE')
 
     @decorators.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
-    @decorators.skip_unless_attr('multiple_images', 'Only one image found')
+    @testtools.skipUnless(CONF.compute.image_ref != CONF.compute.image_ref_alt,
+                          "Need distinct images to run this test")
     def test_list_servers_filter_by_image(self):
         # Filter the list of servers by image
         params = {'image': self.image_ref}
@@ -169,7 +152,8 @@
                          len([x for x in servers['servers'] if 'id' in x]))
 
     @decorators.idempotent_id('b3304c3b-97df-46d2-8cd3-e2b6659724e7')
-    @decorators.skip_unless_attr('multiple_images', 'Only one image found')
+    @testtools.skipUnless(CONF.compute.image_ref != CONF.compute.image_ref_alt,
+                          "Need distinct images to run this test")
     def test_list_servers_detailed_filter_by_image(self):
         # Filter the detailed list of servers by image
         params = {'image': self.image_ref}
@@ -269,16 +253,34 @@
         if not self.fixed_network_name:
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
+
+        # list servers filter by ip is something "regexp match", i.e,
+        # filter by "10.1.1.1" will return both "10.1.1.1" and "10.1.1.10".
+        # so here look for the longest server ip, and filter by that ip,
+        # so as to ensure only one server is returned.
+        ip_list = {}
         self.s1 = self.client.show_server(self.s1['id'])['server']
         # Get first ip address inspite of v4 or v6
-        addr_spec = self.s1['addresses'][self.fixed_network_name][0]
-        params = {'ip': addr_spec['addr']}
+        ip_addr = self.s1['addresses'][self.fixed_network_name][0]['addr']
+        ip_list[ip_addr] = self.s1['id']
+
+        self.s2 = self.client.show_server(self.s2['id'])['server']
+        ip_addr = self.s2['addresses'][self.fixed_network_name][0]['addr']
+        ip_list[ip_addr] = self.s2['id']
+
+        self.s3 = self.client.show_server(self.s3['id'])['server']
+        ip_addr = self.s3['addresses'][self.fixed_network_name][0]['addr']
+        ip_list[ip_addr] = self.s3['id']
+
+        longest_ip = max([[len(ip), ip] for ip in ip_list])[1]
+        params = {'ip': longest_ip}
         body = self.client.list_servers(**params)
         servers = body['servers']
 
-        self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
-        self.assertNotIn(self.s2_name, map(lambda x: x['name'], servers))
-        self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
+        self.assertIn(ip_list[longest_ip], map(lambda x: x['id'], servers))
+        del ip_list[longest_ip]
+        for ip in ip_list:
+            self.assertNotIn(ip_list[ip], map(lambda x: x['id'], servers))
 
     @decorators.skip_because(bug="1540645")
     @decorators.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 7e55b12..87265ec 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,16 @@
 
     @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)
+        body, servers = compute.create_test_server(self.os,
+                                                   wait_until='ACTIVE',
+                                                   min_count=2)
+        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_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 6160024..d810ff7 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
@@ -471,7 +471,7 @@
 
         # NOTE: SHUTOFF is irregular status. To avoid test instability,
         #       one server is created only for this test without using
-        #       the server that was created in setupClass.
+        #       the server that was created in setUpClass.
         server = self.create_test_server(wait_until='ACTIVE')
         temp_server_id = server['id']
 
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index dfda51b..cf4ed85 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -49,7 +49,7 @@
         # We do not know the exact network configuration, but an instance
         # should at least have a single public or private address
         self.assertGreaterEqual(len(addresses), 1)
-        for network_name, network_addresses in addresses.items():
+        for network_addresses in addresses.values():
             self.assertGreaterEqual(len(network_addresses), 1)
             for address in network_addresses:
                 self.assertTrue(address['addr'])
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..22ce37d 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.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.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 209ab38..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
@@ -58,10 +58,8 @@
         cls.password = data_utils.rand_password()
         # Server for positive tests
         server = cls.create_test_server(adminPass=cls.password,
-                                        wait_until='BUILD')
+                                        wait_until='ACTIVE')
         cls.server_id = server['id']
-        waiters.wait_for_server_status(cls.servers_client, cls.server_id,
-                                       'ACTIVE')
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index c3a8c36..565d76d 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
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
new file mode 100644
index 0000000..0370215
--- /dev/null
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -0,0 +1,108 @@
+# Copyright 2017 AT&T 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 six
+
+from tempest.api.compute import base
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest import test
+
+
+class ServerTagsTestJSON(base.BaseV2ComputeTest):
+
+    min_microversion = '2.26'
+    max_microversion = 'latest'
+
+    @classmethod
+    def skip_checks(cls):
+        super(ServerTagsTestJSON, cls).skip_checks()
+        if not test.is_extension_enabled('os-server-tags', 'compute'):
+            msg = "os-server-tags extension is not enabled."
+            raise cls.skipException(msg)
+
+    @classmethod
+    def setup_clients(cls):
+        super(ServerTagsTestJSON, cls).setup_clients()
+        cls.client = cls.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        super(ServerTagsTestJSON, cls).resource_setup()
+        cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+    def _update_server_tags(self, server_id, tags):
+        if not isinstance(tags, (list, tuple)):
+            tags = [tags]
+        for tag in tags:
+            self.client.update_tag(server_id, tag)
+        self.addCleanup(self.client.delete_all_tags, server_id)
+
+    @decorators.idempotent_id('8d95abe2-c658-4c42-9a44-c0258500306b')
+    def test_create_delete_tag(self):
+        # Check that no tags exist.
+        fetched_tags = self.client.list_tags(self.server['id'])['tags']
+        self.assertEmpty(fetched_tags)
+
+        # Add server tag to the server.
+        assigned_tag = data_utils.rand_name('tag')
+        self._update_server_tags(self.server['id'], assigned_tag)
+
+        # Check that added tag exists.
+        fetched_tags = self.client.list_tags(self.server['id'])['tags']
+        self.assertEqual([assigned_tag], fetched_tags)
+
+        # Remove assigned tag from server and check that it was removed.
+        self.client.delete_tag(self.server['id'], assigned_tag)
+        fetched_tags = self.client.list_tags(self.server['id'])['tags']
+        self.assertEmpty(fetched_tags)
+
+    @decorators.idempotent_id('a2c1af8c-127d-417d-974b-8115f7e3d831')
+    def test_update_all_tags(self):
+        # Add server tags to the server.
+        tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
+        self._update_server_tags(self.server['id'], tags)
+
+        # Replace tags with new tags and check that they are present.
+        new_tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
+        replaced_tags = self.client.update_all_tags(
+            self.server['id'], new_tags)['tags']
+        six.assertCountEqual(self, new_tags, replaced_tags)
+
+        # List the tags and check that the tags were replaced.
+        fetched_tags = self.client.list_tags(self.server['id'])['tags']
+        six.assertCountEqual(self, new_tags, fetched_tags)
+
+    @decorators.idempotent_id('a63b2a74-e918-4b7c-bcab-10c855f3a57e')
+    def test_delete_all_tags(self):
+        # Add server tags to the server.
+        assigned_tags = [data_utils.rand_name('tag'),
+                         data_utils.rand_name('tag')]
+        self._update_server_tags(self.server['id'], assigned_tags)
+
+        # Delete tags from the server and check that they were deleted.
+        self.client.delete_all_tags(self.server['id'])
+        fetched_tags = self.client.list_tags(self.server['id'])['tags']
+        self.assertEmpty(fetched_tags)
+
+    @decorators.idempotent_id('81279a66-61c3-4759-b830-a2dbe64cbe08')
+    def test_check_tag_existence(self):
+        # Add server tag to the server.
+        assigned_tag = data_utils.rand_name('tag')
+        self._update_server_tags(self.server['id'], assigned_tag)
+
+        # Check that added tag exists. Throws a 404 if not found, else a 204,
+        # which was already checked by the schema validation.
+        self.client.check_tag_existence(self.server['id'], assigned_tag)
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 b22a434..c6b3b40 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
@@ -176,7 +176,7 @@
 
         self.assertRaises(lib_exc.NotFound,
                           self.client.rebuild_server,
-                          server['id'], self.image_ref_alt)
+                          server['id'], self.image_ref)
 
     @test.related_bug('1660878', status_code=409)
     @test.attr(type=['negative'])
@@ -198,7 +198,7 @@
         self.assertRaises(lib_exc.NotFound,
                           self.client.rebuild_server,
                           nonexistent_server,
-                          self.image_ref_alt)
+                          self.image_ref)
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index 01fd9ef..0f5ea57 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -14,9 +14,9 @@
 #    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
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 c9f0724..dcab067 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -14,11 +14,13 @@
 
 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')
     def test_list_api_versions(self):
         """Test that a get of the unversioned url returns the choices doc.
 
@@ -37,6 +39,7 @@
                          "The first listed version should be v2.0")
 
     @decorators.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
+    @test.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 5304944..73c7614 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -22,7 +22,6 @@
 from tempest.common import waiters
 from tempest import config
 from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
 
 CONF = config.CONF
 
@@ -61,38 +60,14 @@
             server['id'])['addresses']
         return server
 
-    def _detach_volume(self, server_id, volume_id):
-        try:
-            self.servers_client.detach_volume(server_id, volume_id)
-            waiters.wait_for_volume_resource_status(self.volumes_client,
-                                                    volume_id, 'available')
-        except lib_exc.NotFound:
-            LOG.warning("Unable to detach volume %s from server %s "
-                        "possibly it was already detached", volume_id,
-                        server_id)
-
-    def _attach_volume(self, server_id, volume_id, device=None):
-        # Attach the volume to the server
-        kwargs = {'volumeId': volume_id}
-        if device:
-            kwargs.update({'device': '/dev/%s' % device})
-        attachment = self.servers_client.attach_volume(
-            server_id, **kwargs)['volumeAttachment']
-        waiters.wait_for_volume_resource_status(self.volumes_client,
-                                                volume_id, 'in-use')
-        self.addCleanup(self._detach_volume, server_id,
-                        volume_id)
-
-        return attachment
-
     @decorators.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
     def test_attach_detach_volume(self):
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
         server = self._create_server()
         volume = self.create_volume()
-        attachment = self._attach_volume(server['id'], volume['id'],
-                                         device=self.device)
+        attachment = self.attach_volume(server, volume,
+                                        device=('/dev/%s' % self.device))
 
         self.servers_client.stop_server(server['id'])
         waiters.wait_for_server_status(self.servers_client, server['id'],
@@ -115,7 +90,10 @@
             device_name_to_match = '\n' + self.device + ' '
             self.assertIn(device_name_to_match, disks)
 
-        self._detach_volume(server['id'], attachment['volumeId'])
+        self.servers_client.detach_volume(server['id'], attachment['volumeId'])
+        waiters.wait_for_volume_resource_status(
+            self.volumes_client, attachment['volumeId'], 'available')
+
         self.servers_client.stop_server(server['id'])
         waiters.wait_for_server_status(self.servers_client, server['id'],
                                        'SHUTOFF')
@@ -141,8 +119,8 @@
         # List volume attachment of the server
         server = self._create_server()
         volume = self.create_volume()
-        attachment = self._attach_volume(server['id'], volume['id'],
-                                         device=self.device)
+        attachment = self.attach_volume(server, volume,
+                                        device=('/dev/%s' % self.device))
         body = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
         self.assertEqual(1, len(body))
@@ -165,8 +143,8 @@
         server = self._create_server()
         volume_1st = self.create_volume()
         volume_2nd = self.create_volume()
-        attachment_1st = self._attach_volume(server['id'], volume_1st['id'])
-        attachment_2nd = self._attach_volume(server['id'], volume_2nd['id'])
+        attachment_1st = self.attach_volume(server, volume_1st)
+        attachment_2nd = self.attach_volume(server, volume_2nd)
 
         body = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
@@ -253,8 +231,8 @@
         volume = self.create_volume()
         num_vol = self._count_volumes(server)
         self._shelve_server(server)
-        attachment = self._attach_volume(server['id'], volume['id'],
-                                         device=self.device)
+        attachment = self.attach_volume(server, volume,
+                                        device=('/dev/%s' % self.device))
 
         # Unshelve the instance and check that attached volume exists
         self._unshelve_server_and_check_volumes(server, num_vol + 1)
@@ -279,9 +257,12 @@
         volume = self.create_volume()
         num_vol = self._count_volumes(server)
         self._shelve_server(server)
-        self._attach_volume(server['id'], volume['id'], device=self.device)
-        # Detach the volume
-        self._detach_volume(server['id'], volume['id'])
+
+        # Attach and then detach the volume
+        self.attach_volume(server, volume, device=('/dev/%s' % self.device))
+        self.servers_client.detach_volume(server['id'], volume['id'])
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                volume['id'], 'available')
 
         # Unshelve the instance and check that we have the expected number of
         # volume(s)
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..7676ee8 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_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
diff --git a/tempest/api/identity/admin/v2/test_endpoints.py b/tempest/api/identity/admin/v2/test_endpoints.py
index df55d2f..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
 
 
@@ -27,10 +27,10 @@
         s_name = data_utils.rand_name('service')
         s_type = data_utils.rand_name('type')
         s_description = data_utils.rand_name('description')
-        cls.service_data = cls.services_client.create_service(
+        service_data = cls.services_client.create_service(
             name=s_name, type=s_type,
             description=s_description)['OS-KSADM:service']
-        cls.service_id = cls.service_data['id']
+        cls.service_id = service_data['id']
         cls.service_ids.append(cls.service_id)
         # Create endpoints so as to use for LIST and GET test cases
         cls.setup_endpoints = list()
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..f80721c 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index 3b0ddbb..f6d4a24 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index e8c32b9..69f0920 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v2/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
index eb51b5a..6b7413c 100644
--- a/tempest/api/identity/admin/v2/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.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_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index 7b5e01e..3428c07 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
 
 
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index 5889813..df4ded8 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -18,7 +18,7 @@
 from testtools import matchers
 
 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
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index 49fda4e..442c1a7 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index e5a218d..c752532 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -15,7 +15,7 @@
 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
 
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..c2ab488 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
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 4cf9f66..d04e774 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -14,8 +14,8 @@
 #    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
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 4555a6a..280a5a8 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 686743b..0786d82 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/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
 from tempest import test
 
@@ -33,11 +33,10 @@
         s_name = data_utils.rand_name('service')
         s_type = data_utils.rand_name('type')
         s_description = data_utils.rand_name('description')
-        cls.service_data = (
+        service_data = (
             cls.services_client.create_service(name=s_name, type=s_type,
                                                description=s_description))
-        cls.service_data = cls.service_data['service']
-        cls.service_id = cls.service_data['id']
+        cls.service_id = service_data['service']['id']
         cls.service_ids.append(cls.service_id)
         # Create endpoints so as to use for LIST and GET test cases
         cls.setup_endpoints = list()
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 53c2b1f..d46e1f0 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -15,7 +15,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.lib import exceptions as lib_exc
 from tempest import test
@@ -35,11 +35,11 @@
         s_name = data_utils.rand_name('service')
         s_type = data_utils.rand_name('type')
         s_description = data_utils.rand_name('description')
-        cls.service_data = (
+        service_data = (
             cls.services_client.create_service(name=s_name, type=s_type,
                                                description=s_description)
             ['service'])
-        cls.service_id = cls.service_data['id']
+        cls.service_id = service_data['id']
         cls.service_ids.append(cls.service_id)
 
     @classmethod
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 5ce0709..a423a12 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.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
 from tempest import test
 
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
index 8523396..3fe591b 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
 
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_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index eb1c69e..f74cb1c 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.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
 from tempest import test
 
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index b37d33d..77a5c69 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -16,8 +16,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
 
 CONF = config.CONF
diff --git a/tempest/api/identity/admin/v3/test_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index 87f8684..31e7302 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index f57a07c..56ee496 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.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
 from tempest import test
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 445d928..e07d525 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -14,12 +14,15 @@
 #    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
+
 
 class RolesV3TestJSON(base.BaseIdentityV3AdminTest):
 
@@ -306,3 +309,75 @@
         roles_ids = [assignment['role']['id']
                      for assignment in role_assignments]
         self.assertIn(self.roles[0]['id'], roles_ids)
+
+    @decorators.idempotent_id('d92a41d2-5501-497a-84bb-6e294330e8f8')
+    def test_domain_roles_create_delete(self):
+        domain_role = self.roles_client.create_role(
+            name=data_utils.rand_name('domain_role'),
+            domain_id=self.domain['id'])['role']
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.roles_client.delete_role,
+            domain_role['id'])
+
+        domain_roles = self.roles_client.list_roles(
+            domain_id=self.domain['id'])['roles']
+        self.assertEqual(1, len(domain_roles))
+        self.assertIn(domain_role, domain_roles)
+
+        self.roles_client.delete_role(domain_role['id'])
+        domain_roles = self.roles_client.list_roles(
+            domain_id=self.domain['id'])['roles']
+        self.assertEmpty(domain_roles)
+
+    @decorators.idempotent_id('eb1e1c24-1bc4-4d47-9748-e127a1852c82')
+    def test_implied_domain_roles(self):
+        # Create two roles in the same domain
+        domain_role1 = self.setup_test_role(domain_id=self.domain['id'])
+        domain_role2 = self.setup_test_role(domain_id=self.domain['id'])
+
+        # Check if we can create an inference rule from roles in the same
+        # domain
+        self._create_implied_role(domain_role1['id'], domain_role2['id'])
+
+        # Create another role in a different domain
+        domain2 = self.setup_test_domain()
+        domain_role3 = self.setup_test_role(domain_id=domain2['id'])
+
+        # Check if we can create cross domain implied roles
+        self._create_implied_role(domain_role1['id'], domain_role3['id'])
+
+        # Finally, we also should be able to create an implied from a
+        # domain role to a global one
+        self._create_implied_role(domain_role1['id'], self.role['id'])
+
+        if CONF.identity_feature_enabled.forbid_global_implied_dsr:
+            # The contrary is not true: we can't create an inference rule
+            # from a global role to a domain role
+            self.assertRaises(
+                lib_exc.Forbidden,
+                self.roles_client.create_role_inference_rule,
+                self.role['id'],
+                domain_role1['id'])
+
+    @decorators.idempotent_id('3859df7e-5b78-4e4d-b10e-214c8953842a')
+    def test_assignments_for_domain_roles(self):
+        domain_role = self.setup_test_role(domain_id=self.domain['id'])
+
+        # Create a grant using "domain_role"
+        self.roles_client.create_user_role_on_project(
+            self.project['id'], self.user_body['id'], domain_role['id'])
+        self.addCleanup(
+            self.roles_client.delete_role_from_user_on_project,
+            self.project['id'], self.user_body['id'], domain_role['id'])
+
+        # NOTE(rodrigods): Regular roles would appear in the effective
+        # list of role assignments (meaning the role would be returned in
+        # a token) as a result from the grant above. This is not the case
+        # for domain roles, they should not appear in the effective role
+        # assignments list.
+        params = {'scope.project.id': self.project['id'],
+                  'user.id': self.user_body['id']}
+        role_assignments = self.role_assignments.list_role_assignments(
+            effective=True, **params)['role_assignments']
+        self.assertEmpty(role_assignments)
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 35e1814..53e005d 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index a9508d1..fabb91c 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):
 
@@ -150,3 +153,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..7a569b7 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -18,8 +18,8 @@
 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
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index e0ec883..0d12ba9 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
 
 
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 9626108..93241c5 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 3bbe47a..9339d3c 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -13,8 +13,9 @@
 #    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
 
 CONF = config.CONF
@@ -72,15 +73,22 @@
             kwargs['password'] = user_password
         user = self.users_client.create_user(**kwargs)['user']
         # Delete the user at the end of the test
-        self.addCleanup(self.users_client.delete_user, user['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.users_client.delete_user, user['id'])
         return user
 
-    def setup_test_role(self):
+    def setup_test_role(self, domain_id=None):
         """Set up a test role."""
-        role = self.roles_client.create_role(
-            name=data_utils.rand_name('test_role'))['role']
+        params = {'name': data_utils.rand_name('test_role')}
+        if domain_id:
+            params['domain_id'] = domain_id
+
+        role = self.roles_client.create_role(**params)['role']
         # Delete the role at the end of the test
-        self.addCleanup(self.roles_client.delete_role, role['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.roles_client.delete_role, role['id'])
         return role
 
 
@@ -149,7 +157,9 @@
             name=data_utils.rand_name('test_tenant'),
             description=data_utils.rand_name('desc'))['tenant']
         # Delete the tenant at the end of the test
-        self.addCleanup(self.tenants_client.delete_tenant, tenant['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.tenants_client.delete_tenant, tenant['id'])
         return tenant
 
 
@@ -168,6 +178,7 @@
         cls.non_admin_users_client = cls.os.users_v3_client
         cls.non_admin_token = cls.os.token_v3_client
         cls.non_admin_projects_client = cls.os.projects_client
+        cls.non_admin_versions_client = cls.os.identity_versions_v3_client
 
 
 class BaseIdentityV3AdminTest(BaseIdentityV3Test):
@@ -243,12 +254,16 @@
             name=data_utils.rand_name('test_project'),
             description=data_utils.rand_name('desc'))['project']
         # Delete the project at the end of the test
-        self.addCleanup(self.projects_client.delete_project, project['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.projects_client.delete_project, project['id'])
         return project
 
     def setup_test_domain(self):
         """Set up a test domain."""
         domain = self.create_domain()
         # Delete the domain at the end of the test
-        self.addCleanup(self.delete_domain, domain['id'])
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            self.delete_domain, domain['id'])
         return domain
diff --git a/tempest/api/identity/test_extension.py b/tempest/api/identity/v2/test_extension.py
similarity index 95%
rename from tempest/api/identity/test_extension.py
rename to tempest/api/identity/v2/test_extension.py
index 7095181..c538c14 100644
--- a/tempest/api/identity/test_extension.py
+++ b/tempest/api/identity/v2/test_extension.py
@@ -17,7 +17,7 @@
 from tempest.lib import decorators
 
 
-class ExtensionTestJSON(base.BaseIdentityV2AdminTest):
+class ExtensionTestJSON(base.BaseIdentityV2Test):
 
     @decorators.idempotent_id('85f3f661-f54c-4d48-b563-72ae952b9383')
     def test_list_extensions(self):
diff --git a/tempest/api/identity/v3/test_api_discovery.py b/tempest/api/identity/v3/test_api_discovery.py
index 2eed3c8..177a49d 100644
--- a/tempest/api/identity/v3/test_api_discovery.py
+++ b/tempest/api/identity/v3/test_api_discovery.py
@@ -21,6 +21,20 @@
 class TestApiDiscovery(base.BaseIdentityV3Test):
     """Tests for API discovery features."""
 
+    @decorators.idempotent_id('721f480f-35b6-46c7-846e-047e6acea0dc')
+    @test.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
+        # this test path is just v3 API is CURRENT on Keystone side.
+        versions = self.non_admin_versions_client.list_versions()
+        expected_resources = ('id', 'links', 'media-types', 'status',
+                              'updated')
+
+        for version in versions['versions']["values"]:
+            for res in expected_resources:
+                self.assertIn(res, version)
+
     @test.attr(type='smoke')
     @decorators.idempotent_id('b9232f5e-d9e5-4d97-b96c-28d3db4de1bd')
     def test_api_version_resources(self):
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..f075cab 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
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..42ff02f 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -15,7 +15,7 @@
 
 
 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
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 2812c68..30f9ae2 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -20,8 +20,8 @@
 
 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
 
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_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..7032dd4 100644
--- a/tempest/api/image/v2/test_images_tags_negative.py
+++ b/tempest/api/image/v2/test_images_tags_negative.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/image/v2/test_versions.py b/tempest/api/image/v2/test_versions.py
new file mode 100644
index 0000000..24f104c
--- /dev/null
+++ b/tempest/api/image/v2/test_versions.py
@@ -0,0 +1,30 @@
+# 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
+from tempest import test
+
+
+class VersionsTest(base.BaseV2ImageTest):
+
+    @decorators.idempotent_id('659ea30a-a17c-4317-832c-0f68ed23c31d')
+    @test.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_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..a724dc9 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
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..a7ae765 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -18,9 +18,9 @@
 import netaddr
 
 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
 
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_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..fc9f465 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
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 3cc6fb7..5cb12fe 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -15,7 +15,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.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 3908aae..376d4ae 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
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 694b86b..742fe59 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
 
@@ -239,6 +239,36 @@
              '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.')
+    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.')
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 2bda431..8d680e9 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
@@ -82,6 +83,31 @@
                           subnet02['id'])
 
     @test.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)
+
+    @test.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'],
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 607baf0..d7e5149 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
 
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index f46b873..218a79a 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -176,6 +176,16 @@
                           name=name)
 
     @test.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")
+
+    @test.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.
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index d9599c4..be6bffc 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
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 642c1ac..e0216fd 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
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index cbf0d4b..84e4508 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
 
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index cf7dbe8..de64dfe 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -20,8 +20,8 @@
 
 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
 
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..c0f7b3a 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.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.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index d3b456a..7ff337e 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
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 2e617f3..a82d2cc 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.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 import test
 
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index ebbb84e..be066ba 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.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
 from tempest.lib import exceptions
 from tempest import test
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..1c45a98 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -18,10 +18,9 @@
 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
 
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 2829ac7..c100629 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
 
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index 52b3978..c4e6a3a 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
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 58fd822..d463827 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -21,8 +21,8 @@
 
 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
 
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..912deab 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
 
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..9c1393f 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
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..4e17c3d 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
 
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 3a52108..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
@@ -84,12 +84,15 @@
                 # to heat.
                 body = cls.client.show_resource(cls.stack_identifier,
                                                 'Server')
-                server_id = body['physical_resource_id']
-                LOG.debug('Console output for %s', server_id)
-                output = cls.servers_client.get_console_output(
-                    server_id)['output']
-                LOG.debug(output)
-            raise
+                server_id = body.get('physical_resource_id')
+                if server_id:
+                    LOG.debug('Console output for %s', server_id)
+                    output = cls.servers_client.get_console_output(
+                        server_id)['output']
+                    LOG.debug(output)
+                else:
+                    LOG.debug('Server resource is %s', body)
+            raise  # original exception
 
         cls.test_resources = {}
         for resource in resources:
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_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index 89b10cc..dae0bab 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.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
 from tempest.lib import exceptions as lib_exc
 from tempest import test
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 7b5f161..0be135b 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.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
 from tempest import test
 
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_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index d34eb89..86323e1 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
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index c3e904a..4a46adc 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -12,9 +12,9 @@
 
 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
diff --git a/tempest/api/volume/admin/test_qos.py b/tempest/api/volume/admin/test_qos.py
index e1cfb30..7a91985 100644
--- a/tempest/api/volume/admin/test_qos.py
+++ b/tempest/api/volume/admin/test_qos.py
@@ -13,8 +13,8 @@
 #    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
 
 
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 83fca45..3fd9b01 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -13,8 +13,8 @@
 #    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']
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 97a352b..5dfdfce 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -21,9 +21,7 @@
 
 
 def _get_host(host):
-    if CONF.volume_feature_enabled.volume_services:
-        host = host.split('@')[0]
-    return host
+    return host.split('@')[0]
 
 
 class VolumesServicesV2TestJSON(base.BaseVolumeAdminTest):
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 5d08416..6e56be9 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.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 import decorators
 
 CONF = config.CONF
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..d491f23 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,7 +14,7 @@
 #    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
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 13b7384..b771d8a 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -17,9 +17,9 @@
 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
diff --git a/tempest/api/volume/admin/v2/test_snapshot_manage.py b/tempest/api/volume/admin/v2/test_snapshot_manage.py
index eed7dd1..e8bd477 100644
--- a/tempest/api/volume/admin/v2/test_snapshot_manage.py
+++ b/tempest/api/volume/admin/v2/test_snapshot_manage.py
@@ -61,8 +61,8 @@
         new_snapshot = self.admin_snapshot_manage_client.manage_snapshot(
             volume_id=volume['id'],
             ref={'source-name': snapshot_ref})['snapshot']
-        self.addCleanup(self.delete_snapshot,
-                        self.admin_snapshots_client, new_snapshot['id'])
+        self.addCleanup(self.delete_snapshot, new_snapshot['id'],
+                        self.admin_snapshots_client)
 
         # Wait for the snapshot to be available after manage operation
         waiters.wait_for_volume_resource_status(self.admin_snapshots_client,
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/v3/test_user_messages.py
index ed85d4d..991397a 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/v3/test_user_messages.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 from tempest.api.volume.v3 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/volume/base.py b/tempest/api/volume/base.py
index f8c435f..496594c 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -14,9 +14,9 @@
 #    under the License.
 
 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.common.utils import test_utils
 from tempest.lib import exceptions
 import tempest.test
@@ -145,7 +145,7 @@
 
         snapshot = cls.snapshots_client.create_snapshot(
             volume_id=volume_id, **kwargs)['snapshot']
-        cls.snapshots.append(snapshot)
+        cls.snapshots.append(snapshot['id'])
         waiters.wait_for_volume_resource_status(cls.snapshots_client,
                                                 snapshot['id'], 'available')
         return snapshot
@@ -171,11 +171,14 @@
         client.delete_volume(volume_id)
         client.wait_for_resource_deletion(volume_id)
 
-    @staticmethod
-    def delete_snapshot(client, snapshot_id):
+    def delete_snapshot(self, snapshot_id, snapshots_client=None):
         """Delete snapshot by the given client"""
-        client.delete_snapshot(snapshot_id)
-        client.wait_for_resource_deletion(snapshot_id)
+        if snapshots_client is None:
+            snapshots_client = self.snapshots_client
+        snapshots_client.delete_snapshot(snapshot_id)
+        snapshots_client.wait_for_resource_deletion(snapshot_id)
+        if snapshot_id in self.snapshots:
+            self.snapshots.remove(snapshot_id)
 
     def attach_volume(self, server_id, volume_id):
         """Attach a volume to a server"""
@@ -207,12 +210,12 @@
     def clear_snapshots(cls):
         for snapshot in cls.snapshots:
             test_utils.call_and_ignore_notfound_exc(
-                cls.snapshots_client.delete_snapshot, snapshot['id'])
+                cls.snapshots_client.delete_snapshot, snapshot)
 
         for snapshot in cls.snapshots:
             test_utils.call_and_ignore_notfound_exc(
                 cls.snapshots_client.wait_for_resource_deletion,
-                snapshot['id'])
+                snapshot)
 
     def create_server(self, **kwargs):
         name = kwargs.pop(
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 0a6901c..d39b07a 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
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index e664ff7..83006c0 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -13,10 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+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
 
@@ -49,10 +51,15 @@
 
     @decorators.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
     def test_volume_backup_create_get_detailed_list_restore_delete(self):
-        # Create backup
-        volume = self.create_volume()
+        # Create a volume with metadata
+        metadata = {"vol-meta1": "value1",
+                    "vol-meta2": "value2",
+                    "vol-meta3": "value3"}
+        volume = self.create_volume(metadata=metadata)
         self.addCleanup(self.volumes_client.delete_volume,
                         volume['id'])
+
+        # Create a backup
         backup_name = data_utils.rand_name(
             self.__class__.__name__ + '-Backup')
         description = data_utils.rand_name("volume-backup-description")
@@ -74,7 +81,15 @@
         self.assertIn((backup['name'], backup['id']),
                       [(m['name'], m['id']) for m in backups])
 
-        self.restore_backup(backup['id'])
+        restored_volume = self.restore_backup(backup['id'])
+
+        restored_volume_metadata = self.volumes_client.show_volume(
+            restored_volume['volume_id'])['volume']['metadata']
+
+        # Verify the backups has been restored successfully
+        # with the metadata of the source volume.
+        self.assertThat(restored_volume_metadata.items(),
+                        matchers.ContainsAll(metadata.items()))
 
     @decorators.idempotent_id('07af8f6d-80af-44c9-a5dc-c8427b1b62e6')
     @test.services('compute')
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index a3e46a8..d870534 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -17,9 +17,9 @@
 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
 
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index d1da95d..1d6d35f 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -18,7 +18,7 @@
 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
 
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 28e65ed..76ffc03 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -14,7 +14,7 @@
 #    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
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 9f4ce95..82b4fc2 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -10,9 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+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
 
@@ -34,12 +36,6 @@
         cls.name_field = cls.special_fields['name_field']
         cls.descrip_field = cls.special_fields['descrip_field']
 
-    def cleanup_snapshot(self, snapshot):
-        # Delete the snapshot
-        self.snapshots_client.delete_snapshot(snapshot['id'])
-        self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
-        self.snapshots.remove(snapshot)
-
     @decorators.idempotent_id('b467b54c-07a4-446d-a1cf-651dedcc3ff1')
     @test.services('compute')
     def test_snapshot_create_with_volume_in_use(self):
@@ -52,7 +48,7 @@
         snapshot = self.create_snapshot(self.volume_origin['id'],
                                         force=True)
         # Delete the snapshot
-        self.cleanup_snapshot(snapshot)
+        self.delete_snapshot(snapshot['id'])
 
     @decorators.idempotent_id('8567b54c-4455-446d-a1cf-651ddeaa3ff2')
     @test.services('compute')
@@ -68,9 +64,9 @@
 
         # Delete the snapshots. Some snapshot implementations can take
         # different paths according to order they are deleted.
-        self.cleanup_snapshot(snapshot1)
-        self.cleanup_snapshot(snapshot3)
-        self.cleanup_snapshot(snapshot2)
+        self.delete_snapshot(snapshot1['id'])
+        self.delete_snapshot(snapshot3['id'])
+        self.delete_snapshot(snapshot2['id'])
 
     @decorators.idempotent_id('5210a1de-85a0-11e6-bb21-641c676a5d61')
     @test.services('compute')
@@ -89,14 +85,18 @@
 
         # Delete the snapshots. Some snapshot implementations can take
         # different paths according to order they are deleted.
-        self.cleanup_snapshot(snapshot3)
-        self.cleanup_snapshot(snapshot1)
-        self.cleanup_snapshot(snapshot2)
+        self.delete_snapshot(snapshot3['id'])
+        self.delete_snapshot(snapshot1['id'])
+        self.delete_snapshot(snapshot2['id'])
 
     @decorators.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
     def test_snapshot_create_get_list_update_delete(self):
-        # Create a snapshot
-        snapshot = self.create_snapshot(self.volume_origin['id'])
+        # Create a snapshot with metadata
+        metadata = {"snap-meta1": "value1",
+                    "snap-meta2": "value2",
+                    "snap-meta3": "value3"}
+        snapshot = self.create_snapshot(self.volume_origin['id'],
+                                        metadata=metadata)
 
         # Get the snap and check for some of its details
         snap_get = self.snapshots_client.show_snapshot(
@@ -105,6 +105,10 @@
                          snap_get['volume_id'],
                          "Referred volume origin mismatch")
 
+        # 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])
         snaps_list = self.snapshots_client.list_snapshots()['snapshots']
@@ -129,7 +133,7 @@
         self.assertEqual(new_desc, updated_snapshot[self.descrip_field])
 
         # Delete the snapshot
-        self.cleanup_snapshot(snapshot)
+        self.delete_snapshot(snapshot['id'])
 
     @decorators.idempotent_id('677863d1-3142-456d-b6ac-9924f667a7f4')
     def test_volume_from_snapshot(self):
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index a3d91b0..d3e3c9b 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -11,8 +11,8 @@
 #    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
@@ -62,6 +62,13 @@
                           size=src_size - 1,
                           snapshot_id=src_snap['id'])
 
+    @test.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')
+
 
 class VolumesV1SnapshotNegativeTestJSON(VolumesV2SnapshotNegativeTestJSON):
     _api_version = 1
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 8b51e64..d2328c8 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -37,13 +37,12 @@
         super(VolumesV2ListTestJSON, cls).resource_setup()
 
         # Create 3 test volumes
-        metadata = {'Type': 'work'}
         # 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(metadata=metadata)
+            volume = cls.create_volume()
             cls.volume_id_list.append(volume['id'])
 
     @decorators.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_negative.py b/tempest/api/volume/v2/test_volumes_snapshots_negative.py
new file mode 100644
index 0000000..4608b07
--- /dev/null
+++ b/tempest/api/volume/v2/test_volumes_snapshots_negative.py
@@ -0,0 +1,46 @@
+# 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 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 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/clients.py b/tempest/clients.py
index cdd6925..e75fa79 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()
@@ -225,6 +227,8 @@
         self.credentials_client = self.identity_v3.CredentialsClient(
             **params_v3)
         self.groups_client = self.identity_v3.GroupsClient(**params_v3)
+        self.identity_versions_v3_client = self.identity_v3.VersionsClient(
+            **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
diff --git a/tempest/cmd/run.py b/tempest/cmd/run.py
index 54b844a..b36bf5c 100644
--- a/tempest/cmd/run.py
+++ b/tempest/cmd/run.py
@@ -78,11 +78,20 @@
 subunit-trace output filter. But, if you would prefer a subunit v2 stream be
 output to STDOUT use the **--subunit** flag
 
+Combining Runs
+==============
+
+There are certain situations in which you want to split a single run of tempest
+across 2 executions of tempest run. (for example to run part of the tests
+serially and others in parallel) To accomplish this but still treat the results
+as a single run you can leverage the **--combine** option which will append
+the current run's results with the previous runs.
 """
 
 import io
 import os
 import sys
+import tempfile
 import threading
 
 from cliff import command
@@ -165,6 +174,12 @@
         else:
             print("No .testr.conf file was found for local execution")
             sys.exit(2)
+        if parsed_args.combine:
+            temp_stream = tempfile.NamedTemporaryFile()
+            return_code = run_argv(['tempest', 'last', '--subunit'], sys.stdin,
+                                   temp_stream, sys.stderr)
+            if return_code > 0:
+                sys.exit(return_code)
 
         regex = self._build_regex(parsed_args)
         if parsed_args.list_tests:
@@ -173,6 +188,16 @@
         else:
             options = self._build_options(parsed_args)
             returncode = self._run(regex, options)
+            if returncode > 0:
+                sys.exit(returncode)
+
+        if parsed_args.combine:
+            return_code = run_argv(['tempest', 'last', '--subunit'], sys.stdin,
+                                   temp_stream, sys.stderr)
+            if return_code > 0:
+                sys.exit(return_code)
+            returncode = run_argv(['tempest', 'load', temp_stream.name],
+                                  sys.stdin, sys.stdout, sys.stderr)
         sys.exit(returncode)
 
     def get_description(self):
@@ -231,6 +256,10 @@
         # output args
         parser.add_argument("--subunit", action='store_true',
                             help='Enable subunit v2 output')
+        parser.add_argument("--combine", action='store_true',
+                            help='Combine the output of this run with the '
+                                 "previous run's as a combined stream in the "
+                                 "testr repository after it finish")
 
         parser.set_defaults(parallel=True)
         return parser
diff --git a/tempest/cmd/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index 0f868a9..8ee3055 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -294,7 +294,8 @@
             outfile.write(json.dumps(url_parser.test_logs))
         return
 
-    for test_name, items in url_parser.test_logs.iteritems():
+    for test_name in url_parser.test_logs:
+        items = url_parser.test_logs[test_name]
         sys.stdout.write('{0}\n'.format(test_name))
         if not items:
             sys.stdout.write('\n')
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 99da983..9a483bb 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -17,10 +17,10 @@
 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
 
 CONF = config.CONF
 
diff --git a/tempest/common/utils/__init__.py b/tempest/common/utils/__init__.py
index b6565d1..84e31d0 100644
--- a/tempest/common/utils/__init__.py
+++ b/tempest/common/utils/__init__.py
@@ -19,10 +19,6 @@
 
 CONF = config.CONF
 
-PING_IPV4_COMMAND = 'ping -c 3 '
-PING_IPV6_COMMAND = 'ping6 -c 3 '
-PING_PACKET_LOSS_REGEX = '(\d{1,3})\.?\d*\% packet loss'
-
 
 class DataUtils(object):
     def __getattr__(self, attr):
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 1487c1d..6dfc579 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,45 +40,15 @@
         :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
-        ssh_timeout = CONF.validation.ssh_timeout
-        connect_timeout = CONF.validation.connect_timeout
-        self.log_console = CONF.compute_feature_enabled.console_output
-
-        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 = CONF.validation.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 get_hostname(self):
-        # Get host name using command "hostname"
-        actual_hostname = self.exec_command("hostname").rstrip()
-        return actual_hostname
-
-    def get_ram_size_in_mb(self):
-        output = self.exec_command('free -m | grep Mem')
-        if output:
-            return output.split()[1]
-
-    def get_number_of_vcpus(self):
-        output = self.exec_command('grep -c ^processor /proc/cpuinfo')
-        return int(output)
+        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)
 
     def get_disks(self):
         # Select root disk devices as shown by lsblk
@@ -142,15 +79,6 @@
         cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
         return self.exec_command(cmd)
 
-    def ping_host(self, host, count=CONF.validation.ping_count,
-                  size=CONF.validation.ping_size, nic=None):
-        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)
@@ -172,26 +100,15 @@
         nic = self.exec_command(cmd)
         return nic.strip().strip(":").lower()
 
-    def get_ip_list(self):
-        cmd = "ip address"
-        return self.exec_command(cmd)
-
-    def assign_static_ip(self, nic, addr):
+    def assign_static_ip(self, nic, addr, network_mask_bits=28):
         cmd = "sudo ip addr add {ip}/{mask} dev {nic}".format(
-            ip=addr, mask=CONF.network.project_network_mask_bits,
-            nic=nic
-        )
+            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_pids(self, pr_name):
-        # Get pid(s) of a process/program
-        cmd = "ps -ef | grep %s | grep -v 'grep' | awk {'print $1'}" % pr_name
-        return self.exec_command(cmd).split('\n')
-
     def get_dns_servers(self):
         cmd = 'cat /etc/resolv.conf'
         resolve_file = self.exec_command(cmd).strip().split('\n')
@@ -200,10 +117,6 @@
                        if len(l) and l[0] == 'nameserver']
         return dns_servers
 
-    def send_signal(self, pid, signum):
-        cmd = 'sudo /bin/kill -{sig} {pid}'.format(pid=pid, sig=signum)
-        return self.exec_command(cmd)
-
     def _renew_lease_udhcpc(self, fixed_ip=None):
         """Renews DHCP lease via udhcpc client. """
         file_path = '/var/run/udhcpc.'
@@ -211,14 +124,15 @@
         pid = self.exec_command('cat {path}{nic}.pid'.
                                 format(path=file_path, nic=nic_name))
         pid = pid.strip()
-        self.send_signal(pid, 'USR1')
+        cmd = 'sudo /bin/kill -{sig} {pid}'.format(pid=pid, sig='USR1')
+        self.exec_command(cmd)
 
     def _renew_lease_dhclient(self, fixed_ip=None):
         """Renews DHCP lease via dhclient client. """
         cmd = "sudo /sbin/dhclient -r && sudo /sbin/dhclient"
         self.exec_command(cmd)
 
-    def renew_lease(self, fixed_ip=None):
+    def renew_lease(self, fixed_ip=None, dhcp_client='udhcpc'):
         """Wrapper method for renewing DHCP lease via given client
 
         Supporting:
@@ -227,7 +141,6 @@
         """
         # TODO(yfried): add support for dhcpcd
         supported_clients = ['udhcpc', 'dhclient']
-        dhcp_client = CONF.scenario.dhcp_client
         if dhcp_client not in supported_clients:
             raise tempest.lib.exceptions.InvalidConfiguration(
                 '%s DHCP client unsupported' % dhcp_client)
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/config.py b/tempest/config.py
index b4d88c5..d5c8ea9 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -15,12 +15,15 @@
 
 from __future__ import print_function
 
+import functools
 import os
 import tempfile
 
+import debtcollector.removals
 from oslo_concurrency import lockutils
 from oslo_config import cfg
 from oslo_log import log as logging
+import testtools
 
 from tempest.lib import exceptions
 from tempest.lib.services import clients
@@ -130,7 +133,7 @@
     cfg.StrOpt('uri_v3',
                help='Full URI of the OpenStack Identity API (Keystone), v3'),
     cfg.StrOpt('auth_version',
-               default='v2',
+               default='v3',
                help="Identity API version to be used for authentication "
                     "for API tests."),
     cfg.StrOpt('region',
@@ -222,6 +225,13 @@
                 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.
+    cfg.BoolOpt('forbid_global_implied_dsr',
+                default=False,
+                help='Does the environment forbid global roles implying '
+                     'domain specific ones?'),
     cfg.BoolOpt('security_compliance',
                 default=False,
                 help='Does the environment have the security compliance '
@@ -504,10 +514,20 @@
 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."
@@ -799,14 +819,7 @@
                 help="Is the v2 volume API enabled"),
     cfg.BoolOpt('api_v3',
                 default=False,
-                help="Is the v3 volume API enabled"),
-    # TODO(ynesenenko): Remove volume_services once liberty-eol happens.
-    cfg.BoolOpt('volume_services',
-                default=True,
-                help='Extract correct host info from host@backend',
-                deprecated_for_removal=True,
-                deprecated_reason='This config switch was added for Liberty '
-                                  'which is not supported anymore.')
+                help="Is the v3 volume API enabled")
 ]
 
 
@@ -981,9 +994,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",
@@ -1018,7 +1028,12 @@
                help="Prefix to be added when generating the name for "
                     "test resources. It can be used to discover all "
                     "resources associated with a specific test run when "
-                    "running tempest on a real-life cloud"),
+                    "running tempest on a real-life cloud",
+               deprecated_for_removal=True,
+               deprecated_reason="It is enough to add 'tempest' as this "
+                                 "prefix to ideintify resources which are "
+                                 "created by Tempest and no projects set "
+                                 "this option on OpenStack dev community."),
 ]
 
 _opts = [
@@ -1082,6 +1097,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']
@@ -1103,6 +1124,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."""
@@ -1180,6 +1218,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):
@@ -1189,6 +1233,79 @@
 CONF = TempestConfigProxy()
 
 
+@debtcollector.removals.remove(
+    message='use testtools.skipUnless instead', removal_version='Queens')
+def skip_unless_config(*args):
+    """Decorator to raise a skip if a config opt doesn't exist or is False
+
+    :param str group: The first arg, the option group to check
+    :param str name: The second arg, the option name to check
+    :param str msg: Optional third arg, the skip msg to use if a skip is raised
+    :raises testtools.TestCaseskipException: If the specified config option
+        doesn't exist or it exists and evaluates to False
+    """
+    def decorator(f):
+        group = args[0]
+        name = args[1]
+
+        @functools.wraps(f)
+        def wrapper(self, *func_args, **func_kwargs):
+            if not hasattr(CONF, group):
+                msg = "Config group %s doesn't exist" % group
+                raise testtools.TestCase.skipException(msg)
+
+            conf_group = getattr(CONF, group)
+            if not hasattr(conf_group, name):
+                msg = "Config option %s.%s doesn't exist" % (group,
+                                                             name)
+                raise testtools.TestCase.skipException(msg)
+
+            value = getattr(conf_group, name)
+            if not value:
+                if len(args) == 3:
+                    msg = args[2]
+                else:
+                    msg = "Config option %s.%s is false" % (group,
+                                                            name)
+                raise testtools.TestCase.skipException(msg)
+            return f(self, *func_args, **func_kwargs)
+        return wrapper
+    return decorator
+
+
+@debtcollector.removals.remove(
+    message='use testtools.skipIf instead', removal_version='Queens')
+def skip_if_config(*args):
+    """Raise a skipException if a config exists and is True
+
+    :param str group: The first arg, the option group to check
+    :param str name: The second arg, the option name to check
+    :param str msg: Optional third arg, the skip msg to use if a skip is raised
+    :raises testtools.TestCase.skipException: If the specified config option
+        exists and evaluates to True
+    """
+    def decorator(f):
+        group = args[0]
+        name = args[1]
+
+        @functools.wraps(f)
+        def wrapper(self, *func_args, **func_kwargs):
+            if hasattr(CONF, group):
+                conf_group = getattr(CONF, group)
+                if hasattr(conf_group, name):
+                    value = getattr(conf_group, name)
+                    if value:
+                        if len(args) == 3:
+                            msg = args[2]
+                        else:
+                            msg = "Config option %s.%s is false" % (group,
+                                                                    name)
+                        raise testtools.TestCase.skipException(msg)
+            return f(self, *func_args, **func_kwargs)
+        return wrapper
+    return decorator
+
+
 def service_client_config(service_client_name=None):
     """Return a dict with the parameters to init service clients
 
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/keypairs.py b/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
index 2828097..e7dcf79 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/keypairs.py
@@ -34,12 +34,9 @@
 
                 },
                 'additionalProperties': False,
-                # When we run the get keypair API, response body includes
-                # all the above mentioned attributes.
-                # But in Nova API sample file, response body includes only
-                # 'public_key', 'name' & 'fingerprint'. So only 'public_key',
-                # 'name' & 'fingerprint' are defined as 'required'.
-                'required': ['public_key', 'name', 'fingerprint']
+                'required': ['public_key', 'name', 'fingerprint', 'user_id',
+                             'deleted', 'created_at', 'updated_at',
+                             'deleted_at', 'id']
             }
         },
         'additionalProperties': False,
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_26/servers.py b/tempest/lib/api_schema/response/compute/v2_26/servers.py
index bc5d18e..b03bdf6 100644
--- a/tempest/lib/api_schema/response/compute/v2_26/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_26/servers.py
@@ -1,4 +1,5 @@
 # Copyright 2016 IBM Corp.
+# Copyright 2017 AT&T Corp.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
@@ -45,3 +46,36 @@
 # list response schema wasn't changed for v2.26 so use v2.1
 
 list_servers = copy.deepcopy(servers21.list_servers)
+
+list_tags = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'tags': tag_items,
+        },
+        'additionalProperties': False,
+        'required': ['tags']
+    }
+}
+
+update_all_tags = copy.deepcopy(list_tags)
+
+delete_all_tags = {'status_code': [204]}
+
+check_tag_existence = {'status_code': [204]}
+
+update_tag = {
+    'status_code': [201, 204],
+    'response_header': {
+        'type': 'object',
+        'properties': {
+            'location': {
+                'type': 'string'
+            }
+        },
+        'required': ['location']
+    }
+}
+
+delete_tag = {'status_code': [204]}
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index 283b10f..eafde44 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -26,10 +26,6 @@
 from oslo_utils import uuidutils
 import six.moves.urllib.parse as urlparse
 
-# TODO(oomichi): Need to remove this after switching all modules to decorators
-# on all OpenStack projects because they runs check-uuid on their own gates.
-OLD_DECORATOR_MODULE = 'test'
-
 DECORATOR_MODULE = 'decorators'
 DECORATOR_NAME = 'idempotent_id'
 DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
@@ -128,8 +124,7 @@
                 hasattr(decorator.func, 'attr') and
                 decorator.func.attr == DECORATOR_NAME and
                 hasattr(decorator.func, 'value') and
-                (decorator.func.value.id == DECORATOR_MODULE or
-                 decorator.func.value.id == OLD_DECORATOR_MODULE)):
+                decorator.func.value.id == DECORATOR_MODULE):
                 for arg in decorator.args:
                     idempotent_id = ast.literal_eval(arg)
         return idempotent_id
@@ -361,7 +356,7 @@
         sys.exit("@decorators.idempotent_id existence and uniqueness checks "
                  "failed\n"
                  "Run 'tox -v -euuidgen' to automatically fix tests with\n"
-                 "missing @test.idempotent_id decorators.")
+                 "missing @decorators.idempotent_id decorators.")
 
 if __name__ == '__main__':
     run()
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index f5bff20..99ba6ab 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -23,6 +23,7 @@
 from oslo_log import log as logging
 from oslo_serialization import jsonutils as json
 import six
+from six.moves import urllib
 
 from tempest.lib.common import http
 from tempest.lib.common import jsonschema_validator
@@ -731,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
@@ -915,6 +925,16 @@
                     msg = ("HTTP response header is invalid (%s)" % ex)
                     raise exceptions.InvalidHTTPResponseHeader(msg)
 
+    def _get_base_version_url(self):
+        # TODO(oomichi): This method can be used for auth's replace_version().
+        # So it is nice to have common logic for the maintenance.
+        endpoint = self.base_url
+        url = urllib.parse.urlsplit(endpoint)
+        new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
+        url = list(url)
+        url[2] = new_path + '/'
+        return urllib.parse.urlunsplit(url)
+
 
 class ResponseBody(dict):
     """Class that wraps an http response and dict body into a single value.
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index 5e65bee..657c0c1 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -111,6 +111,7 @@
             except (EOFError,
                     socket.error, socket.timeout,
                     paramiko.SSHException) as e:
+                ssh.close()
                 if self._is_timed_out(_start_time):
                     LOG.exception("Failed to establish authenticated ssh"
                                   " connection to %s@%s after %d attempts",
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index 642514b..a0941ef 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -43,7 +43,7 @@
     return uuid.uuid4().hex
 
 
-def rand_name(name='', prefix=None):
+def rand_name(name='', prefix='tempest'):
     """Generate a random name that includes a random number
 
     :param str name: The name that you want to include
diff --git a/tempest/lib/common/utils/linux/__init__.py b/tempest/lib/common/utils/linux/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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 6ed99b4..92f9698 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -15,6 +15,7 @@
 import functools
 import uuid
 
+import debtcollector.removals
 import six
 import testtools
 
@@ -61,6 +62,7 @@
     return decorator
 
 
+@debtcollector.removals.remove(removal_version='Queen')
 class skip_unless_attr(object):
     """Decorator to skip tests if a specified attr does not exists or False"""
     def __init__(self, attr, msg=None):
diff --git a/tempest/lib/services/clients.py b/tempest/lib/services/clients.py
index 445e8bd..eefac66 100644
--- a/tempest/lib/services/clients.py
+++ b/tempest/lib/services/clients.py
@@ -125,6 +125,9 @@
                 name=plugin_name,
                 detailed_error=detailed_error % plugin_name)
         self._service_clients[plugin_name] = service_client_data
+        LOG.debug("Successfully registered plugin %s in the service client "
+                  "registry with configuration: %s", plugin_name,
+                  service_client_data)
 
     def get_service_clients(self):
         return self._service_clients
diff --git a/tempest/lib/services/compute/agents_client.py b/tempest/lib/services/compute/agents_client.py
index 169d978..408f75d 100644
--- a/tempest/lib/services/compute/agents_client.py
+++ b/tempest/lib/services/compute/agents_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-v2.1.html#listbuilds
+        https://developer.openstack.org/api-ref/compute/#list-agent-builds
         """
         url = 'os-agents'
         if params:
@@ -43,7 +43,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#agentbuild
+        https://developer.openstack.org/api-ref/compute/#create-agent-build
         """
         post_body = json.dumps({'agent': kwargs})
         resp, body = self.post('os-agents', post_body)
@@ -56,7 +56,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteBuild
+        https://developer.openstack.org/api-ref/compute/#delete-agent-build
         """
         resp, body = self.delete("os-agents/%s" % agent_id)
         self.validate_response(schema.delete_agent, resp, body)
@@ -67,7 +67,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updatebuild
+        https://developer.openstack.org/api-ref/compute/#update-agent-build
         """
         put_body = json.dumps({'para': kwargs})
         resp, body = self.put('os-agents/%s' % agent_id, put_body)
diff --git a/tempest/lib/services/compute/aggregates_client.py b/tempest/lib/services/compute/aggregates_client.py
index c1a6c8c..713d7a3 100644
--- a/tempest/lib/services/compute/aggregates_client.py
+++ b/tempest/lib/services/compute/aggregates_client.py
@@ -42,7 +42,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createAggregate
+        https://developer.openstack.org/api-ref/compute/#create-aggregate
         """
         post_body = json.dumps({'aggregate': kwargs})
         resp, body = self.post('os-aggregates', post_body)
@@ -56,7 +56,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateAggregate
+        https://developer.openstack.org/api-ref/compute/#update-aggregate
         """
         put_body = json.dumps({'aggregate': kwargs})
         resp, body = self.put('os-aggregates/%s' % aggregate_id, put_body)
@@ -88,7 +88,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#addHost
+        https://developer.openstack.org/api-ref/compute/#add-host
         """
         post_body = json.dumps({'add_host': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
@@ -102,7 +102,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#removeAggregateHost
+        https://developer.openstack.org/api-ref/compute/#remove-host
         """
         post_body = json.dumps({'remove_host': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
@@ -116,7 +116,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#addAggregateMetadata
+        https://developer.openstack.org/api-ref/compute/#create-or-update-aggregate-metadata
         """
         post_body = json.dumps({'set_metadata': kwargs})
         resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
diff --git a/tempest/lib/services/compute/fixed_ips_client.py b/tempest/lib/services/compute/fixed_ips_client.py
index 682ee86..968646c 100644
--- a/tempest/lib/services/compute/fixed_ips_client.py
+++ b/tempest/lib/services/compute/fixed_ips_client.py
@@ -34,7 +34,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#reserveIP
+        https://developer.openstack.org/api-ref/compute/#reserve-or-release-a-fixed-ip
         """
         url = "os-fixed-ips/%s/action" % fixed_ip
         resp, body = self.post(url, json.dumps(kwargs))
diff --git a/tempest/lib/services/compute/flavors_client.py b/tempest/lib/services/compute/flavors_client.py
index a83c68b..0fb1991 100644
--- a/tempest/lib/services/compute/flavors_client.py
+++ b/tempest/lib/services/compute/flavors_client.py
@@ -32,7 +32,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listFlavors
+        https://developer.openstack.org/api-ref/compute/#list-flavors
+        https://developer.openstack.org/api-ref/compute/#list-flavors-with-details
         """
         url = 'flavors'
         _schema = schema.list_flavors
@@ -53,7 +54,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showFlavor
+        https://developer.openstack.org/api-ref/compute/#show-flavor-details
         """
         resp, body = self.get("flavors/%s" % flavor_id)
         body = json.loads(body)
@@ -65,7 +66,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createFlavor
+        https://developer.openstack.org/api-ref/compute/#create-flavor
         """
         if 'ephemeral' in kwargs:
             kwargs['OS-FLV-EXT-DATA:ephemeral'] = kwargs.pop('ephemeral')
@@ -84,7 +85,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteFlavor
+        https://developer.openstack.org/api-ref/compute/#delete-flavor
         """
         resp, body = self.delete("flavors/{0}".format(flavor_id))
         self.validate_response(schema.delete_flavor, resp, body)
@@ -110,7 +111,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createFlavorExtraSpec
+        https://developer.openstack.org/api-ref/compute/#create-extra-specs-for-a-flavor
         """
         post_body = json.dumps({'extra_specs': kwargs})
         resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
@@ -125,7 +126,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listFlavorExtraSpecs
+        https://developer.openstack.org/api-ref/compute/#list-extra-specs-for-a-flavor
         """
         resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
         body = json.loads(body)
@@ -138,7 +139,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showFlavorExtraSpec
+        https://developer.openstack.org/api-ref/compute/#show-an-extra-spec-for-a-flavor
         """
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (flavor_id,
                               key))
@@ -153,7 +154,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateFlavorExtraSpec
+        https://developer.openstack.org/api-ref/compute/#update-an-extra-spec-for-a-flavor
         """
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key), json.dumps(kwargs))
@@ -170,7 +171,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteFlavorExtraSpec
+        https://developer.openstack.org/api-ref/compute/#delete-an-extra-spec-for-a-flavor
         """
         resp, body = self.delete('flavors/%s/os-extra_specs/%s' %
                                  (flavor_id, key))
@@ -182,7 +183,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listFlavorAccess
+        https://developer.openstack.org/api-ref/compute/#list-flavor-access-information-for-given-flavor
         """
         resp, body = self.get('flavors/%s/os-flavor-access' % flavor_id)
         body = json.loads(body)
@@ -195,7 +196,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#addFlavorAccess
+        https://developer.openstack.org/api-ref/compute/#add-flavor-access-to-tenant-addtenantaccess-action
         """
         post_body = {
             'addTenantAccess': {
@@ -214,7 +215,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#removeFlavorAccess
+        https://developer.openstack.org/api-ref/compute/#remove-flavor-access-from-tenant-removetenantaccess-action
         """
         post_body = {
             'removeTenantAccess': {
diff --git a/tempest/lib/services/compute/floating_ips_client.py b/tempest/lib/services/compute/floating_ips_client.py
index 744e14c..5364d97 100644
--- a/tempest/lib/services/compute/floating_ips_client.py
+++ b/tempest/lib/services/compute/floating_ips_client.py
@@ -29,7 +29,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listfloatingipsObject
+        https://developer.openstack.org/api-ref/compute/#list-floating-ip-addresses
         """
         url = 'os-floating-ips'
         if params:
@@ -45,7 +45,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showFloatingIP
+        https://developer.openstack.org/api-ref/compute/#show-floating-ip-address-details
         """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.get(url)
@@ -58,7 +58,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createFloatingIP
+        https://developer.openstack.org/api-ref/compute/#create-allocate-floating-ip-address
         """
         url = 'os-floating-ips'
         post_body = json.dumps(kwargs)
@@ -72,7 +72,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteFloatingIP
+        https://developer.openstack.org/api-ref/compute/#delete-deallocate-floating-ip-address
         """
         url = "os-floating-ips/%s" % floating_ip_id
         resp, body = self.delete(url)
diff --git a/tempest/lib/services/compute/hosts_client.py b/tempest/lib/services/compute/hosts_client.py
index 1b93b00..1fdd907 100644
--- a/tempest/lib/services/compute/hosts_client.py
+++ b/tempest/lib/services/compute/hosts_client.py
@@ -23,7 +23,12 @@
 class HostsClient(base_compute_client.BaseComputeClient):
 
     def list_hosts(self, **params):
-        """List all hosts."""
+        """List all hosts.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#list-hosts
+        """
 
         url = 'os-hosts'
         if params:
@@ -47,7 +52,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#enablehost
+        https://developer.openstack.org/api-ref/compute/#update-host-status
         """
 
         request_body = {
diff --git a/tempest/lib/services/compute/images_client.py b/tempest/lib/services/compute/images_client.py
index e937c13..86bea9e 100644
--- a/tempest/lib/services/compute/images_client.py
+++ b/tempest/lib/services/compute/images_client.py
@@ -29,7 +29,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createImage
+        https://developer.openstack.org/api-ref/compute/#create-image-createimage-action
         """
 
         post_body = {'createImage': kwargs}
@@ -44,7 +44,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listImages
+        https://developer.openstack.org/api-ref/compute/#list-images
+        https://developer.openstack.org/api-ref/compute/#list-images-with-details
         """
         url = 'images'
         _schema = schema.list_images
@@ -85,7 +86,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createImageMetadata
+        https://developer.openstack.org/api-ref/compute/#update-image-metadata
         """
         post_body = json.dumps({'metadata': meta})
         resp, body = self.put('images/%s/metadata' % image_id, post_body)
@@ -98,7 +99,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateImageMetadata
+        https://developer.openstack.org/api-ref/compute/#create-image-metadata
         """
         post_body = json.dumps({'metadata': meta})
         resp, body = self.post('images/%s/metadata' % image_id, post_body)
@@ -118,7 +119,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#setImageMetadataItem
+        https://developer.openstack.org/api-ref/compute/#create-or-update-image-metadata-item
         """
         post_body = json.dumps({'meta': meta})
         resp, body = self.put('images/%s/metadata/%s' % (image_id, key),
diff --git a/tempest/lib/services/compute/interfaces_client.py b/tempest/lib/services/compute/interfaces_client.py
index 37157a4..d7c3107 100644
--- a/tempest/lib/services/compute/interfaces_client.py
+++ b/tempest/lib/services/compute/interfaces_client.py
@@ -33,7 +33,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createAttachInterface
+        https://developer.openstack.org/api-ref/compute/#create-interface
         """
         post_body = {'interfaceAttachment': kwargs}
         post_body = json.dumps(post_body)
diff --git a/tempest/lib/services/compute/keypairs_client.py b/tempest/lib/services/compute/keypairs_client.py
index c3f1781..5215fca 100644
--- a/tempest/lib/services/compute/keypairs_client.py
+++ b/tempest/lib/services/compute/keypairs_client.py
@@ -32,7 +32,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listKeypairs
+        https://developer.openstack.org/api-ref/compute/#list-keypairs
         """
         url = 'os-keypairs'
         if params:
@@ -48,7 +48,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showKeypair
+        https://developer.openstack.org/api-ref/compute/#show-keypair-details
         """
         url = "os-keypairs/%s" % keypair_name
         if params:
@@ -64,7 +64,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createKeypair
+        https://developer.openstack.org/api-ref/compute/#create-or-import-keypair
         """
         post_body = json.dumps({'keypair': kwargs})
         resp, body = self.post("os-keypairs", body=post_body)
@@ -78,7 +78,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteKeypair
+        https://developer.openstack.org/api-ref/compute/#delete-keypair
         """
         url = "os-keypairs/%s" % keypair_name
         if params:
diff --git a/tempest/lib/services/compute/migrations_client.py b/tempest/lib/services/compute/migrations_client.py
index 375cbda..68c8f3f 100644
--- a/tempest/lib/services/compute/migrations_client.py
+++ b/tempest/lib/services/compute/migrations_client.py
@@ -32,7 +32,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listMigrations
+        https://developer.openstack.org/api-ref/compute/#list-migrations
         """
 
         url = 'os-migrations'
diff --git a/tempest/lib/services/compute/quotas_client.py b/tempest/lib/services/compute/quotas_client.py
index a2b0397..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):
@@ -47,7 +62,7 @@
 
         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
+        https://developer.openstack.org/api-ref/compute/#update-quotas
         """
 
         post_body = json.dumps({'quota_set': kwargs})
diff --git a/tempest/lib/services/compute/security_group_default_rules_client.py b/tempest/lib/services/compute/security_group_default_rules_client.py
index e2d3c98..70cab88 100644
--- a/tempest/lib/services/compute/security_group_default_rules_client.py
+++ b/tempest/lib/services/compute/security_group_default_rules_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-v2.1.html#createSecGroupDefaultRule
+        https://developer.openstack.org/api-ref/compute/#create-default-security-group-rule
         """
         post_body = json.dumps({'security_group_default_rule': kwargs})
         url = 'os-security-group-default-rules'
diff --git a/tempest/lib/services/compute/security_group_rules_client.py b/tempest/lib/services/compute/security_group_rules_client.py
index 3121e24..710bfab 100644
--- a/tempest/lib/services/compute/security_group_rules_client.py
+++ b/tempest/lib/services/compute/security_group_rules_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-v2.1.html#createSecGroupRule
+        https://developer.openstack.org/api-ref/compute/#create-security-group-rule
         """
         post_body = json.dumps({'security_group_rule': kwargs})
         url = 'os-security-group-rules'
diff --git a/tempest/lib/services/compute/security_groups_client.py b/tempest/lib/services/compute/security_groups_client.py
index a247346..b525f68 100644
--- a/tempest/lib/services/compute/security_groups_client.py
+++ b/tempest/lib/services/compute/security_groups_client.py
@@ -30,7 +30,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listSecGroups
+        https://developer.openstack.org/api-ref/compute/#list-security-groups
         """
 
         url = 'os-security-groups'
@@ -47,7 +47,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showSecGroup
+        https://developer.openstack.org/api-ref/compute/#show-security-group-details
         """
         url = "os-security-groups/%s" % security_group_id
         resp, body = self.get(url)
@@ -60,7 +60,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createSecGroup
+        https://developer.openstack.org/api-ref/compute/#create-security-group
         """
         post_body = json.dumps({'security_group': kwargs})
         resp, body = self.post('os-security-groups', post_body)
@@ -73,7 +73,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateSecGroup
+        https://developer.openstack.org/api-ref/compute/#update-security-group
         """
         post_body = json.dumps({'security_group': kwargs})
         resp, body = self.put('os-security-groups/%s' % security_group_id,
@@ -87,7 +87,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteSecGroup
+        https://developer.openstack.org/api-ref/compute/#delete-security-group
         """
         resp, body = self.delete(
             'os-security-groups/%s' % security_group_id)
diff --git a/tempest/lib/services/compute/server_groups_client.py b/tempest/lib/services/compute/server_groups_client.py
index 9ba8d38..3a935b4 100644
--- a/tempest/lib/services/compute/server_groups_client.py
+++ b/tempest/lib/services/compute/server_groups_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-v2.1.html#createServerGroup
+        https://developer.openstack.org/api-ref/compute/#create-server-group
         """
         post_body = json.dumps({'server_group': kwargs})
         resp, body = self.post('os-server-groups', post_body)
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index adff244..b37afb3 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -1,5 +1,6 @@
 # Copyright 2012 OpenStack Foundation
 # Copyright 2013 Hewlett-Packard Development Company, L.P.
+# Copyright 2017 AT&T Corp.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -98,7 +99,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateServer
+        https://developer.openstack.org/api-ref/compute/#update-server
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -132,7 +133,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteServer
+        https://developer.openstack.org/api-ref/compute/#delete-server
         """
         resp, body = self.delete("servers/%s" % server_id)
         self.validate_response(schema.delete_server, resp, body)
@@ -143,8 +144,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listServers
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listDetailServers
+        https://developer.openstack.org/api-ref/compute/#list-servers
+        https://developer.openstack.org/api-ref/compute/#list-servers-detailed
         """
 
         url = 'servers'
@@ -167,7 +168,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#list-ips
+        https://developer.openstack.org/api-ref/compute/#list-ips
         """
         resp, body = self.get("servers/%s/ips" % server_id)
         body = json.loads(body)
@@ -198,7 +199,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createBackup
+        https://developer.openstack.org/api-ref/compute/#create-server-back-up-createbackup-action
         """
         return self.action(server_id, "createBackup", **kwargs)
 
@@ -207,7 +208,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#changePassword
+        https://developer.openstack.org/api-ref/compute/#change-administrative-password-changepassword-action
         """
         return self.action(server_id, 'changePassword', **kwargs)
 
@@ -235,7 +236,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#reboot
+        https://developer.openstack.org/api-ref/compute/#reboot-server-reboot-action
         """
         return self.action(server_id, 'reboot', **kwargs)
 
@@ -244,7 +245,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#rebuild
+        https://developer.openstack.org/api-ref/compute/#rebuild-server-rebuild-action
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -266,7 +267,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#resize
+        https://developer.openstack.org/api-ref/compute/#resize-server-resize-action
 
         Most parameters except the following are passed to the API without
         any changes.
@@ -282,7 +283,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#confirmResize
+        https://developer.openstack.org/api-ref/compute/#confirm-resized-server-confirmresize-action
         """
         return self.action(server_id, 'confirmResize',
                            schema.server_actions_confirm_resize,
@@ -293,7 +294,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#revertResize
+        https://developer.openstack.org/api-ref/compute/#revert-resized-server-revertresize-action
         """
         return self.action(server_id, 'revertResize', **kwargs)
 
@@ -302,7 +303,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listServerMetadata
+        https://developer.openstack.org/api-ref/compute/#list-all-metadata
         """
         resp, body = self.get("servers/%s/metadata" % server_id)
         body = json.loads(body)
@@ -314,7 +315,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createServerMetadata
+        https://developer.openstack.org/api-ref/compute/#create-or-replace-metadata-items
         """
         if no_metadata_field:
             post_body = ""
@@ -331,7 +332,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#updateServerMetadata
+        https://developer.openstack.org/api-ref/compute/#update-metadata-items
         """
         post_body = json.dumps({'metadata': meta})
         resp, body = self.post('servers/%s/metadata' % server_id,
@@ -346,7 +347,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showServerMetadataItem
+        https://developer.openstack.org/api-ref/compute/#show-metadata-item-details
         """
         resp, body = self.get("servers/%s/metadata/%s" % (server_id, key))
         body = json.loads(body)
@@ -359,7 +360,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#setServerMetadataItem
+        https://developer.openstack.org/api-ref/compute/#create-or-update-metadata-item
         """
         post_body = json.dumps({'meta': meta})
         resp, body = self.put('servers/%s/metadata/%s' % (server_id, key),
@@ -374,7 +375,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteServerMetadataItem
+        https://developer.openstack.org/api-ref/compute/#delete-metadata-item
         """
         resp, body = self.delete("servers/%s/metadata/%s" %
                                  (server_id, key))
@@ -387,7 +388,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#stop
+        https://developer.openstack.org/api-ref/compute/#stop-server-os-stop-action
         """
         return self.action(server_id, 'os-stop', **kwargs)
 
@@ -396,7 +397,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#start
+        https://developer.openstack.org/api-ref/compute/#start-server-os-start-action
         """
         return self.action(server_id, 'os-start', **kwargs)
 
@@ -405,7 +406,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#attachVolume
+        https://developer.openstack.org/api-ref/compute/#attach-a-volume-to-an-instance
         """
         post_body = json.dumps({'volumeAttachment': kwargs})
         resp, body = self.post('servers/%s/os-volume_attachments' % server_id,
@@ -428,7 +429,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteVolumeAttachment
+        https://developer.openstack.org/api-ref/compute/#detach-a-volume-from-an-instance
         """
         resp, body = self.delete('servers/%s/os-volume_attachments/%s' %
                                  (server_id, volume_id))
@@ -440,7 +441,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#getVolumeAttachmentDetails
+        https://developer.openstack.org/api-ref/compute/#show-a-detail-of-a-volume-attachment
         """
         resp, body = self.get('servers/%s/os-volume_attachments/%s' % (
             server_id, volume_id))
@@ -453,7 +454,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listVolumeAttachments
+        https://developer.openstack.org/api-ref/compute/#list-volume-attachments-for-an-instance
         """
         resp, body = self.get('servers/%s/os-volume_attachments' % (
             server_id))
@@ -466,12 +467,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#addSecurityGroup
+        https://developer.openstack.org/api-ref/compute/#add-security-group-to-a-server-addsecuritygroup-action
         """
-        # TODO(oomichi): The api-site doesn't contain this API description.
-        # So the above should be changed to the api-site link after
-        # adding the description on the api-site.
-        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524199
         return self.action(server_id, 'addSecurityGroup', **kwargs)
 
     def remove_security_group(self, server_id, **kwargs):
@@ -479,12 +476,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#removeSecurityGroup
+        https://developer.openstack.org/api-ref/compute/#remove-security-group-from-a-server-removesecuritygroup-action
         """
-        # TODO(oomichi): The api-site doesn't contain this API description.
-        # So the above should be changed to the api-site link after
-        # adding the description on the api-site.
-        # LP: https://bugs.launchpad.net/openstack-api-site/+bug/1524199
         return self.action(server_id, 'removeSecurityGroup', **kwargs)
 
     def live_migrate_server(self, server_id, **kwargs):
@@ -492,7 +485,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#migrateLive
+        https://developer.openstack.org/api-ref/compute/#live-migrate-server-os-migratelive-action
         """
         return self.action(server_id, 'os-migrateLive', **kwargs)
 
@@ -501,7 +494,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#migrate
+        https://developer.openstack.org/api-ref/compute/#migrate-server-migrate-action
         """
         return self.action(server_id, 'migrate', **kwargs)
 
@@ -510,7 +503,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#lock
+        https://developer.openstack.org/api-ref/compute/#lock-server-lock-action
         """
         return self.action(server_id, 'lock', **kwargs)
 
@@ -519,7 +512,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#unlock
+        https://developer.openstack.org/api-ref/compute/#unlock-server-unlock-action
         """
         return self.action(server_id, 'unlock', **kwargs)
 
@@ -528,7 +521,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#suspend
+        https://developer.openstack.org/api-ref/compute/#suspend-server-suspend-action
         """
         return self.action(server_id, 'suspend', **kwargs)
 
@@ -537,7 +530,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#resume
+        https://developer.openstack.org/api-ref/compute/#resume-suspended-server-resume-action
         """
         return self.action(server_id, 'resume', **kwargs)
 
@@ -546,7 +539,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#pause
+        https://developer.openstack.org/api-ref/compute/#pause-server-pause-action
         """
         return self.action(server_id, 'pause', **kwargs)
 
@@ -555,7 +548,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#unpause
+        https://developer.openstack.org/api-ref/compute/#unpause-server-unpause-action
         """
         return self.action(server_id, 'unpause', **kwargs)
 
@@ -564,7 +557,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#resetState
+        https://developer.openstack.org/api-ref/compute/#reset-server-state-os-resetstate-action
         """
         return self.action(server_id, 'os-resetState', **kwargs)
 
@@ -573,7 +566,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#shelve
+        https://developer.openstack.org/api-ref/compute/#shelve-server-shelve-action
         """
         return self.action(server_id, 'shelve', **kwargs)
 
@@ -582,7 +575,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#unshelve
+        https://developer.openstack.org/api-ref/compute/#unshelve-restore-shelved-server-unshelve-action
         """
         return self.action(server_id, 'unshelve', **kwargs)
 
@@ -591,7 +584,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#shelveOffload
+        https://developer.openstack.org/api-ref/compute/#shelf-offload-remove-server-shelveoffload-action
         """
         return self.action(server_id, 'shelveOffload', **kwargs)
 
@@ -600,7 +593,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#getConsoleOutput
+        https://developer.openstack.org/api-ref/compute/#show-console-output-os-getconsoleoutput-action
         """
         return self.action(server_id, 'os-getConsoleOutput',
                            schema.get_console_output, **kwargs)
@@ -618,7 +611,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#rescue
+        https://developer.openstack.org/api-ref/compute/#rescue-server-rescue-action
         """
         if self.enable_instance_password:
             rescue_schema = schema.rescue_server_with_admin_pass
@@ -631,7 +624,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#unrescue
+        https://developer.openstack.org/api-ref/compute/#unrescue-server-unrescue-action
         """
         return self.action(server_id, 'unrescue')
 
@@ -661,7 +654,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#forceDelete
+        https://developer.openstack.org/api-ref/compute/#force-delete-server-forcedelete-action
         """
         return self.action(server_id, 'forceDelete', **kwargs)
 
@@ -670,7 +663,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#restore
+        https://developer.openstack.org/api-ref/compute/#restore-soft-deleted-instance-restore-action
         """
         return self.action(server_id, 'restore', **kwargs)
 
@@ -679,7 +672,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#resetNetwork
+        https://developer.openstack.org/api-ref/compute/#reset-networking-on-a-server-resetnetwork-action
         """
         return self.action(server_id, 'resetNetwork', **kwargs)
 
@@ -688,7 +681,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#injectNetworkInfo
+        https://developer.openstack.org/api-ref/compute/#inject-network-information-injectnetworkinfo-action
         """
         return self.action(server_id, 'injectNetworkInfo', **kwargs)
 
@@ -697,7 +690,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#getVNCConsole
+        https://developer.openstack.org/api-ref/compute/#get-vnc-console-os-getvncconsole-action
         """
         return self.action(server_id, "os-getVNCConsole",
                            schema.get_vnc_console, **kwargs)
@@ -707,7 +700,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#addFixedIp
+        https://developer.openstack.org/api-ref/compute/#add-associate-fixed-ip-addfixedip-action
         """
         return self.action(server_id, 'addFixedIp', **kwargs)
 
@@ -716,7 +709,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#removeFixedIp
+        https://developer.openstack.org/api-ref/compute/#remove-disassociate-fixed-ip-removefixedip-action
         """
         return self.action(server_id, 'removeFixedIp', **kwargs)
 
@@ -725,10 +718,99 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listSecurityGroupsByServer
+        https://developer.openstack.org/api-ref/compute/#list-security-groups-by-server
         """
         resp, body = self.get("servers/%s/os-security-groups" % server_id)
         body = json.loads(body)
         self.validate_response(security_groups_schema.list_security_groups,
                                resp, body)
         return rest_client.ResponseBody(resp, body)
+
+    def list_tags(self, server_id):
+        """Lists all tags for a server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#list-tags
+        """
+        url = 'servers/%s/tags' % server_id
+        resp, body = self.get(url)
+        body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.list_tags, resp, body)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_all_tags(self, server_id, tags):
+        """Replaces all tags on specified server with the new set of tags.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#replace-tags
+
+        :param tags: List of tags to replace current server tags with.
+        """
+        url = 'servers/%s/tags' % server_id
+        put_body = {'tags': tags}
+        resp, body = self.put(url, json.dumps(put_body))
+        body = json.loads(body)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.update_all_tags, resp, body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_all_tags(self, server_id):
+        """Deletes all tags from the specified server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#delete-all-tags
+        """
+        url = 'servers/%s/tags' % server_id
+        resp, body = self.delete(url)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.delete_all_tags, resp, body)
+        return rest_client.ResponseBody(resp, body)
+
+    def check_tag_existence(self, server_id, tag):
+        """Checks tag existence on the server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#check-tag-existence
+
+        :param tag: Check for existence of tag on specified server.
+        """
+        url = 'servers/%s/tags/%s' % (server_id, tag)
+        resp, body = self.get(url)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.check_tag_existence, resp, body)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_tag(self, server_id, tag):
+        """Adds a single tag to the server if server has no specified tag.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#add-a-single-tag
+
+        :param tag: Tag to be added to the specified server.
+        """
+        url = 'servers/%s/tags/%s' % (server_id, tag)
+        resp, body = self.put(url, None)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.update_tag, resp, body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_tag(self, server_id, tag):
+        """Deletes a single tag from the specified server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#delete-a-single-tag
+
+        :param tag: Tag to be removed from the specified server.
+        """
+        url = 'servers/%s/tags/%s' % (server_id, tag)
+        resp, body = self.delete(url)
+        schema = self.get_schema(self.schema_versions_info)
+        self.validate_response(schema.delete_tag, resp, body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/services_client.py b/tempest/lib/services/compute/services_client.py
index 0dbd1b2..77ac82f 100644
--- a/tempest/lib/services/compute/services_client.py
+++ b/tempest/lib/services/compute/services_client.py
@@ -29,7 +29,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listServices
+        https://developer.openstack.org/api-ref/compute/#list-compute-services
         """
         url = 'os-services'
         if params:
@@ -45,7 +45,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#enableScheduling
+        https://developer.openstack.org/api-ref/compute/#enable-scheduling-for-a-compute-service
         """
         post_body = json.dumps(kwargs)
         resp, body = self.put('os-services/enable', post_body)
@@ -58,7 +58,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#disableScheduling
+        https://developer.openstack.org/api-ref/compute/#disable-scheduling-for-a-compute-service
         """
         post_body = json.dumps(kwargs)
         resp, body = self.put('os-services/disable', post_body)
diff --git a/tempest/lib/services/compute/snapshots_client.py b/tempest/lib/services/compute/snapshots_client.py
index fde5288..df8d6fb 100644
--- a/tempest/lib/services/compute/snapshots_client.py
+++ b/tempest/lib/services/compute/snapshots_client.py
@@ -29,7 +29,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createSnapshot
+        https://developer.openstack.org/api-ref/compute/#create-snapshot
         """
         post_body = {
             'volume_id': volume_id
@@ -49,6 +49,12 @@
         return rest_client.ResponseBody(resp, body)
 
     def list_snapshots(self, detail=False, params=None):
+        """List snapshots.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#list-snapshots
+        """
         url = 'os-snapshots'
 
         if detail:
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index b2052c3..75984ec 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -12,10 +12,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import re
-
 from oslo_serialization import jsonutils as json
-from six.moves import urllib
 
 from tempest.lib.api_schema.response.compute.v2_1 import versions as schema
 from tempest.lib.common import rest_client
@@ -24,19 +21,6 @@
 
 class VersionsClient(base_compute_client.BaseComputeClient):
 
-    def _get_base_version_url(self):
-        # NOTE: The URL which is got from keystone's catalog contains
-        # API version and project-id like "/app-name/v2/{project-id}" or
-        # "/v2/{project-id}", but we need to access the URL which doesn't
-        # contain API version for getting API versions. For that, here
-        # should use raw_request() instead of get().
-        endpoint = self.base_url
-        url = urllib.parse.urlsplit(endpoint)
-        new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
-        url = list(url)
-        url[2] = new_path + '/'
-        return urllib.parse.urlunsplit(url)
-
     def list_versions(self):
         version_url = self._get_base_version_url()
         resp, body = self.raw_request(version_url, 'GET')
diff --git a/tempest/lib/services/compute/volumes_client.py b/tempest/lib/services/compute/volumes_client.py
index b75f22e..95cdd53 100644
--- a/tempest/lib/services/compute/volumes_client.py
+++ b/tempest/lib/services/compute/volumes_client.py
@@ -29,7 +29,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#listVolumes
+        https://developer.openstack.org/api-ref/compute/#list-volumes
+        https://developer.openstack.org/api-ref/compute/#list-volumes-with-details
         """
         url = 'os-volumes'
 
@@ -48,7 +49,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#showVolume
+        https://developer.openstack.org/api-ref/compute/#show-volume-details
         """
         url = "os-volumes/%s" % volume_id
         resp, body = self.get(url)
@@ -61,7 +62,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#createVolume
+        https://developer.openstack.org/api-ref/compute/#create-volume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('os-volumes', post_body)
@@ -74,7 +75,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-compute-v2.1.html#deleteVolume
+        https://developer.openstack.org/api-ref/compute/#delete-volume
         """
         resp, body = self.delete("os-volumes/%s" % volume_id)
         self.validate_response(schema.delete_volume, resp, body)
diff --git a/tempest/lib/services/identity/v2/roles_client.py b/tempest/lib/services/identity/v2/roles_client.py
index 635d013..9e841dd 100644
--- a/tempest/lib/services/identity/v2/roles_client.py
+++ b/tempest/lib/services/identity/v2/roles_client.py
@@ -24,7 +24,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#createRole
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#create-a-role
         """
         post_body = json.dumps({'role': kwargs})
         resp, body = self.post('OS-KSADM/roles', post_body)
@@ -37,9 +37,9 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-identity-v2-ext.html#showRoleByID
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#show-a-role
         OR
-        http://developer.openstack.org/api-ref-identity-v2-ext.html#showRoleByName
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#show-role-information-by-name
         """
         resp, body = self.get('OS-KSADM/roles/%s' % role_id_or_name)
         self.expected_success(200, resp.status)
@@ -51,7 +51,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#listRoles
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#list-all-roles
         """
         url = 'OS-KSADM/roles'
         if params:
@@ -66,7 +66,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#deleteRole
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#delete-a-role
         """
         resp, body = self.delete('OS-KSADM/roles/%s' % role_id)
         self.expected_success(204, resp.status)
@@ -77,7 +77,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#grantRoleToUserOnTenant
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#grant-roles-to-user-on-tenant
         """
         resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
                               (tenant_id, user_id, role_id), "")
@@ -101,7 +101,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#revokeRoleFromUserOnTenant
+        https://developer.openstack.org/api-ref/identity/v2-ext/index.html#revoke-role-from-user-on-tenant
         """
         resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
                                  (tenant_id, user_id, role_id))
diff --git a/tempest/lib/services/identity/v2/services_client.py b/tempest/lib/services/identity/v2/services_client.py
index b3f94aa..47398db 100644
--- a/tempest/lib/services/identity/v2/services_client.py
+++ b/tempest/lib/services/identity/v2/services_client.py
@@ -26,7 +26,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/identity/v2-ext/?expanded=#create-service-admin-extension
+        http://developer.openstack.org/api-ref/identity/v2-ext/#create-service-admin-extension
         """
         post_body = json.dumps({'OS-KSADM:service': kwargs})
         resp, body = self.post('/OS-KSADM/services', post_body)
@@ -47,7 +47,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/identity/v2-ext/?expanded=#list-services-admin-extension
+        http://developer.openstack.org/api-ref/identity/v2-ext/#list-services-admin-extension
         """
         url = '/OS-KSADM/services'
         if params:
diff --git a/tempest/lib/services/identity/v2/tenants_client.py b/tempest/lib/services/identity/v2/tenants_client.py
index b687332..026db64 100644
--- a/tempest/lib/services/identity/v2/tenants_client.py
+++ b/tempest/lib/services/identity/v2/tenants_client.py
@@ -39,7 +39,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#deleteTenant
+        https://developer.openstack.org/api-ref/identity/v2-admin/index.html#delete-tenant
         """
         resp, body = self.delete('tenants/%s' % str(tenant_id))
         self.expected_success(204, resp.status)
@@ -50,7 +50,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#admin-showTenantById
+        https://developer.openstack.org/api-ref/identity/v2-admin/index.html#show-tenant-details-by-id
         """
         resp, body = self.get('tenants/%s' % str(tenant_id))
         self.expected_success(200, resp.status)
diff --git a/tempest/lib/services/identity/v2/users_client.py b/tempest/lib/services/identity/v2/users_client.py
index f20fdc4..cfd97bb 100644
--- a/tempest/lib/services/identity/v2/users_client.py
+++ b/tempest/lib/services/identity/v2/users_client.py
@@ -50,7 +50,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-identity-admin-v2.html#admin-showUser
+        https://developer.openstack.org/api-ref/identity/v2-admin/index.html#show-user-details-admin-endpoint
         """
         resp, body = self.get("users/%s" % user_id)
         self.expected_success(200, resp.status)
@@ -62,7 +62,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-identity-admin-v2.html#admin-deleteUser
+        https://developer.openstack.org/api-ref/identity/v2-admin/index.html#delete-user-admin-endpoint
         """
         resp, body = self.delete("users/%s" % user_id)
         self.expected_success(204, resp.status)
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 8058d51..88801e7 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -30,9 +30,10 @@
 from tempest.lib.services.identity.v3.token_client import V3TokenClient
 from tempest.lib.services.identity.v3.trusts_client import TrustsClient
 from tempest.lib.services.identity.v3.users_client import UsersClient
+from tempest.lib.services.identity.v3.versions_client import VersionsClient
 
 __all__ = ['CredentialsClient', 'DomainsClient', 'EndPointsClient',
            'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
            'PoliciesClient', 'ProjectsClient', 'RegionsClient',
            'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
-           'V3TokenClient', 'TrustsClient', 'UsersClient', ]
+           'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']
diff --git a/tempest/lib/services/identity/v3/endpoints_client.py b/tempest/lib/services/identity/v3/endpoints_client.py
index c4c0d8d..91592de 100644
--- a/tempest/lib/services/identity/v3/endpoints_client.py
+++ b/tempest/lib/services/identity/v3/endpoints_client.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#endpoints-v3
+https://developer.openstack.org/api-ref/identity/v3/index.html#service-catalog-and-endpoints
 """
 
 from oslo_serialization import jsonutils as json
diff --git a/tempest/lib/services/identity/v3/groups_client.py b/tempest/lib/services/identity/v3/groups_client.py
index 5e68939..bc6ead0 100644
--- a/tempest/lib/services/identity/v3/groups_client.py
+++ b/tempest/lib/services/identity/v3/groups_client.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#groups-v3
+https://developer.openstack.org/api-ref/identity/v3/index.html#groups
 """
 
 from oslo_serialization import jsonutils as json
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/policies_client.py b/tempest/lib/services/identity/v3/policies_client.py
index 0282745..d4560e2 100644
--- a/tempest/lib/services/identity/v3/policies_client.py
+++ b/tempest/lib/services/identity/v3/policies_client.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#policies-v3
+https://developer.openstack.org/api-ref/identity/v3/index.html#policies
 """
 
 from oslo_serialization import jsonutils as json
diff --git a/tempest/lib/services/identity/v3/regions_client.py b/tempest/lib/services/identity/v3/regions_client.py
index 33c754a..d7507cf 100644
--- a/tempest/lib/services/identity/v3/regions_client.py
+++ b/tempest/lib/services/identity/v3/regions_client.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#regions-v3
+https://developer.openstack.org/api-ref/identity/v3/index.html#regions
 """
 
 from oslo_serialization import jsonutils as json
diff --git a/tempest/lib/services/identity/v3/role_assignments_client.py b/tempest/lib/services/identity/v3/role_assignments_client.py
index 10de03f..a426e69 100644
--- a/tempest/lib/services/identity/v3/role_assignments_client.py
+++ b/tempest/lib/services/identity/v3/role_assignments_client.py
@@ -26,7 +26,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/identity/v3/?expanded=list-effective-role-assignments-detail
+        http://developer.openstack.org/api-ref/identity/v3/#list-role-assignments
 
         :param effective: If True, returns the effective assignments, including
                           any assignments gained by virtue of group membership
diff --git a/tempest/lib/services/identity/v3/services_client.py b/tempest/lib/services/identity/v3/services_client.py
index 14c81cc..17b0f24 100644
--- a/tempest/lib/services/identity/v3/services_client.py
+++ b/tempest/lib/services/identity/v3/services_client.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 """
-http://developer.openstack.org/api-ref-identity-v3.html#service-catalog-v3
+https://developer.openstack.org/api-ref/identity/v3/index.html#service-catalog-and-endpoints
 """
 
 from oslo_serialization import jsonutils as json
diff --git a/tempest/lib/services/identity/v3/versions_client.py b/tempest/lib/services/identity/v3/versions_client.py
new file mode 100644
index 0000000..441ee0d
--- /dev/null
+++ b/tempest/lib/services/identity/v3/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 = "v3"
+
+    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/image/v1/images_client.py b/tempest/lib/services/image/v1/images_client.py
index 03f4c4b..faafb4a 100644
--- a/tempest/lib/services/image/v1/images_client.py
+++ b/tempest/lib/services/image/v1/images_client.py
@@ -61,7 +61,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-image-v1.html#createImage-v1
+        https://developer.openstack.org/api-ref/image/v1/index.html#create-image
         """
         if headers is None:
             headers = {}
@@ -79,7 +79,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-image-v1.html#updateImage-v1
+        https://developer.openstack.org/api-ref/image/v1/index.html#update-image
         """
         if headers is None:
             headers = {}
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 ac8b569..a7f8c39 100644
--- a/tempest/lib/services/image/v2/namespace_tags_client.py
+++ b/tempest/lib/services/image/v2/namespace_tags_client.py
@@ -115,5 +115,11 @@
         """
         url = 'metadefs/namespaces/%s/tags' % namespace
         resp, _ = self.delete(url)
-        self.expected_success(200, resp.status)
+
+        # NOTE(rosmaita): Bug 1656183 fixed the success response code for
+        # this call to make it consistent with the other metadefs delete
+        # calls.  Accept both codes in case tempest is being run against
+        # an old Glance.
+        self.expected_success([200, 204], resp.status)
+
         return rest_client.ResponseBody(resp)
diff --git a/tempest/lib/services/image/v2/resource_types_client.py b/tempest/lib/services/image/v2/resource_types_client.py
index 1b6889f..13259d1 100644
--- a/tempest/lib/services/image/v2/resource_types_client.py
+++ b/tempest/lib/services/image/v2/resource_types_client.py
@@ -26,7 +26,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?expanded=#list-resource-types
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#list-resource-types
         """
         url = 'metadefs/resource_types'
         resp, body = self.get(url)
@@ -39,7 +39,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?expanded=#create-resource-type-association
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#create-resource-type-association
         """
         url = 'metadefs/namespaces/%s/resource_types' % namespace_id
         data = json.dumps(kwargs)
@@ -53,7 +53,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?expanded=#list-resource-type-associations
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#list-resource-type-associations
         """
         url = 'metadefs/namespaces/%s/resource_types' % namespace_id
         resp, body = self.get(url)
@@ -66,7 +66,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?expanded=#remove-resource-type-association
+        http://developer.openstack.org/api-ref/image/v2/metadefs-index.html#remove-resource-type-association
         """
         url = 'metadefs/namespaces/%s/resource_types/%s' % (namespace_id,
                                                             resource_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/network/ports_client.py b/tempest/lib/services/network/ports_client.py
index 93138b9..daa15d7 100644
--- a/tempest/lib/services/network/ports_client.py
+++ b/tempest/lib/services/network/ports_client.py
@@ -73,7 +73,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/networking/v2/index.html?expanded=#bulk-create-ports
+        http://developer.openstack.org/api-ref/networking/v2/index.html#bulk-create-ports
         """
         uri = '/ports'
         return self.create_resource(uri, kwargs)
diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py
index ab5eefd..2b5e82d 100644
--- a/tempest/lib/services/volume/v2/backups_client.py
+++ b/tempest/lib/services/volume/v2/backups_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-blockstorage-v2.html#createBackup
+        https://developer.openstack.org/api-ref/block-storage/v2/index.html#create-backup
         """
         post_body = json.dumps({'backup': kwargs})
         resp, body = self.post('backups', post_body)
@@ -41,7 +41,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-blockstorage-v2.html#restoreBackup
+        https://developer.openstack.org/api-ref/block-storage/v2/index.html#restore-backup
         """
         post_body = json.dumps({'restore': kwargs})
         resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
diff --git a/tempest/lib/services/volume/v2/capabilities_client.py b/tempest/lib/services/volume/v2/capabilities_client.py
index b6de5b9..40cb8bf 100644
--- a/tempest/lib/services/volume/v2/capabilities_client.py
+++ b/tempest/lib/services/volume/v2/capabilities_client.py
@@ -19,6 +19,7 @@
 
 
 class CapabilitiesClient(rest_client.RestClient):
+    api_version = "v2"
 
     def show_backend_capabilities(self, host):
         """Shows capabilities for a storage back end.
diff --git a/tempest/lib/services/volume/v2/qos_client.py b/tempest/lib/services/volume/v2/qos_client.py
index 40d4a3f..47d3914 100644
--- a/tempest/lib/services/volume/v2/qos_client.py
+++ b/tempest/lib/services/volume/v2/qos_client.py
@@ -43,9 +43,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/index.html
-                                ?expanded=create-qos-specification-detail
-                                #quality-of-service-qos-specifications-qos-specs
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-qos-specification
         """
         post_body = json.dumps({'qos_specs': kwargs})
         resp, body = self.post('qos-specs', post_body)
@@ -81,9 +79,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/index.html
-                            ?expanded=set-keys-in-qos-specification-detail
-                            #quality-of-service-qos-specifications-qos-specs
+        http://developer.openstack.org/api-ref/block-storage/v2/#set-keys-in-qos-specification
         """
         put_body = json.dumps({"qos_specs": kwargs})
         resp, body = self.put('qos-specs/%s' % qos_id, put_body)
@@ -98,9 +94,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/index.html
-                            ?expanded=unset-keys-in-qos-specification-detail
-                            #quality-of-service-qos-specifications-qos-specs
+        http://developer.openstack.org/api-ref/block-storage/v2/#unset-keys-in-qos-specification
         """
         put_body = json.dumps({'keys': keys})
         resp, body = self.put('qos-specs/%s/delete_keys' % qos_id, put_body)
diff --git a/tempest/lib/services/volume/v2/quotas_client.py b/tempest/lib/services/volume/v2/quotas_client.py
index 430957d..e4b2895 100644
--- a/tempest/lib/services/volume/v2/quotas_client.py
+++ b/tempest/lib/services/volume/v2/quotas_client.py
@@ -49,7 +49,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateQuota
+        https://developer.openstack.org/api-ref/block-storage/v2/index.html#update-quotas
         """
         put_body = jsonutils.dumps({'quota_set': kwargs})
         resp, body = self.put('os-quota-sets/%s' % tenant_id, put_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..3f56f82 100644
--- a/tempest/lib/services/volume/v2/scheduler_stats_client.py
+++ b/tempest/lib/services/volume/v2/scheduler_stats_client.py
@@ -19,6 +19,7 @@
 
 
 class SchedulerStatsClient(rest_client.RestClient):
+    api_version = "v2"
 
     def list_pools(self, detail=False):
         """List all the volumes pools (hosts).
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index e670216..727afd6 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
@@ -635,13 +635,14 @@
                                             private_key=private_key)
         if dev_name is not None:
             ssh_client.make_fs(dev_name)
-            ssh_client.mount(dev_name, mount_path)
+            ssh_client.exec_command('sudo mount /dev/%s %s' % (dev_name,
+                                                               mount_path))
         cmd_timestamp = 'sudo sh -c "date > %s/timestamp; sync"' % mount_path
         ssh_client.exec_command(cmd_timestamp)
         timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
                                             % mount_path)
         if dev_name is not None:
-            ssh_client.umount(mount_path)
+            ssh_client.exec_command('sudo umount %s' % mount_path)
         return timestamp
 
     def get_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
@@ -653,7 +654,7 @@
         timestamp = ssh_client.exec_command('sudo cat %s/timestamp'
                                             % mount_path)
         if dev_name is not None:
-            ssh_client.umount(mount_path)
+            ssh_client.exec_command('sudo umount %s' % mount_path)
         return timestamp
 
     def get_server_ip(self, server):
@@ -731,36 +732,6 @@
                         network['id'])
         return network
 
-    def _list_networks(self, *args, **kwargs):
-        """List networks using admin creds """
-        networks_list = self.admin_manager.networks_client.list_networks(
-            *args, **kwargs)
-        return networks_list['networks']
-
-    def _list_subnets(self, *args, **kwargs):
-        """List subnets using admin creds """
-        subnets_list = self.admin_manager.subnets_client.list_subnets(
-            *args, **kwargs)
-        return subnets_list['subnets']
-
-    def _list_routers(self, *args, **kwargs):
-        """List routers using admin creds """
-        routers_list = self.admin_manager.routers_client.list_routers(
-            *args, **kwargs)
-        return routers_list['routers']
-
-    def _list_ports(self, *args, **kwargs):
-        """List ports using admin creds """
-        ports_list = self.admin_manager.ports_client.list_ports(
-            *args, **kwargs)
-        return ports_list['ports']
-
-    def _list_agents(self, *args, **kwargs):
-        """List agents using admin creds """
-        agents_list = self.admin_manager.network_agents_client.list_agents(
-            *args, **kwargs)
-        return agents_list['agents']
-
     def _create_subnet(self, network, subnets_client=None,
                        routers_client=None, namestart='subnet-smoke',
                        **kwargs):
@@ -779,7 +750,8 @@
             :returns: True if subnet with cidr already exist in tenant
                   False else
             """
-            cidr_in_use = self._list_subnets(tenant_id=tenant_id, cidr=cidr)
+            cidr_in_use = self.admin_manager.subnets_client.list_subnets(
+                tenant_id=tenant_id, cidr=cidr)['subnets']
             return len(cidr_in_use) != 0
 
         ip_version = kwargs.pop('ip_version', 4)
@@ -827,7 +799,8 @@
         return subnet
 
     def _get_server_port_id_and_ip4(self, server, ip_addr=None):
-        ports = self._list_ports(device_id=server['id'], fixed_ip=ip_addr)
+        ports = self.admin_manager.ports_client.list_ports(
+            device_id=server['id'], fixed_ip=ip_addr)['ports']
         # A port can have more than one IP address in some cases.
         # If the network is dual-stack (IPv4 + IPv6), this port is associated
         # with 2 subnets
@@ -856,7 +829,8 @@
         return port_map[0]
 
     def _get_network_by_name(self, network_name):
-        net = self._list_networks(name=network_name)
+        net = self.admin_manager.networks_client.list_networks(
+            name=network_name)['networks']
         self.assertNotEqual(len(net), 0,
                             "Unable to get network by name: %s" % network_name)
         return net[0]
@@ -939,7 +913,7 @@
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         try:
-            for net_name, ip_addresses in server['addresses'].items():
+            for ip_addresses in server['addresses'].values():
                 for ip_address in ip_addresses:
                     self.check_vm_connectivity(ip_address['addr'],
                                                username,
@@ -953,14 +927,15 @@
 
     def _check_remote_connectivity(self, source, dest, should_succeed=True,
                                    nic=None):
-        """check ping server via source ssh connection
+        """assert ping server via source ssh connection
+
+        Note: This is an internal method.  Use check_remote_connectivity
+        instead.
 
         :param source: RemoteClient: an ssh connection from which to ping
         :param dest: and IP to ping against
         :param should_succeed: boolean should ping succeed or not
         :param nic: specific network interface to ping from
-        :returns: boolean -- should_succeed == ping
-        :returns: ping is false if ping failed
         """
         def ping_remote():
             try:
@@ -975,6 +950,25 @@
                                           CONF.validation.ping_timeout,
                                           1)
 
+    def check_remote_connectivity(self, source, dest, should_succeed=True,
+                                  nic=None):
+        """assert ping server via source ssh connection
+
+        :param source: RemoteClient: an ssh connection from which to ping
+        :param dest: and IP to ping against
+        :param should_succeed: boolean should ping succeed or not
+        :param nic: specific network interface to ping from
+        """
+        result = self._check_remote_connectivity(source, dest, should_succeed,
+                                                 nic)
+        source_host = source.ssh_client.host
+        if should_succeed:
+            msg = "Timed out waiting for %s to become reachable from %s" \
+                % (dest, source_host)
+        else:
+            msg = "%s is reachable from %s" % (dest, source_host)
+        self.assertTrue(result, msg)
+
     def _create_security_group(self, security_group_rules_client=None,
                                tenant_id=None,
                                namestart='secgroup-smoke',
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 95c2d32..cefa119 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
@@ -82,7 +82,7 @@
         aggregate = self.aggregates_client.set_metadata(aggregate['id'],
                                                         metadata=meta)
 
-        for key, value in meta.items():
+        for key in meta.keys():
             self.assertEqual(meta[key],
                              aggregate['aggregate']['metadata'][key])
 
@@ -96,6 +96,7 @@
         return aggregate
 
     @decorators.idempotent_id('cb2b4c4f-0c7c-4164-bdde-6285b302a081')
+    @test.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 da29485..a05b1b1 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -62,6 +62,7 @@
         self.nova_volume_detach(server, attached_volume)
 
     @decorators.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
+    @test.attr(type='slow')
     @test.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_luks(self):
         server = self.launch_instance()
@@ -71,6 +72,7 @@
         self.attach_detach_volume(server, volume)
 
     @decorators.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
+    @test.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_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 27c45cb..5fee801 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -94,7 +94,7 @@
             raise exceptions.TimeoutException(msg)
 
     def _get_floating_ip_in_server_addresses(self, floating_ip, server):
-        for network_name, addresses in server['addresses'].items():
+        for addresses in server['addresses'].values():
             for address in addresses:
                 if (address['OS-EXT-IPS:type'] == 'floating' and
                         address['addr'] == floating_ip['ip']):
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 1196659..6665fa7 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -104,6 +104,7 @@
         return body['OS-EXT-SRV-ATTR:host']
 
     @decorators.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
         keypair = self.create_keypair()
@@ -129,6 +130,7 @@
             server, keypair, floating_ip)
 
     @decorators.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_rebuild(self):
         keypair = self.create_keypair()
@@ -143,6 +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')
     @test.services('compute', 'network')
     def test_server_connectivity_pause_unpause(self):
         keypair = self.create_keypair()
@@ -160,6 +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')
     @test.services('compute', 'network')
     def test_server_connectivity_suspend_resume(self):
         keypair = self.create_keypair()
@@ -177,6 +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')
     @test.services('compute', 'network')
     def test_server_connectivity_resize(self):
         resize_flavor = CONF.compute.flavor_ref_alt
@@ -200,6 +205,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_cold_migration(self):
         keypair = self.create_keypair()
@@ -225,6 +231,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
+    @test.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 4dae564..15a0a70 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()
 
@@ -127,23 +126,23 @@
         via checking the result of list_[networks,routers,subnets]
         """
 
-        seen_nets = self._list_networks()
-        seen_names = [n['name'] for n in seen_nets]
-        seen_ids = [n['id'] for n in seen_nets]
+        seen_nets = self.admin_manager.networks_client.list_networks()
+        seen_names = [n['name'] for n in seen_nets['networks']]
+        seen_ids = [n['id'] for n in seen_nets['networks']]
         self.assertIn(self.network['name'], seen_names)
         self.assertIn(self.network['id'], seen_ids)
 
         if self.subnet:
-            seen_subnets = self._list_subnets()
-            seen_net_ids = [n['network_id'] for n in seen_subnets]
-            seen_subnet_ids = [n['id'] for n in seen_subnets]
+            seen_subnets = self.admin_manager.subnets_client.list_subnets()
+            seen_net_ids = [n['network_id'] for n in seen_subnets['subnets']]
+            seen_subnet_ids = [n['id'] for n in seen_subnets['subnets']]
             self.assertIn(self.network['id'], seen_net_ids)
             self.assertIn(self.subnet['id'], seen_subnet_ids)
 
         if self.router:
-            seen_routers = self._list_routers()
-            seen_router_ids = [n['id'] for n in seen_routers]
-            seen_router_names = [n['name'] for n in seen_routers]
+            seen_routers = self.admin_manager.routers_client.list_routers()
+            seen_router_ids = [n['id'] for n in seen_routers['routers']]
+            seen_router_names = [n['name'] for n in seen_routers['routers']]
             self.assertIn(self.router['name'],
                           seen_router_names)
             self.assertIn(self.router['id'],
@@ -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
@@ -240,7 +241,8 @@
             ip_address, private_key=private_key)
         old_nic_list = self._get_server_nics(ssh_client)
         # get a port from a list of one item
-        port_list = self._list_ports(device_id=server['id'])
+        port_list = self.admin_manager.ports_client.list_ports(
+            device_id=server['id'])['ports']
         self.assertEqual(1, len(port_list))
         old_port = port_list[0]
         interface = self.interface_client.create_interface(
@@ -253,9 +255,12 @@
                         server['id'], interface['port_id'])
 
         def check_ports():
-            self.new_port_list = [port for port in
-                                  self._list_ports(device_id=server['id'])
-                                  if port['id'] != old_port['id']]
+            self.new_port_list = [
+                port for port in
+                self.admin_manager.ports_client.list_ports(
+                    device_id=server['id'])['ports']
+                if port['id'] != old_port['id']
+            ]
             return len(self.new_port_list) == 1
 
         if not test_utils.call_until_true(
@@ -281,14 +286,14 @@
                                               % 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'])
+        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)
 
     def _get_server_nics(self, ssh_client):
         reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
-        ipatxt = ssh_client.get_ip_list()
+        ipatxt = ssh_client.exec_command("ip address")
         return reg.findall(ipatxt)
 
     def _check_network_internal_connectivity(self, network,
@@ -301,10 +306,13 @@
         floating_ip, server = self.floating_ip_tuple
         # get internal ports' ips:
         # get all network ports in the new network
-        internal_ips = (p['fixed_ips'][0]['ip_address'] for p in
-                        self._list_ports(tenant_id=server['tenant_id'],
-                                         network_id=network['id'])
-                        if p['device_owner'].startswith('network'))
+        internal_ips = (
+            p['fixed_ips'][0]['ip_address'] for p in
+            self.admin_manager.ports_client.list_ports(
+                tenant_id=server['tenant_id'],
+                network_id=network['id'])['ports']
+            if p['device_owner'].startswith('network')
+        )
 
         self._check_server_connectivity(floating_ip,
                                         internal_ips,
@@ -320,8 +328,11 @@
         # We ping the external IP from the instance using its floating IP
         # which is always IPv4, so we must only test connectivity to
         # external IPv4 IPs if the external network is dualstack.
-        v4_subnets = [s for s in self._list_subnets(
-            network_id=CONF.network.public_network_id) if s['ip_version'] == 4]
+        v4_subnets = [
+            s for s in self.admin_manager.subnets_client.list_subnets(
+                network_id=CONF.network.public_network_id)['subnets']
+            if s['ip_version'] == 4
+        ]
         self.assertEqual(1, len(v4_subnets),
                          "Found %d IPv4 subnets" % len(v4_subnets))
 
@@ -337,20 +348,8 @@
             ip_address, private_key=private_key)
 
         for remote_ip in address_list:
-            if should_connect:
-                msg = ("Timed out waiting for %s to become "
-                       "reachable") % remote_ip
-            else:
-                msg = "ip address %s is reachable" % remote_ip
-            try:
-                self.assertTrue(self._check_remote_connectivity
-                                (ssh_source, remote_ip, should_connect),
-                                msg)
-            except Exception:
-                LOG.exception("Unable to access {dest} via ssh to "
-                              "floating-ip {src}".format(dest=remote_ip,
-                                                         src=floating_ip))
-                raise
+            self.check_remote_connectivity(ssh_source, remote_ip,
+                                           should_connect)
 
     @test.attr(type='smoke')
     @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
@@ -408,6 +407,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')
     @test.services('compute', 'network')
     def test_mtu_sized_frames(self):
         """Validate that network MTU sized frames fit through."""
@@ -420,6 +420,7 @@
                       'Connectivity can only be tested when in a '
                       'multitenant network environment')
     @decorators.skip_because(bug="1610994")
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
         """Test connectivity between VMs on different networks
@@ -495,6 +496,7 @@
     @testtools.skipIf(CONF.network.shared_physical_network,
                       'Router state can be altered only with multitenant '
                       'networks capabilities')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_update_router_admin_state(self):
         """Test to update admin state up of router
@@ -528,6 +530,7 @@
                       'network isolation not available')
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_subnet_details(self):
         """Tests that subnet's extra configuration details are affecting VMs.
@@ -594,7 +597,8 @@
             # NOTE(amuller): we are renewing the lease as part of the retry
             # because Neutron updates dnsmasq asynchronously after the
             # subnet-update API call returns.
-            ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
+            ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'],
+                                   dhcp_client=CONF.scenario.dhcp_client)
             if ssh_client.get_dns_servers() != [alt_dns_server]:
                 LOG.debug("Failed to update DNS nameservers")
                 return False
@@ -610,6 +614,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')
     @test.services('compute', 'network')
     def test_update_instance_port_admin_state(self):
         """Test to update admin_state_up attribute of instance port
@@ -624,7 +629,8 @@
         self._setup_network_and_servers()
         floating_ip, server = self.floating_ip_tuple
         server_id = server['id']
-        port_id = self._list_ports(device_id=server_id)[0]['id']
+        port_id = self.admin_manager.ports_client.list_ports(
+            device_id=server_id)['ports'][0]['id']
         server_pip = server['addresses'][self.network['name']][0]['addr']
 
         server2 = self._create_server(self.network)
@@ -637,23 +643,24 @@
         self.check_public_network_connectivity(
             should_connect=True, msg="before updating "
             "admin_state_up of instance port to False")
-        self._check_remote_connectivity(ssh_client, dest=server_pip,
-                                        should_succeed=True)
+        self.check_remote_connectivity(ssh_client, dest=server_pip,
+                                       should_succeed=True)
         self.ports_client.update_port(port_id, admin_state_up=False)
         self.check_public_network_connectivity(
             should_connect=False, msg="after updating "
             "admin_state_up of instance port to False",
             should_check_floating_ip_status=False)
-        self._check_remote_connectivity(ssh_client, dest=server_pip,
-                                        should_succeed=False)
+        self.check_remote_connectivity(ssh_client, dest=server_pip,
+                                       should_succeed=False)
         self.ports_client.update_port(port_id, admin_state_up=True)
         self.check_public_network_connectivity(
             should_connect=True, msg="after updating "
             "admin_state_up of instance port to True")
-        self._check_remote_connectivity(ssh_client, dest=server_pip,
-                                        should_succeed=True)
+        self.check_remote_connectivity(ssh_client, dest=server_pip,
+                                       should_succeed=True)
 
     @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_preserve_preexisting_port(self):
         """Test preserve pre-existing port
@@ -677,8 +684,8 @@
                              'Server should have been created from a '
                              'pre-existing port.')
         # Assert the port is bound to the server.
-        port_list = self._list_ports(device_id=server['id'],
-                                     network_id=self.network['id'])
+        port_list = self.admin_manager.ports_client.list_ports(
+            device_id=server['id'], network_id=self.network['id'])['ports']
         self.assertEqual(1, len(port_list),
                          'There should only be one port created for '
                          'server %s.' % server['id'])
@@ -696,8 +703,8 @@
         # Boot another server with the same port to make sure nothing was
         # left around that could cause issues.
         server = self._create_server(self.network, port['id'])
-        port_list = self._list_ports(device_id=server['id'],
-                                     network_id=self.network['id'])
+        port_list = self.admin_manager.ports_client.list_ports(
+            device_id=server['id'], network_id=self.network['id'])['ports']
         self.assertEqual(1, len(port_list),
                          'There should only be one port created for '
                          'server %s.' % server['id'])
@@ -705,6 +712,7 @@
 
     @test.requires_ext(service='network', extension='l3_agent_scheduler')
     @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
+    @test.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.
@@ -727,9 +735,11 @@
         unschedule_router = (self.admin_manager.network_agents_client.
                              delete_router_from_l3_agent)
 
-        agent_list_alive = set(a["id"] for a in
-                               self._list_agents(agent_type="L3 agent") if
-                               a["alive"] is True)
+        agent_list_alive = set(
+            a["id"] for a in
+            self.admin_manager.network_agents_client.list_agents(
+                agent_type="L3 agent")['agents'] if a["alive"] is True
+        )
         self._setup_network_and_servers()
 
         # NOTE(kevinbenton): we have to use the admin credentials to check
@@ -782,6 +792,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')
     @test.services('compute', 'network')
     def test_port_security_macspoofing_port(self):
         """Tests port_security extension enforces mac spoofing
@@ -811,8 +822,8 @@
         self._create_new_network()
         self._hotplug_server()
         fip, server = self.floating_ip_tuple
-        new_ports = self._list_ports(device_id=server["id"],
-                                     network_id=self.new_net["id"])
+        new_ports = self.admin_manager.ports_client.list_ports(
+            device_id=server["id"], network_id=self.new_net["id"])['ports']
         spoof_port = new_ports[0]
         private_key = self._get_server_key(server)
         ssh_client = self.get_remote_client(fip['floating_ip_address'],
@@ -820,15 +831,15 @@
         spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
         peer = self._create_server(self.new_net)
         peer_address = peer['addresses'][self.new_net['name']][0]['addr']
-        self._check_remote_connectivity(ssh_client, dest=peer_address,
-                                        nic=spoof_nic, should_succeed=True)
+        self.check_remote_connectivity(ssh_client, dest=peer_address,
+                                       nic=spoof_nic, should_succeed=True)
         ssh_client.set_mac_address(spoof_nic, spoof_mac)
         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,
-                                        nic=spoof_nic, should_succeed=False)
+        self.check_remote_connectivity(ssh_client, dest=peer_address,
+                                       nic=spoof_nic, should_succeed=False)
         self.ports_client.update_port(spoof_port["id"],
                                       port_security_enabled=False,
                                       security_groups=[])
-        self._check_remote_connectivity(ssh_client, dest=peer_address,
-                                        nic=spoof_nic, should_succeed=True)
+        self.check_remote_connectivity(ssh_client, dest=peer_address,
+                                       nic=spoof_nic, should_succeed=True)
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 2d6ea75..cfd83d0 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,12 +105,12 @@
                             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):
         ips = {'4': None, '6': []}
-        for net_name, nics in srv['addresses'].items():
+        for nics in srv['addresses'].values():
             for nic in nics:
                 if nic['version'] == 6:
                     ips['6'].append(nic['addr'])
@@ -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,14 +140,18 @@
 
         @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._list_ports(device_id=sid,
-                                  network_id=self.network_v6['id'])]
+        ports = [
+            p["mac_address"] for p in
+            self.admin_manager.ports_client.list_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))
 
@@ -162,16 +164,17 @@
         sshv4_2, ips_from_api_2, sid2 = self.prepare_server(networks=net_list)
 
         def guest_has_address(ssh, addr):
-            return addr in ssh.get_ip_list()
+            return addr in ssh.exec_command("ip address")
 
         # 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.get_ip_list()
-        ips_from_ip_2 = sshv4_2.get_ip_list()
+        ips_from_ip_1 = sshv4_1.exec_command("ip address")
+        ips_from_ip_2 = sshv4_2.exec_command("ip address")
         self.assertIn(ips_from_api_1['4'], ips_from_ip_1)
         self.assertIn(ips_from_api_2['4'], ips_from_ip_2)
         for i in range(n_subnets6):
@@ -189,25 +192,18 @@
             self.assertTrue(test_utils.call_until_true(srv2_v6_addr_assigned,
                             CONF.validation.ping_timeout, 1))
 
-        self._check_connectivity(sshv4_1, ips_from_api_2['4'])
-        self._check_connectivity(sshv4_2, ips_from_api_1['4'])
+        self.check_remote_connectivity(sshv4_1, ips_from_api_2['4'])
+        self.check_remote_connectivity(sshv4_2, ips_from_api_1['4'])
 
         for i in range(n_subnets6):
-            self._check_connectivity(sshv4_1,
-                                     ips_from_api_2['6'][i])
-            self._check_connectivity(sshv4_1,
-                                     self.subnets_v6[i]['gateway_ip'])
-            self._check_connectivity(sshv4_2,
-                                     ips_from_api_1['6'][i])
-            self._check_connectivity(sshv4_2,
-                                     self.subnets_v6[i]['gateway_ip'])
-
-    def _check_connectivity(self, source, dest):
-        self.assertTrue(
-            self._check_remote_connectivity(source, dest),
-            "Timed out waiting for %s to become reachable from %s" %
-            (dest, source.ssh_client.host)
-        )
+            self.check_remote_connectivity(sshv4_1,
+                                           ips_from_api_2['6'][i])
+            self.check_remote_connectivity(sshv4_1,
+                                           self.subnets_v6[i]['gateway_ip'])
+            self.check_remote_connectivity(sshv4_2,
+                                           ips_from_api_1['6'][i])
+            self.check_remote_connectivity(sshv4_2,
+                                           self.subnets_v6[i]['gateway_ip'])
 
     @test.attr(type='slow')
     @decorators.idempotent_id('2c92df61-29f0-4eaa-bee3-7c65bef62a43')
@@ -245,6 +241,7 @@
     def test_dualnet_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless', dualnet=True)
 
+    @test.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 c989e01..7fd8c91 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -46,6 +46,7 @@
         self.delete_container(container_name)
 
     @decorators.idempotent_id('916c7111-cb1f-44b2-816d-8f760e4ea910')
+    @test.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 5565cb8..72b61c8 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
@@ -220,22 +220,24 @@
         # Checks that we see the newly created network/subnet/router via
         # checking the result of list_[networks,routers,subnets]
         # Check that (router, subnet) couple exist in port_list
-        seen_nets = self._list_networks()
-        seen_names = [n['name'] for n in seen_nets]
-        seen_ids = [n['id'] for n in seen_nets]
+        seen_nets = self.admin_manager.networks_client.list_networks()
+        seen_names = [n['name'] for n in seen_nets['networks']]
+        seen_ids = [n['id'] for n in seen_nets['networks']]
 
         self.assertIn(tenant.network['name'], seen_names)
         self.assertIn(tenant.network['id'], seen_ids)
 
-        seen_subnets = [(n['id'], n['cidr'], n['network_id'])
-                        for n in self._list_subnets()]
+        seen_subnets = [
+            (n['id'], n['cidr'], n['network_id']) for n in
+            self.admin_manager.subnets_client.list_subnets()['subnets']
+        ]
         mysubnet = (tenant.subnet['id'], tenant.subnet['cidr'],
                     tenant.network['id'])
         self.assertIn(mysubnet, seen_subnets)
 
-        seen_routers = self._list_routers()
-        seen_router_ids = [n['id'] for n in seen_routers]
-        seen_router_names = [n['name'] for n in seen_routers]
+        seen_routers = self.admin_manager.routers_client.list_routers()
+        seen_router_ids = [n['id'] for n in seen_routers['routers']]
+        seen_router_names = [n['name'] for n in seen_routers['routers']]
 
         self.assertIn(tenant.router['name'], seen_router_names)
         self.assertIn(tenant.router['id'], seen_router_ids)
@@ -243,9 +245,11 @@
         myport = (tenant.router['id'], tenant.subnet['id'])
         router_ports = [
             (i['device_id'], f['subnet_id'])
-            for i in self._list_ports(device_id=tenant.router['id'])
+            for i in self.admin_manager.ports_client.list_ports(
+                device_id=tenant.router['id'])['ports']
             if net_info.is_router_interface_port(i)
-            for f in i['fixed_ips']]
+            for f in i['fixed_ips']
+        ]
 
         self.assertIn(myport, router_ports)
 
@@ -364,20 +368,12 @@
             access_point_ssh, private_key=private_key)
         return access_point_ssh
 
-    def _check_connectivity(self, access_point, ip, should_succeed=True):
-        if should_succeed:
-            msg = "Timed out waiting for %s to become reachable" % ip
-        else:
-            msg = "%s is reachable" % ip
-        self.assertTrue(self._check_remote_connectivity(access_point, ip,
-                                                        should_succeed), msg)
-
     def _test_in_tenant_block(self, tenant):
         access_point_ssh = self._connect_to_access_point(tenant)
         for server in tenant.servers:
-            self._check_connectivity(access_point=access_point_ssh,
-                                     ip=self._get_server_ip(server),
-                                     should_succeed=False)
+            self.check_remote_connectivity(source=access_point_ssh,
+                                           dest=self._get_server_ip(server),
+                                           should_succeed=False)
 
     def _test_in_tenant_allow(self, tenant):
         ruleset = dict(
@@ -392,8 +388,8 @@
         )
         access_point_ssh = self._connect_to_access_point(tenant)
         for server in tenant.servers:
-            self._check_connectivity(access_point=access_point_ssh,
-                                     ip=self._get_server_ip(server))
+            self.check_remote_connectivity(source=access_point_ssh,
+                                           dest=self._get_server_ip(server))
 
     def _test_cross_tenant_block(self, source_tenant, dest_tenant):
         # if public router isn't defined, then dest_tenant access is via
@@ -401,8 +397,8 @@
         access_point_ssh = self._connect_to_access_point(source_tenant)
         ip = self._get_server_ip(dest_tenant.access_point,
                                  floating=self.floating_ip_access)
-        self._check_connectivity(access_point=access_point_ssh, ip=ip,
-                                 should_succeed=False)
+        self.check_remote_connectivity(source=access_point_ssh, dest=ip,
+                                       should_succeed=False)
 
     def _test_cross_tenant_allow(self, source_tenant, dest_tenant):
         """check for each direction:
@@ -423,7 +419,7 @@
         access_point_ssh = self._connect_to_access_point(source_tenant)
         ip = self._get_server_ip(dest_tenant.access_point,
                                  floating=self.floating_ip_access)
-        self._check_connectivity(access_point_ssh, ip)
+        self.check_remote_connectivity(access_point_ssh, ip)
 
         # test that reverse traffic is still blocked
         self._test_cross_tenant_block(dest_tenant, source_tenant)
@@ -440,7 +436,7 @@
         access_point_ssh_2 = self._connect_to_access_point(dest_tenant)
         ip = self._get_server_ip(source_tenant.access_point,
                                  floating=self.floating_ip_access)
-        self._check_connectivity(access_point_ssh_2, ip)
+        self.check_remote_connectivity(access_point_ssh_2, ip)
 
     def _verify_mac_addr(self, tenant):
         """Verify that VM has the same ip, mac as listed in port"""
@@ -450,7 +446,8 @@
         mac_addr = mac_addr.strip().lower()
         # Get the fixed_ips and mac_address fields of all ports. Select
         # only those two columns to reduce the size of the response.
-        port_list = self._list_ports(fields=['fixed_ips', 'mac_address'])
+        port_list = self.admin_manager.ports_client.list_ports(
+            fields=['fixed_ips', 'mac_address'])['ports']
         port_detail_list = [
             (port['fixed_ips'][0]['subnet_id'],
              port['fixed_ips'][0]['ip_address'],
@@ -497,6 +494,7 @@
             raise
 
     @decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_port_update_new_security_group(self):
         """Verifies the traffic after updating the vm port
@@ -532,24 +530,26 @@
         # Check connectivity failure with default security group
         try:
             access_point_ssh = self._connect_to_access_point(new_tenant)
-            self._check_connectivity(access_point=access_point_ssh,
-                                     ip=self._get_server_ip(server),
-                                     should_succeed=False)
+            self.check_remote_connectivity(source=access_point_ssh,
+                                           dest=self._get_server_ip(server),
+                                           should_succeed=False)
             server_id = server['id']
-            port_id = self._list_ports(device_id=server_id)[0]['id']
+            port_id = self.admin_manager.ports_client.list_ports(
+                device_id=server_id)['ports'][0]['id']
 
             # update port with new security group and check connectivity
             self.ports_client.update_port(port_id, security_groups=[
                 new_tenant.security_groups['new_sg']['id']])
-            self._check_connectivity(
-                access_point=access_point_ssh,
-                ip=self._get_server_ip(server))
+            self.check_remote_connectivity(
+                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)
             raise
 
     @decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
+    @test.attr(type='slow')
     @test.services('compute', 'network')
     def test_multiple_security_groups(self):
         """Verify multiple security groups and checks that rules
@@ -581,6 +581,7 @@
                                    private_key=private_key,
                                    should_connect=True)
 
+    @test.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
     @test.services('compute', 'network')
@@ -598,28 +599,30 @@
 
         access_point_ssh = self._connect_to_access_point(new_tenant)
         server_id = server['id']
-        port_id = self._list_ports(device_id=server_id)[0]['id']
+        port_id = self.admin_manager.ports_client.list_ports(
+            device_id=server_id)['ports'][0]['id']
 
         # Flip the port's port security and check connectivity
         try:
             self.ports_client.update_port(port_id,
                                           port_security_enabled=True,
                                           security_groups=[])
-            self._check_connectivity(access_point=access_point_ssh,
-                                     ip=self._get_server_ip(server),
-                                     should_succeed=False)
+            self.check_remote_connectivity(source=access_point_ssh,
+                                           dest=self._get_server_ip(server),
+                                           should_succeed=False)
 
             self.ports_client.update_port(port_id,
                                           port_security_enabled=False,
                                           security_groups=[])
-            self._check_connectivity(
-                access_point=access_point_ssh,
-                ip=self._get_server_ip(server))
+            self.check_remote_connectivity(
+                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)
             raise
 
+    @test.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
     @testtools.skipUnless(
@@ -642,7 +645,8 @@
         sec_groups = []
         server = self._create_server(name, tenant, sec_groups)
         server_id = server['id']
-        ports = self._list_ports(device_id=server_id)
+        ports = self.admin_manager.ports_client.list_ports(
+            device_id=server_id)['ports']
         self.assertEqual(1, len(ports))
         for port in ports:
             self.assertEmpty(port['security_groups'],
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 4d9e59c..1960e9a 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -48,6 +48,7 @@
         cls.set_network_resources()
         super(TestServerAdvancedOps, cls).setup_credentials()
 
+    @test.attr(type='slow')
     @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
@@ -69,37 +70,22 @@
         waiters.wait_for_server_status(self.servers_client, instance_id,
                                        'ACTIVE')
 
+    @test.attr(type='slow')
     @decorators.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
     @test.services('compute')
     def test_server_sequence_suspend_resume(self):
         # We create an instance for use in this test
-        instance = self.create_server()
-        instance_id = instance['id']
-        LOG.debug("Suspending instance %s. Current status: %s",
-                  instance_id, instance['status'])
-        self.servers_client.suspend_server(instance_id)
-        waiters.wait_for_server_status(self.servers_client, instance_id,
-                                       'SUSPENDED')
-        fetched_instance = (self.servers_client.show_server(instance_id)
-                            ['server'])
-        LOG.debug("Resuming instance %s. Current status: %s",
-                  instance_id, fetched_instance['status'])
-        self.servers_client.resume_server(instance_id)
-        waiters.wait_for_server_status(self.servers_client, instance_id,
-                                       'ACTIVE')
-        fetched_instance = (self.servers_client.show_server(instance_id)
-                            ['server'])
-        LOG.debug("Suspending instance %s. Current status: %s",
-                  instance_id, fetched_instance['status'])
-        self.servers_client.suspend_server(instance_id)
-        waiters.wait_for_server_status(self.servers_client, instance_id,
-                                       'SUSPENDED')
-        fetched_instance = (self.servers_client.show_server(instance_id)
-                            ['server'])
-        LOG.debug("Resuming instance %s. Current status: %s",
-                  instance_id, fetched_instance['status'])
-        self.servers_client.resume_server(instance_id)
-        waiters.wait_for_server_status(self.servers_client, instance_id,
-                                       'ACTIVE')
+        instance_id = self.create_server()['id']
+
+        for _ in range(2):
+            LOG.debug("Suspending instance %s", instance_id)
+            self.servers_client.suspend_server(instance_id)
+            waiters.wait_for_server_status(self.servers_client, instance_id,
+                                           'SUSPENDED')
+
+            LOG.debug("Resuming instance %s", instance_id)
+            self.servers_client.resume_server(instance_id)
+            waiters.wait_for_server_status(self.servers_client, instance_id,
+                                           'ACTIVE')
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 75cef88..9e763f8 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -74,6 +74,7 @@
                                         private_key=keypair['private_key'])
         self.assertEqual(timestamp, timestamp2)
 
+    @test.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.')
@@ -81,6 +82,7 @@
     def test_shelve_instance(self):
         self._create_server_then_shelve_and_unshelve()
 
+    @test.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 6dedd1d..a699de2 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -41,6 +41,7 @@
             raise cls.skipException("Snapshotting is not available.")
 
     @decorators.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
+    @test.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 ef9664d..96b423d 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
@@ -88,6 +88,8 @@
                                           CONF.compute.build_interval):
             raise lib_exc.TimeoutException
 
+    @test.attr(type='slow')
+    @decorators.skip_because(bug="1664793")
     @decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
                           'Snapshotting is not available.')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 9c33b71..ae0230e 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
@@ -43,16 +43,13 @@
         return self.create_volume(name=vol_name, imageRef=img_uuid)
 
     def _get_bdm(self, source_id, source_type, delete_on_termination=False):
-        # NOTE(gfidente): the syntax for block_device_mapping is
-        # dev_name=id:type:size:delete_on_terminate
-        # where type needs to be "snap" if the server is booted
-        # from a snapshot, size instead can be safely left empty
-
-        bd_map = [{
-            'device_name': 'vda',
-            '{}_id'.format(source_type): source_id,
-            'delete_on_termination': str(int(delete_on_termination))}]
-        return {'block_device_mapping': bd_map}
+        bd_map_v2 = [{
+            'uuid': source_id,
+            'source_type': source_type,
+            'destination_type': 'volume',
+            'boot_index': 0,
+            'delete_on_termination': delete_on_termination}]
+        return {'block_device_mapping_v2': bd_map_v2}
 
     def _boot_instance_from_resource(self, source_id,
                                      source_type,
@@ -98,7 +95,6 @@
         waiters.wait_for_server_termination(self.servers_client, server['id'])
 
     @decorators.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
-    @test.attr(type='smoke')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
     @test.services('compute', 'volume', 'image')
@@ -180,6 +176,7 @@
         self.assertEqual(timestamp, timestamp3)
 
     @decorators.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
+    @test.attr(type='slow')
     @test.services('compute', 'image', 'volume')
     def test_create_server_from_volume_snapshot(self):
         # Create a volume from an image
@@ -236,14 +233,3 @@
 
         # delete instance
         self._delete_server(instance)
-
-
-class TestVolumeBootPatternV2(TestVolumeBootPattern):
-    def _get_bdm(self, source_id, source_type, delete_on_termination=False):
-        bd_map_v2 = [{
-            'uuid': source_id,
-            'source_type': source_type,
-            'destination_type': 'volume',
-            'boot_index': 0,
-            'delete_on_termination': delete_on_termination}]
-        return {'block_device_mapping_v2': bd_map_v2}
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 891e22d..f580ea6 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -91,6 +91,7 @@
         waiters.wait_for_volume_retype(self.volumes_client,
                                        volume_id, new_volume_type)
 
+    @test.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/test.py b/tempest/test.py
index 06de520..52994ac 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -31,7 +31,6 @@
 from tempest import config
 from tempest import exceptions
 from tempest.lib.common import cred_client
-from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
@@ -644,12 +643,11 @@
             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 assertNotEmpty(self, list, msg=None):
+        if msg is None:
+            msg = "list is empty."
         self.assertGreater(len(list), 0, msg)
-
-
-call_until_true = debtcollector.moves.moved_function(
-    test_utils.call_until_true, 'call_until_true', __name__,
-    version='Newton', removal_version='Ocata')
diff --git a/tempest/test_discover/plugins.py b/tempest/test_discover/plugins.py
index abe2b73..276cf3c 100644
--- a/tempest/test_discover/plugins.py
+++ b/tempest/test_discover/plugins.py
@@ -46,10 +46,41 @@
         """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
 
@@ -124,7 +155,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_subunit_describe_calls.py b/tempest/tests/cmd/test_subunit_describe_calls.py
index 1c24c37..5f3d770 100644
--- a/tempest/tests/cmd/test_subunit_describe_calls.py
+++ b/tempest/tests/cmd/test_subunit_describe_calls.py
@@ -33,6 +33,16 @@
         p.communicate()
         self.assertEqual(0, p.returncode)
 
+    def test_return_code_no_output(self):
+        subunit_file = os.path.join(
+            os.path.dirname(os.path.abspath(__file__)),
+            'sample_streams/calls.subunit')
+        p = subprocess.Popen([
+            'subunit-describe-calls', '-s', subunit_file],
+            stdin=subprocess.PIPE)
+        p.communicate()
+        self.assertEqual(0, p.returncode)
+
     def test_parse(self):
         subunit_file = os.path.join(
             os.path.dirname(os.path.abspath(__file__)),
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 5be6229..48cb86b 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -67,16 +67,6 @@
         self.ssh_mock = self.useFixture(mockpatch.PatchObject(self.conn,
                                                               'ssh_client'))
 
-    def test_get_hostname(self):
-        self.ssh_mock.mock.exec_command.return_value = 'fake_hostname'
-        self.assertEqual(self.conn.get_hostname(), 'fake_hostname')
-
-    def test_get_ram_size(self):
-        free_output = "Mem:         48294      45738       2555          0" \
-                      "402      40346"
-        self.ssh_mock.mock.exec_command.return_value = free_output
-        self.assertEqual(self.conn.get_ram_size_in_mb(), '48294')
-
     def test_write_to_console_regular_str(self):
         self.conn.write_to_console('test')
         self._assert_exec_called_with(
@@ -102,11 +92,6 @@
         cmd = "set -eu -o pipefail; PATH=$PATH:/sbin; " + cmd
         self.ssh_mock.mock.exec_command.assert_called_with(cmd)
 
-    def test_get_number_of_vcpus(self):
-        self.ssh_mock.mock.exec_command.return_value = '16'
-        self.assertEqual(self.conn.get_number_of_vcpus(), 16)
-        self._assert_exec_called_with('grep -c ^processor /proc/cpuinfo')
-
     def test_get_disks(self):
         output_lsblk = """\
 NAME       MAJ:MIN    RM          SIZE RO TYPE MOUNTPOINT
@@ -154,23 +139,6 @@
         self._assert_exec_called_with(
             "ip addr | awk '/ether/ {print $2}'")
 
-    def test_get_ip_list(self):
-        ips = """1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
-    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-    inet 127.0.0.1/8 scope host lo
-    inet6 ::1/128 scope host
-       valid_lft forever preferred_lft forever
-2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
-    link/ether fa:16:3e:6e:26:3b brd ff:ff:ff:ff:ff:ff
-    inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0
-    inet6 fd55:faaf:e1ab:3d9:f816:3eff:fe6e:263b/64 scope global dynamic
-       valid_lft 2591936sec preferred_lft 604736sec
-    inet6 fe80::f816:3eff:fe6e:263b/64 scope link
-       valid_lft forever preferred_lft forever"""
-        self.ssh_mock.mock.exec_command.return_value = ips
-        self.assertEqual(self.conn.get_ip_list(), ips)
-        self._assert_exec_called_with('ip address')
-
     def test_assign_static_ip(self):
         self.ssh_mock.mock.exec_command.return_value = ''
         ip = '10.0.0.2'
@@ -214,7 +182,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/lib/common/utils/linux/__init__.py b/tempest/tests/lib/common/utils/linux/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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/common/utils/test_data_utils.py b/tempest/tests/lib/common/utils/test_data_utils.py
index 4446e5c..8bdf70e 100644
--- a/tempest/tests/lib/common/utils/test_data_utils.py
+++ b/tempest/tests/lib/common/utils/test_data_utils.py
@@ -37,16 +37,20 @@
         actual2 = data_utils.rand_uuid_hex()
         self.assertNotEqual(actual, actual2)
 
-    def test_rand_name(self):
-        actual = data_utils.rand_name()
+    def test_rand_name_with_default_prefix(self):
+        actual = data_utils.rand_name('foo')
         self.assertIsInstance(actual, str)
-        actual2 = data_utils.rand_name()
+        self.assertTrue(actual.startswith('tempest-foo'))
+        actual2 = data_utils.rand_name('foo')
+        self.assertTrue(actual2.startswith('tempest-foo'))
         self.assertNotEqual(actual, actual2)
 
-        actual = data_utils.rand_name('foo')
+    def test_rand_name_with_none_prefix(self):
+        actual = data_utils.rand_name('foo', prefix=None)
+        self.assertIsInstance(actual, str)
         self.assertTrue(actual.startswith('foo'))
-        actual2 = data_utils.rand_name('foo')
-        self.assertTrue(actual.startswith('foo'))
+        actual2 = data_utils.rand_name('foo', prefix=None)
+        self.assertTrue(actual2.startswith('foo'))
         self.assertNotEqual(actual, actual2)
 
     def test_rand_name_with_prefix(self):
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 b563ab2..8d391c1 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -1,4 +1,5 @@
 # Copyright 2015 IBM Corp.
+# Copyright 2017 AT&T Corp.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
@@ -14,6 +15,9 @@
 
 import copy
 
+import mock
+
+from tempest.lib.services.compute import base_compute_client
 from tempest.lib.services.compute import servers_client
 from tempest.tests.lib import fake_auth_provider
 from tempest.tests.lib.services import base
@@ -186,6 +190,9 @@
     FAKE_REBUILD_SERVER = copy.deepcopy(FAKE_SERVER_GET)
     FAKE_REBUILD_SERVER['server']['adminPass'] = 'fake-admin-pass'
 
+    FAKE_TAGS = ["foo", "bar"]
+    REPLACE_FAKE_TAGS = ["baz", "qux"]
+
     server_id = FAKE_SERVER_GET['server']['id']
     network_id = 'a6b0875b-6b5d-4a5a-81eb-0c3aa62e5fdb'
 
@@ -194,6 +201,7 @@
         fake_auth = fake_auth_provider.FakeAuthProvider()
         self.client = servers_client.ServersClient(
             fake_auth, 'compute', 'regionOne')
+        self.addCleanup(mock.patch.stopall)
 
     def test_list_servers_with_str_body(self):
         self._test_list_servers()
@@ -1031,3 +1039,113 @@
             {'security_groups': self.FAKE_SECURITY_GROUPS},
             server_id=self.server_id,
             )
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_list_tags_str_body(self, _):
+        self._test_list_tags()
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_list_tags_byte_body(self, _):
+        self._test_list_tags(bytes_body=True)
+
+    def _test_list_tags(self, bytes_body=False):
+        expected = {"tags": self.FAKE_TAGS}
+        self.check_service_client_function(
+            self.client.list_tags,
+            'tempest.lib.common.rest_client.RestClient.get',
+            expected,
+            server_id=self.server_id,
+            to_utf=bytes_body)
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_update_all_tags_str_body(self, _):
+        self._test_update_all_tags()
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_update_all_tags_byte_body(self, _):
+        self._test_update_all_tags(bytes_body=True)
+
+    def _test_update_all_tags(self, bytes_body=False):
+        expected = {"tags": self.REPLACE_FAKE_TAGS}
+        self.check_service_client_function(
+            self.client.update_all_tags,
+            'tempest.lib.common.rest_client.RestClient.put',
+            expected,
+            server_id=self.server_id,
+            tags=self.REPLACE_FAKE_TAGS,
+            to_utf=bytes_body)
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_delete_all_tags(self, _):
+        self.check_service_client_function(
+            self.client.delete_all_tags,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            server_id=self.server_id,
+            status=204)
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_check_tag_existence_str_body(self, _):
+        self._test_check_tag_existence()
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_check_tag_existence_byte_body(self, _):
+        self._test_check_tag_existence(bytes_body=True)
+
+    def _test_check_tag_existence(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.check_tag_existence,
+            'tempest.lib.common.rest_client.RestClient.get',
+            {},
+            server_id=self.server_id,
+            tag=self.FAKE_TAGS[0],
+            status=204,
+            to_utf=bytes_body)
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_update_tag_str_body(self, _):
+        self._test_update_tag()
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_update_tag_byte_body(self, _):
+        self._test_update_tag(bytes_body=True)
+
+    def _test_update_tag(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_tag,
+            'tempest.lib.common.rest_client.RestClient.put',
+            {},
+            server_id=self.server_id,
+            tag=self.FAKE_TAGS[0],
+            status=201,
+            headers={'location': 'fake_location'},
+            to_utf=bytes_body)
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_delete_tag_str_body(self, _):
+        self._test_delete_tag()
+
+    @mock.patch.object(base_compute_client, 'COMPUTE_MICROVERSION',
+                       new_callable=mock.PropertyMock(return_value='2.26'))
+    def test_delete_tag_byte_body(self, _):
+        self._test_delete_tag(bytes_body=True)
+
+    def _test_delete_tag(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.delete_tag,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            server_id=self.server_id,
+            tag=self.FAKE_TAGS[0],
+            status=204,
+            to_utf=bytes_body)
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_versions_client.py b/tempest/tests/lib/services/identity/v3/test_versions_client.py
new file mode 100644
index 0000000..3bfaf1e
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_versions_client.py
@@ -0,0 +1,70 @@
+# 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.identity.v3 import versions_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestIdentityClient(base.BaseServiceTest):
+
+    FAKE_VERSIONS_INFO = {
+        "versions": {
+            "values": [
+                {"status": "stable", "updated": "2017-02-22T00:00:00Z",
+                 "media-types": [
+                     {"base": "application/json", "type":
+                      "application/vnd.openstack.identity-v3+json"}
+                 ],
+                 "id": "v3.8",
+                 "links": [
+                     {"href": "https://15.184.67.226/identity_admin/v3/",
+                      "rel": "self"}
+                 ]},
+                {"status": "deprecated", "updated": "2016-08-04T00:00:00Z",
+                 "media-types": [
+                     {"base": "application/json",
+                      "type": "application/vnd.openstack.identity-v2.0+json"}
+                 ],
+                 "id": "v2.0",
+                 "links": [
+                     {"href": "https://15.184.67.226/identity_admin/v2.0/",
+                      "rel": "self"},
+                     {"href": "https://docs.openstack.org/",
+                      "type": "text/html", "rel": "describedby"}
+                 ]}
+            ]
+        }
+    }
+
+    def setUp(self):
+        super(TestIdentityClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = versions_client.VersionsClient(fake_auth,
+                                                     'identity',
+                                                     '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/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/test_decorators.py b/tempest/tests/test_decorators.py
index a069a81..ae2f2a3 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -199,3 +199,96 @@
                           self._test_requires_ext_helper,
                           extension='enabled_ext',
                           service='bad_service')
+
+
+class TestConfigDecorators(BaseDecoratorsTest):
+    def setUp(self):
+        super(TestConfigDecorators, self).setUp()
+        cfg.CONF.set_default('nova', True, 'service_available')
+        cfg.CONF.set_default('glance', False, 'service_available')
+
+    def _assert_skip_message(self, func, skip_msg):
+        try:
+            func()
+            self.fail()
+        except testtools.TestCase.skipException as skip_exc:
+            self.assertEqual(skip_exc.args[0], skip_msg)
+
+    def _test_skip_unless_config(self, expected_to_skip=True, *decorator_args):
+
+        class TestFoo(test.BaseTestCase):
+            @config.skip_unless_config(*decorator_args)
+            def test_bar(self):
+                return 0
+
+        t = TestFoo('test_bar')
+        if expected_to_skip:
+            self.assertRaises(testtools.TestCase.skipException, t.test_bar)
+            if (len(decorator_args) >= 3):
+                # decorator_args[2]: skip message specified
+                self._assert_skip_message(t.test_bar, decorator_args[2])
+        else:
+            try:
+                self.assertEqual(t.test_bar(), 0)
+            except testtools.TestCase.skipException:
+                # We caught a skipException but we didn't expect to skip
+                # this test so raise a hard test failure instead.
+                raise testtools.TestCase.failureException(
+                    "Not supposed to skip")
+
+    def _test_skip_if_config(self, expected_to_skip=True,
+                             *decorator_args):
+
+        class TestFoo(test.BaseTestCase):
+            @config.skip_if_config(*decorator_args)
+            def test_bar(self):
+                return 0
+
+        t = TestFoo('test_bar')
+        if expected_to_skip:
+            self.assertRaises(testtools.TestCase.skipException, t.test_bar)
+            if (len(decorator_args) >= 3):
+                # decorator_args[2]: skip message specified
+                self._assert_skip_message(t.test_bar, decorator_args[2])
+        else:
+            try:
+                self.assertEqual(t.test_bar(), 0)
+            except testtools.TestCase.skipException:
+                # We caught a skipException but we didn't expect to skip
+                # this test so raise a hard test failure instead.
+                raise testtools.TestCase.failureException(
+                    "Not supposed to skip")
+
+    def test_skip_unless_no_group(self):
+        self._test_skip_unless_config(True, 'fake_group', 'an_option')
+
+    def test_skip_unless_no_option(self):
+        self._test_skip_unless_config(True, 'service_available',
+                                      'not_an_option')
+
+    def test_skip_unless_false_option(self):
+        self._test_skip_unless_config(True, 'service_available', 'glance')
+
+    def test_skip_unless_false_option_msg(self):
+        self._test_skip_unless_config(True, 'service_available', 'glance',
+                                      'skip message')
+
+    def test_skip_unless_true_option(self):
+        self._test_skip_unless_config(False,
+                                      'service_available', 'nova')
+
+    def test_skip_if_no_group(self):
+        self._test_skip_if_config(False, 'fake_group', 'an_option')
+
+    def test_skip_if_no_option(self):
+        self._test_skip_if_config(False, 'service_available', 'not_an_option')
+
+    def test_skip_if_false_option(self):
+        self._test_skip_if_config(False, 'service_available', 'glance')
+
+    def test_skip_if_true_option(self):
+        self._test_skip_if_config(True, 'service_available', 'nova')
+
+    def test_skip_if_true_option_msg(self):
+        self._test_skip_if_config(True, 'service_available', 'nova',
+                                  'skip message')
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
deleted file mode 100644
index a4ef699..0000000
--- a/tempest/tests/test_wrappers.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import os
-import shutil
-import subprocess
-import tempfile
-
-import six
-
-from tempest.tests import base
-
-DEVNULL = open(os.devnull, 'wb')
-
-
-class TestWrappers(base.TestCase):
-    def setUp(self):
-        super(TestWrappers, self).setUp()
-        # Setup test dirs
-        self.directory = tempfile.mkdtemp(prefix='tempest-unit')
-        self.addCleanup(shutil.rmtree, self.directory)
-        self.test_dir = os.path.join(self.directory, 'tests')
-        os.mkdir(self.test_dir)
-        # Setup Test files
-        self.testr_conf_file = os.path.join(self.directory, '.testr.conf')
-        self.setup_cfg_file = os.path.join(self.directory, 'setup.cfg')
-        self.passing_file = os.path.join(self.test_dir, 'test_passing.py')
-        self.failing_file = os.path.join(self.test_dir, 'test_failing.py')
-        self.init_file = os.path.join(self.test_dir, '__init__.py')
-        self.setup_py = os.path.join(self.directory, 'setup.py')
-        shutil.copy('tempest/tests/files/testr-conf', self.testr_conf_file)
-        shutil.copy('tempest/tests/files/passing-tests', self.passing_file)
-        shutil.copy('tempest/tests/files/failing-tests', self.failing_file)
-        shutil.copy('setup.py', self.setup_py)
-        shutil.copy('tempest/tests/files/setup.cfg', self.setup_cfg_file)
-        shutil.copy('tempest/tests/files/__init__.py', self.init_file)
-        # copy over the pretty_tox scripts
-        shutil.copy('tools/pretty_tox.sh',
-                    os.path.join(self.directory, 'pretty_tox.sh'))
-        shutil.copy('tools/pretty_tox_serial.sh',
-                    os.path.join(self.directory, 'pretty_tox_serial.sh'))
-
-        self.stdout = six.StringIO()
-        self.stderr = six.StringIO()
-        # Change directory, run wrapper and check result
-        self.addCleanup(os.chdir, os.path.abspath(os.curdir))
-        os.chdir(self.directory)
-
-    def assertRunExit(self, cmd, expected):
-        p = subprocess.Popen(
-            "bash %s" % cmd, shell=True,
-            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        out, err = p.communicate()
-
-        self.assertEqual(
-            p.returncode, expected,
-            "Stdout: %s; Stderr: %s" % (out, err))
-
-    def test_pretty_tox(self):
-        # Git init is required for the pbr testr command. pbr requires a git
-        # version or an sdist to work. so make the test directory a git repo
-        # too.
-        subprocess.call(['git', 'init'], stderr=DEVNULL)
-        self.assertRunExit('pretty_tox.sh passing', 0)
-
-    def test_pretty_tox_fails(self):
-        # Git init is required for the pbr testr command. pbr requires a git
-        # version or an sdist to work. so make the test directory a git repo
-        # too.
-        subprocess.call(['git', 'init'], stderr=DEVNULL)
-        self.assertRunExit('pretty_tox.sh', 1)
-
-    def test_pretty_tox_serial(self):
-        self.assertRunExit('pretty_tox_serial.sh passing', 0)
-
-    def test_pretty_tox_serial_fails(self):
-        self.assertRunExit('pretty_tox_serial.sh', 1)
diff --git a/test-requirements.txt b/test-requirements.txt
index f7d63a8..13950bd 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,9 +1,9 @@
 # The order of packages is significant, because pip processes them in the order
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
-hacking<0.13,>=0.12.0 # Apache-2.0
+hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
 # needed for doc build
-sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
+sphinx>=1.5.1 # BSD
 oslosphinx>=4.7.0 # Apache-2.0
 reno>=1.8.0 # Apache-2.0
 mock>=2.0 # BSD
diff --git a/tools/pretty_tox.sh b/tools/pretty_tox.sh
deleted file mode 100755
index 0b83b91..0000000
--- a/tools/pretty_tox.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
-
-set -o pipefail
-
-TESTRARGS=$1
-python setup.py testr --testr-args="--subunit $TESTRARGS" | subunit-trace --no-failure-debug -f
-retval=$?
-# NOTE(mtreinish) The pipe above would eat the slowest display from pbr's testr
-# wrapper so just manually print the slowest tests.
-echo -e "\nSlowest Tests:\n"
-testr slowest
-exit $retval
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
deleted file mode 100755
index 1f8204e..0000000
--- a/tools/pretty_tox_serial.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-echo "WARNING: This script is deprecated and will be removed in the near future. Please migrate to tempest run or another method of launching a test runner"
-
-set -o pipefail
-
-TESTRARGS=$@
-
-if [ ! -d .testrepository ]; then
-    testr init
-fi
-testr run --subunit $TESTRARGS | subunit-trace -f -n
-retval=$?
-testr slowest
-
-exit $retval
diff --git a/tools/tox_install.sh b/tools/tox_install.sh
new file mode 100755
index 0000000..43468e4
--- /dev/null
+++ b/tools/tox_install.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+# Client constraint file contains this client version pin that is in conflict
+# with installing the client from source. We should remove the version pin in
+# the constraints file before applying it for from-source installation.
+
+CONSTRAINTS_FILE=$1
+shift 1
+
+set -e
+
+# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get
+# published to logs.openstack.org for easy debugging.
+localfile="$VIRTUAL_ENV/log/upper-constraints.txt"
+
+if [[ $CONSTRAINTS_FILE != http* ]]; then
+    CONSTRAINTS_FILE=file://$CONSTRAINTS_FILE
+fi
+# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep
+curl $CONSTRAINTS_FILE --insecure --progress-bar --output $localfile
+
+pip install -c$localfile openstack-requirements
+
+# This is the main purpose of the script: Allow local installation of
+# the current repo. It is listed in constraints file and thus any
+# install will be constrained and we need to unconstrain it.
+edit-constraints $localfile -- $CLIENT_NAME
+
+pip install -c$localfile -U $*
+exit $?
diff --git a/tox.ini b/tox.ini
index d8d390e..dfa8332 100644
--- a/tox.ini
+++ b/tox.ini
@@ -8,6 +8,8 @@
 setenv =
     VIRTUAL_ENV={envdir}
     OS_TEST_PATH=./tempest/test_discover
+    BRANCH_NAME=master
+    CLIENT_NAME=tempest
 deps =
     setuptools
     -r{toxinidir}/requirements.txt
@@ -17,9 +19,12 @@
     VIRTUAL_ENV={envdir}
     OS_TEST_PATH=./tempest/tests
     PYTHONWARNINGS=default::DeprecationWarning
-passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
+    BRANCH_NAME=master
+    CLIENT_NAME=tempest
+passenv = OS_STDOUT_CAPTURE OS_STDERR_CAPTURE OS_TEST_TIMEOUT OS_TEST_LOCK_PATH OS_TEST_PATH TEMPEST_CONFIG TEMPEST_CONFIG_DIR http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY ZUUL_CACHE_DIR REQUIREMENTS_PIP_LOCATION
 usedevelop = True
-install_command = pip install -U {opts} {packages}
+install_command =
+    {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
 whitelist_externals = *
 deps =
     -r{toxinidir}/requirements.txt
@@ -78,7 +83,8 @@
 # See the testrepository bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
     find . -type f -name "*.pyc" -delete
-    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))' {posargs}
+    tempest run --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.api)' {posargs}
+    tempest run --combine --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.scenario)' {posargs}
 
 [testenv:full-serial]
 envdir = .tox/tempest
@@ -91,6 +97,16 @@
     find . -type f -name "*.pyc" -delete
     tempest run --serial --regex '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario))' {posargs}
 
+[testenv:scenario]
+envdir = .tox/tempest
+sitepackages = {[tempestenv]sitepackages}
+setenv = {[tempestenv]setenv}
+deps = {[tempestenv]deps}
+# The regex below is used to select all scenario tests
+commands =
+    find . -type f -name "*.pyc" -delete
+    tempest run --serial --regex '(^tempest\.scenario)' {posargs}
+
 [testenv:smoke]
 envdir = .tox/tempest
 sitepackages = {[tempestenv]sitepackages}