Merge "Volume force-delete when volume in maintenance state"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 18269bf..2314222 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -9,6 +9,8 @@
 config file which explains the purpose of each individual option. You can see
 the sample config file here: :ref:`tempest-sampleconf`
 
+.. _tempest_cred_provider_conf:
+
 Test Credentials
 ----------------
 
@@ -232,6 +234,9 @@
 
 Enabling Remote Access to Created Servers
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. _tempest_conf_network_allocation:
+
 Network Creation/Usage for Servers
 """"""""""""""""""""""""""""""""""
 When Tempest creates servers for testing, some tests require being able to
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 896cd98..1264ecc 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -67,7 +67,8 @@
    HACKING
    REVIEWING
    microversion_testing
-   test-removal
+   test_removal
+   write_tests
 
 -------
 Plugins
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index 6b30825..b3af92f 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -1,3 +1,5 @@
+.. _tempest_plugin:
+
 =============================
 Tempest Test Plugin Interface
 =============================
diff --git a/doc/source/test-removal.rst b/doc/source/test_removal.rst
similarity index 100%
rename from doc/source/test-removal.rst
rename to doc/source/test_removal.rst
diff --git a/doc/source/write_tests.rst b/doc/source/write_tests.rst
new file mode 100644
index 0000000..768bf0f
--- /dev/null
+++ b/doc/source/write_tests.rst
@@ -0,0 +1,243 @@
+.. _tempest_test_writing:
+
+Tempest Test Writing Guide
+==========================
+
+This guide serves as a starting point for developers working on writing new
+Tempest tests. At a high level tests in Tempest are just tests that conform to
+the standard python `unit test`_ framework. But there are several aspects of
+that are unique to tempest and it's role as an integration test suite running
+against a real cloud.
+
+.. _unit test: https://docs.python.org/3.6/library/unittest.html
+
+.. note:: This guide is for writing tests in the tempest repository. While many
+          parts of this guide are also applicable to tempest plugins, not all
+          the APIs mentioned are considered stable or recommended for use in
+          plugins. Please refer to :ref:`tempest_plugin` for details about
+          writing plugins
+
+
+Adding a New TestCase
+=====================
+
+The base unit of testing in Tempest is the `TestCase`_ (also called the test
+class). Each TestCase contains test methods which are the individual tests that
+will be executed by the test runner. But, the TestCase is the smallest self
+contained unit for tests from the tempest perspective. It's also the level at
+which tempest is parallel safe. In other words, multiple TestCases can be
+executed in parallel, but individual test methods in the same TestCase can not.
+Also, all test methods within a TestCase are assumed to be executed serially. As
+such you can use the test case to store variables that are shared between
+methods.
+
+.. _TestCase: https://docs.python.org/3.6/library/unittest.html#unittest.TestCase
+
+In standard unittest the lifecycle of a TestCase can be described in the
+following phases:
+
+ #. setUpClass
+ #. setUp
+ #. Test Execution
+ #. tearDown
+ #. doCleanups
+ #. tearDownClass
+
+setUpClass
+----------
+
+The setUpClass phase is the first phase executed by the test runner and is used
+to perform any setup required for all the test methods to be executed. In
+Tempest this is a very important step and will automatically do the necessary
+setup for interacting with the configured cloud.
+
+To accomplish this you do **not** define a setUpClass function, instead there
+are a number of predefined phases to setUpClass that are used. The phases are:
+
+ * skip_checks
+ * setup_credentials
+ * setup_clients
+ * resource_setup
+
+which is executed in that order. An example of a TestCase which defines all
+of these would be::
+
+  from tempest import config
+  from tempest import test
+
+  CONF = config.CONF
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+    @classmethod
+    def skip_checks(cls):
+        """This section is used to evaluate config early and skip all test
+           methods based on these checks
+        """
+        super(TestExampleCase, cls).skip_checks()
+        if not CONF.section.foo
+            cls.skip('A helpful message')
+
+    @classmethod
+    def setup_credentials(cls):
+        """This section is used to do any manual credential allocation and also
+           in the case of dynamic credentials to override the default network
+           resource creation/auto allocation
+        """
+        # This call is used to tell the credential allocator to not create any
+        # network resources for this test case. It also enables selective
+        # creation of other neutron resources. NOTE: it must go before the
+        # super call
+        cls.set_network_resources()
+        super(TestExampleCase, cls).setup_credentials()
+
+    @classmethod
+    def setup_clients(cls):
+        """This section is used to setup client aliases from the manager object
+           or to initialize any additional clients. Except in a few very
+           specific situations you should not need to use this.
+        """
+        super(TestExampleCase, cls).setup_clients()
+        cls.servers_client = cls.os.servers_client
+
+    @classmethod
+    def resource_setup(cls):
+        """This section is used to create any resources or objects which are
+           going to be used and shared by **all** test methods in the
+           TestCase. Note then anything created in this section must also be
+           destroyed in the corresponding resource_cleanup() method (which will
+           be run during tearDownClass())
+        """
+        super(TestExampleCase, cls).resource_setup()
+        cls.shared_server = cls.servers_client.create_server(...)
+
+
+Allocating Credentials
+''''''''''''''''''''''
+
+Since Tempest tests are all about testing a running cloud, every test will need
+credentials to be able to make API requests against the cloud. Since this is
+critical to operation and, when running in parallel, easy to make a mistake,
+the base TestCase class will automatically allocate a regular user for each
+TestCase during the setup_credentials() phase. During this process it will also
+initialize a client manager object using those credentials, which will be your
+entry point into interacting with the cloud. For more details on how credentials
+are allocated the :ref:`tempest_cred_provider_conf` section of the Tempest
+Configuration Guide provides more details on the operation of this.
+
+There are some cases when you need more than a single set of credentials, or
+credentials with a more specialized set of roles. To accomplish this you have
+to set a class variable ``credentials`` on the TestCase directly. For example::
+
+    from tempest import test
+
+    class TestExampleAdmin(test.BaseTestCase):
+
+        credentials = ['primary', 'admin']
+
+    @classmethod
+    def skip_checks(cls):
+    ...
+
+In this example the ``TestExampleAdmin`` TestCase will allocate 2 sets of
+credentials, one regular user and one admin user. The corresponding manager
+objects will be set as class variables cls.os and cls.os_adm respectively. You
+can also allocate a second user by putting **'alt'** in the list too. A set of
+alt credentials are the same as primary but can be used for tests cases that
+need a second user/project.
+
+You can also specify credentials with specific roles assigned. This is useful
+for cases where there are specific RBAC requirements hard coded into an API.
+The canonical example of this are swift tests which often want to test swift's
+concepts of operator and reseller_admin. An actual example from tempest on how
+to do this is::
+
+    class PublicObjectTest(base.BaseObjectTest):
+
+        credentials = [['operator', CONF.object_storage.operator_role],
+                       ['operator_alt', CONF.object_storage.operator_role]]
+
+        @classmethod
+        def setup_credentials(cls):
+            super(PublicObjectTest, cls).setup_credentials()
+            ...
+
+In this case the manager objects will be set to ``cls.os_roles_operator`` and
+``cls.os_roles_operator_alt`` respectively.
+
+
+There is no limit to how many credentials you can allocate in this manner,
+however in almost every case you should **not** need more than 3 sets of
+credentials per test case.
+
+To figure out the mapping of manager objects set on the TestCase and the
+requested credentials you can reference:
+
++-------------------+---------------------+
+| Credentials Entry | Manager Variable    |
++===================+=====================+
+| primary           | cls.os              |
++-------------------+---------------------+
+| admin             | cls.os_adm          |
++-------------------+---------------------+
+| alt               | cls.os_alt          |
++-------------------+---------------------+
+| [$label, $role]   | cls.os_roles_$label |
++-------------------+---------------------+
+
+By default cls.os is available since it is allocated in the base tempest test
+class. (located in tempest/test.py) If your TestCase inherits from a different
+direct parent class (it'll still inherit from the BaseTestCase, just not
+directly) be sure to check if that class overrides allocated credentials.
+
+Dealing with Network Allocation
+'''''''''''''''''''''''''''''''
+
+When neutron is enabled and a testing requires networking this isn't normally
+automatically setup when a tenant is created. Since tempest needs isolated
+tenants to function properly it also needs to handle network allocation. By
+default the base test class will allocate a network, subnet, and router
+automatically. (this depends on the configured credential provider, for more
+details see: :ref:`tempest_conf_network_allocation`) However, there are
+situations where you do no need all of these resources allocated. (or your
+TestCase inherits from a class that overrides the default in tempest/test.py)
+There is a class level mechanism to override this allocation and specify which
+resources you need. To do this you need to call `cls.set_network_resources()`
+in the `setup_credentials()` method before the `super()`. For example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+  @classmethod
+  def setup_credentials(cls):
+      cls.set_network_resources(network=True, subnet=True, router=False)
+      super(TestExampleCase, cls).setup_credentials()
+
+There are 2 quirks with the usage here. First for the set_network_resources
+function to work properly it **must be called before super()**. This is so
+that children classes' settings are always used instead of a parent classes'.
+The other quirk here is that if you do not want to allocate any network
+resources for your test class simply call `set_network_resources()` without
+any arguments. For example::
+
+  from tempest import test
+
+
+  class TestExampleCase(test.BaseTestCase):
+
+  @classmethod
+  def setup_credentials(cls):
+      cls.set_network_resources()
+      super(TestExampleCase, cls).setup_credentials()
+
+This will not allocate any networking resources. This is because by default all
+the arguments default to False.
+
+It's also worth pointing out that it is common for base test classes for
+different services (and scenario tests) to override this setting. When
+inheriting from classes other than the base TestCase in tempest/test.py it is
+worth checking the immediate parent for what is set to determine if your
+class needs to override that setting.
diff --git a/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
new file mode 100644
index 0000000..6b45666
--- /dev/null
+++ b/releasenotes/notes/add-OAUTH-Consumer-Client-tempest-tests-db1df7aae4a9fd4e.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Add a new client to handle the OAUTH consumers feature from the identity API.
diff --git a/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml b/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
new file mode 100644
index 0000000..01136c6
--- /dev/null
+++ b/releasenotes/notes/add-additional-methods-to-roles-client-library-178d4a6000dec72d.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Add missing API call, list all role inference rules,
+    to the roles_client library. This feature enables the
+    possibility of listing all role inference rules in the
+    system.
diff --git a/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml b/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
new file mode 100644
index 0000000..848a21b
--- /dev/null
+++ b/releasenotes/notes/add-compute-server-evaculate-client-as-a-library-ed76baf25f02c3ca.yaml
@@ -0,0 +1,3 @@
+---
+features:
+    - Define the compute server evacuate client method in the servers_client library.
diff --git a/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml b/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
new file mode 100644
index 0000000..c95e77c
--- /dev/null
+++ b/releasenotes/notes/add-update-encryption-type-to-encryption-types-client-f3093532a0bcf9a1.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add update encryption type API to the v2 encryption_types_client library.
+    This feature enables the possibility to update an encryption type for an
+    existing volume type.
diff --git a/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml b/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
new file mode 100644
index 0000000..3453050
--- /dev/null
+++ b/releasenotes/notes/add-volume-manage-client-as-library-78ab198a1dc1bd41.yaml
@@ -0,0 +1,9 @@
+---
+features:
+  - |
+    Add the unmanage volume API service method in v2 volumes_client library.
+    Define v2 volume_manage_client client for the volume service as library
+    interfaces, allowing other projects to use this module as stable libraries
+    without maintenance changes.
+
+    * volume_manage_client(v2)
diff --git a/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml b/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
new file mode 100644
index 0000000..c3e43ee
--- /dev/null
+++ b/releasenotes/notes/deprecate-dvr_extra_resources-config-8c319d6dab7f7e5c.yaml
@@ -0,0 +1,7 @@
+---
+deprecations:
+  - |
+    The ``dvr_extra_resources`` configuration switch from the ``config`` module
+    is deprecated. It was added to support the Liberty Release which we don't
+    support anymore.
+
diff --git a/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml b/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
new file mode 100644
index 0000000..b4e4dd1
--- /dev/null
+++ b/releasenotes/notes/remove-deprecated-compute-validation-config-options-part-2-5cd17b6e0e6cb8a3.yaml
@@ -0,0 +1,11 @@
+---
+upgrade:
+  - |
+    Below deprecated config options from compute group have been removed.
+    Corresponding config options already been available in validation group.
+
+    - ``compute.image_ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``compute.ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``scenario.ssh_user`` (available as ``validation.image_ssh_user``)
+    - ``compute.network_for_ssh`` (available as ``validation.network_for_ssh``)
+    - ``compute.ping_timeout `` (available as ``validation.ping_timeout``)
diff --git a/requirements.txt b/requirements.txt
index 92825a7..7c934c2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,7 +10,7 @@
 testrepository>=0.0.18 # Apache-2.0/BSD
 oslo.concurrency>=3.8.0 # Apache-2.0
 oslo.config>=3.22.0 # Apache-2.0
-oslo.log>=3.11.0 # Apache-2.0
+oslo.log>=3.22.0 # Apache-2.0
 oslo.serialization>=1.10.0 # Apache-2.0
 oslo.utils>=3.20.0 # Apache-2.0
 six>=1.9.0 # MIT
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 984f1a9..22a5bc4 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -10,10 +10,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.api.compute import base
 from tempest.common import waiters
 from tempest import config
 from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
 from tempest import test
 
 CONF = config.CONF
@@ -41,6 +44,41 @@
         if not CONF.compute_feature_enabled.swap_volume:
             raise cls.skipException("Swapping volumes is not supported.")
 
+    def _wait_for_server_volume_swap(self, server_id, old_volume_id,
+                                     new_volume_id):
+        """Waits for a server to swap the old volume to a new one."""
+        volume_attachments = self.servers_client.list_volume_attachments(
+            server_id)['volumeAttachments']
+        attached_volume_ids = [attachment['volumeId']
+                               for attachment in volume_attachments]
+        start = int(time.time())
+
+        while (old_volume_id in attached_volume_ids) \
+                or (new_volume_id not in attached_volume_ids):
+            time.sleep(self.servers_client.build_interval)
+            volume_attachments = self.servers_client.list_volume_attachments(
+                server_id)['volumeAttachments']
+            attached_volume_ids = [attachment['volumeId']
+                                   for attachment in volume_attachments]
+
+            if int(time.time()) - start >= self.servers_client.build_timeout:
+                old_vol_bdm_status = 'in BDM' \
+                    if old_volume_id in attached_volume_ids else 'not in BDM'
+                new_vol_bdm_status = 'in BDM' \
+                    if new_volume_id in attached_volume_ids else 'not in BDM'
+                message = ('Failed to swap old volume %(old_volume_id)s '
+                           '(current %(old_vol_bdm_status)s) to new volume '
+                           '%(new_volume_id)s (current %(new_vol_bdm_status)s)'
+                           ' on server %(server_id)s within the required time '
+                           '(%(timeout)s s)' %
+                           {'old_volume_id': old_volume_id,
+                            'old_vol_bdm_status': old_vol_bdm_status,
+                            'new_volume_id': new_volume_id,
+                            'new_vol_bdm_status': new_vol_bdm_status,
+                            'server_id': server_id,
+                            'timeout': self.servers_client.build_timeout})
+                raise lib_exc.TimeoutException(message)
+
     @decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
     @test.services('volume')
     def test_volume_swap(self):
@@ -61,6 +99,8 @@
                                                 volume1['id'], 'available')
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume2['id'], 'in-use')
+        self._wait_for_server_volume_swap(server['id'], volume1['id'],
+                                          volume2['id'])
         # Verify "volume2" is attached to the server
         vol_attachments = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
@@ -74,6 +114,8 @@
                                                 volume2['id'], 'available')
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume1['id'], 'in-use')
+        self._wait_for_server_volume_swap(server['id'], volume2['id'],
+                                          volume1['id'])
         # Verify "volume1" is attached to the server
         vol_attachments = self.servers_client.list_volume_attachments(
             server['id'])['volumeAttachments']
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ef13eef..1736463 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -94,10 +94,7 @@
             cls.os.security_group_default_rules_client)
         cls.versions_client = cls.os.compute_versions_client
 
-        if CONF.volume_feature_enabled.api_v1:
-            cls.volumes_client = cls.os.volumes_client
-        else:
-            cls.volumes_client = cls.os.volumes_v2_client
+        cls.volumes_client = cls.os.volumes_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index b82fa3b..a50933b 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -14,12 +14,9 @@
 #    under the License.
 
 from tempest.api.compute.security_groups import base
-from tempest import config
 from tempest.lib import decorators
 from tempest import test
 
-CONF = config.CONF
-
 
 class SecurityGroupRulesTestJSON(base.BaseSecurityGroupsTest):
 
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 12eb5e1..1ad153a 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -48,23 +48,25 @@
             cls.fixed_network_name = None
         network_kwargs = fixed_network.set_networks_kwarg(network)
         cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
-        cls.s1 = cls.create_test_server(name=cls.s1_name,
-                                        wait_until='ACTIVE',
-                                        **network_kwargs)
+        cls.s1 = cls.create_test_server(name=cls.s1_name, **network_kwargs)
 
         cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
         # If image_ref_alt is "" or None then we still want to boot a server
         # but we rely on `testtools.skipUnless` decorator to actually skip
         # the irrelevant tests.
         cls.s2 = cls.create_test_server(
-            name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref,
-            wait_until='ACTIVE')
+            name=cls.s2_name, image_id=cls.image_ref_alt or cls.image_ref)
 
         cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
         cls.s3 = cls.create_test_server(name=cls.s3_name,
                                         flavor=cls.flavor_ref_alt,
                                         wait_until='ACTIVE')
 
+        waiters.wait_for_server_status(cls.client, cls.s1['id'],
+                                       'ACTIVE')
+        waiters.wait_for_server_status(cls.client, cls.s2['id'],
+                                       'ACTIVE')
+
     @decorators.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
     @testtools.skipUnless(CONF.compute.image_ref != CONF.compute.image_ref_alt,
                           "Need distinct images to run this test")
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index a72df5e..6354c57 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -13,14 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import socket
 import struct
 
 import six
-from six.moves.urllib import parse as urlparse
 import urllib3
 
 from tempest.api.compute import base
+from tempest.common import compute
 from tempest import config
 from tempest.lib import decorators
 
@@ -158,14 +157,6 @@
             self._websocket.response.find(b'Server: WebSockify') > 0,
             'Did not get the expected WebSocket HTTP Response.')
 
-    def _create_websocket(self, url):
-        url = urlparse.urlparse(url)
-        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        client_socket.connect((url.hostname, url.port))
-        # Turn the Socket into a WebSocket to do the communication
-        return _WebSocket(client_socket, url)
-
     @decorators.idempotent_id('c640fdff-8ab4-45a4-a5d8-7e6146cbd0dc')
     def test_novnc(self):
         body = self.client.get_vnc_console(self.server['id'],
@@ -174,7 +165,7 @@
         # Do the initial HTTP Request to novncproxy to get the NoVNC JavaScript
         self._validate_novnc_html(body['url'])
         # Do the WebSockify HTTP Request to novncproxy to do the RFB connection
-        self._websocket = self._create_websocket(body['url'])
+        self._websocket = compute.create_websocket(body['url'])
         # Validate that we succesfully connected and upgraded to Web Sockets
         self._validate_websocket_upgrade()
         # Validate the RFB Negotiation to determine if a valid VNC session
@@ -187,84 +178,9 @@
         self.assertEqual('novnc', body['type'])
         # Do the WebSockify HTTP Request to novncproxy with a bad token
         url = body['url'].replace('token=', 'token=bad')
-        self._websocket = self._create_websocket(url)
+        self._websocket = compute.create_websocket(url)
         # Make sure the novncproxy rejected the connection and closed it
         data = self._websocket.receive_frame()
         self.assertTrue(data is None or len(data) == 0,
                         "The novnc proxy actually sent us some data, but we "
                         "expected it to close the connection.")
-
-
-class _WebSocket(object):
-    def __init__(self, client_socket, url):
-        """Contructor for the WebSocket wrapper to the socket."""
-        self._socket = client_socket
-        # Upgrade the HTTP connection to a WebSocket
-        self._upgrade(url)
-
-    def receive_frame(self):
-        """Wrapper for receiving data to parse the WebSocket frame format"""
-        # We need to loop until we either get some bytes back in the frame
-        # or no data was received (meaning the socket was closed).  This is
-        # done to handle the case where we get back some empty frames
-        while True:
-            header = self._socket.recv(2)
-            # If we didn't receive any data, just return None
-            if len(header) == 0:
-                return None
-            # We will make the assumption that we are only dealing with
-            # frames less than 125 bytes here (for the negotiation) and
-            # that only the 2nd byte contains the length, and since the
-            # server doesn't do masking, we can just read the data length
-            if ord_func(header[1]) & 127 > 0:
-                return self._socket.recv(ord_func(header[1]) & 127)
-
-    def send_frame(self, data):
-        """Wrapper for sending data to add in the WebSocket frame format."""
-        frame_bytes = list()
-        # For the first byte, want to say we are sending binary data (130)
-        frame_bytes.append(130)
-        # Only sending negotiation data so don't need to worry about > 125
-        # We do need to add the bit that says we are masking the data
-        frame_bytes.append(len(data) | 128)
-        # We don't really care about providing a random mask for security
-        # So we will just hard-code a value since a test program
-        mask = [7, 2, 1, 9]
-        for i in range(len(mask)):
-            frame_bytes.append(mask[i])
-        # Mask each of the actual data bytes that we are going to send
-        for i in range(len(data)):
-            frame_bytes.append(ord_func(data[i]) ^ mask[i % 4])
-        # Convert our integer list to a binary array of bytes
-        frame_bytes = struct.pack('!%iB' % len(frame_bytes), * frame_bytes)
-        self._socket.sendall(frame_bytes)
-
-    def close(self):
-        """Helper method to close the connection."""
-        # Close down the real socket connection and exit the test program
-        if self._socket is not None:
-            self._socket.shutdown(1)
-            self._socket.close()
-            self._socket = None
-
-    def _upgrade(self, url):
-        """Upgrade the HTTP connection to a WebSocket and verify."""
-        # The real request goes to the /websockify URI always
-        reqdata = 'GET /websockify HTTP/1.1\r\n'
-        reqdata += 'Host: %s:%s\r\n' % (url.hostname, url.port)
-        # Tell the HTTP Server to Upgrade the connection to a WebSocket
-        reqdata += 'Upgrade: websocket\r\nConnection: Upgrade\r\n'
-        # The token=xxx is sent as a Cookie not in the URI
-        reqdata += 'Cookie: %s\r\n' % url.query
-        # Use a hard-coded WebSocket key since a test program
-        reqdata += 'Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n'
-        reqdata += 'Sec-WebSocket-Version: 13\r\n'
-        # We are choosing to use binary even though browser may do Base64
-        reqdata += 'Sec-WebSocket-Protocol: binary\r\n\r\n'
-        # Send the HTTP GET request and get the response back
-        self._socket.sendall(reqdata.encode('utf8'))
-        self.response = data = self._socket.recv(4096)
-        # Loop through & concatenate all of the data in the response body
-        while len(data) > 0 and self.response.find(b'\r\n\r\n') < 0:
-            data = self._socket.recv(4096)
-            self.response += data
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 73c7614..b0a6622 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo_log import log as logging
 import testtools
 
 from tempest.api.compute import base
@@ -25,8 +24,6 @@
 
 CONF = config.CONF
 
-LOG = logging.getLogger(__name__)
-
 
 class AttachVolumeTestJSON(base.BaseV2ComputeTest):
     max_microversion = '2.19'
@@ -65,6 +62,20 @@
         # Stop and Start a server with an attached volume, ensuring that
         # the volume remains attached.
         server = self._create_server()
+
+        # NOTE(andreaf) Create one remote client used throughout the test.
+        if CONF.validation.run_validation:
+            linux_client = remote_client.RemoteClient(
+                self.get_server_ip(server),
+                self.image_ssh_user,
+                self.image_ssh_password,
+                self.validation_resources['keypair']['private_key'],
+                server=server,
+                servers_client=self.servers_client)
+            # NOTE(andreaf) We need to ensure the ssh key has been
+            # injected in the guest before we power cycle
+            linux_client.validate_authentication()
+
         volume = self.create_volume()
         attachment = self.attach_volume(server, volume,
                                         device=('/dev/%s' % self.device))
@@ -78,14 +89,6 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            linux_client = remote_client.RemoteClient(
-                self.get_server_ip(server),
-                self.image_ssh_user,
-                self.image_ssh_password,
-                self.validation_resources['keypair']['private_key'],
-                server=server,
-                servers_client=self.servers_client)
-
             disks = linux_client.get_disks()
             device_name_to_match = '\n' + self.device + ' '
             self.assertIn(device_name_to_match, disks)
@@ -103,14 +106,6 @@
                                        'ACTIVE')
 
         if CONF.validation.run_validation:
-            linux_client = remote_client.RemoteClient(
-                self.get_server_ip(server),
-                self.image_ssh_user,
-                self.image_ssh_password,
-                self.validation_resources['keypair']['private_key'],
-                server=server,
-                servers_client=self.servers_client)
-
             disks = linux_client.get_disks()
             self.assertNotIn(device_name_to_match, disks)
 
diff --git a/tempest/api/identity/admin/v3/test_oauth_consumers.py b/tempest/api/identity/admin/v3/test_oauth_consumers.py
new file mode 100644
index 0000000..f06fb8f
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_oauth_consumers.py
@@ -0,0 +1,91 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.identity import base
+from tempest.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions as exceptions
+
+
+class OAUTHConsumersV3Test(base.BaseIdentityV3AdminTest):
+
+    def _create_consumer(self):
+        """Creates a consumer with a random description."""
+        description = data_utils.rand_name('test_create_consumer')
+        consumer = self.oauth_consumers_client.create_consumer(
+            description)['consumer']
+        # cleans up created consumers after tests
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.oauth_consumers_client.delete_consumer,
+                        consumer['id'])
+        return consumer
+
+    @decorators.idempotent_id('c8307ea6-a86c-47fd-ae7b-5b3b2caca76d')
+    def test_create_and_show_consumer(self):
+        """Tests to make sure that a consumer with parameters is made"""
+        consumer = self._create_consumer()
+        # fetch created consumer from client
+        fetched_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        # assert that the fetched consumer matches the created one and
+        # has all parameters
+        for key in ['description', 'id', 'links']:
+            self.assertEqual(consumer[key], fetched_consumer[key])
+
+    @decorators.idempotent_id('fdfa1b7f-2a31-4354-b2c7-f6ae20554f93')
+    def test_delete_consumer(self):
+        """Tests the delete function."""
+        consumer = self._create_consumer()
+        # fetch consumer from client to confirm it exists
+        fetched_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        self.assertEqual(consumer['id'], fetched_consumer['id'])
+        # delete existing consumer
+        self.oauth_consumers_client.delete_consumer(consumer['id'])
+        # check that consumer no longer exists
+        self.assertRaises(exceptions.NotFound,
+                          self.oauth_consumers_client.show_consumer,
+                          consumer['id'])
+
+    @decorators.idempotent_id('080a9b1a-c009-47c0-9979-5305bf72e3dc')
+    def test_update_consumer(self):
+        """Tests the update functionality"""
+        # create a new consumer to update
+        consumer = self._create_consumer()
+        # create new description
+        new_description = data_utils.rand_name('test_update_consumer')
+        # update consumer
+        self.oauth_consumers_client.update_consumer(consumer['id'],
+                                                    new_description)
+        # check that the same consumer now has the new description
+        updated_consumer = self.oauth_consumers_client.show_consumer(
+            consumer['id'])['consumer']
+        self.assertEqual(new_description, updated_consumer['description'])
+
+    @decorators.idempotent_id('09ca50de-78f2-4ffb-ac71-f2254036b2b8')
+    def test_list_consumers(self):
+        """Test for listing consumers"""
+        # create two consumers to populate list
+        new_consumer_one = self._create_consumer()
+        new_consumer_two = self._create_consumer()
+        # fetch the list of consumers
+        consumer_list = self.oauth_consumers_client \
+                            .list_consumers()['consumers']
+        # add fetched consumer ids to a list
+        id_list = [consumer['id'] for consumer in consumer_list]
+        # check if created consumers are in the list
+        self.assertIn(new_consumer_one['id'], id_list)
+        self.assertIn(new_consumer_two['id'], id_list)
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index e07d525..04be00b 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -381,3 +381,48 @@
         role_assignments = self.role_assignments.list_role_assignments(
             effective=True, **params)['role_assignments']
         self.assertEmpty(role_assignments)
+
+    @decorators.idempotent_id('3748c316-c18f-4b08-997b-c60567bc6235')
+    def test_list_all_implied_roles(self):
+        # Create inference rule from "roles[0]" to "roles[1]"
+        self._create_implied_role(
+            self.roles[0]['id'], self.roles[1]['id'])
+
+        # Create inference rule from "roles[0]" to "roles[2]"
+        self._create_implied_role(
+            self.roles[0]['id'], self.roles[2]['id'])
+
+        # Create inference rule from "roles[2]" to "role"
+        self._create_implied_role(
+            self.roles[2]['id'], self.role['id'])
+
+        rules = self.roles_client.list_all_role_inference_rules()[
+            'role_inferences']
+        # Sort the rules by the number of inferences, since there should be 1
+        # inference between "roles[2]" and "role" and 2 inferences for
+        # "roles[0]": between "roles[1]" and "roles[2]".
+        sorted_rules = sorted(rules, key=lambda r: len(r['implies']))
+
+        # Check that 2 sets of rules are returned.
+        self.assertEqual(2, len(sorted_rules))
+        # Check that only 1 inference rule exists between "roles[2]" and "role"
+        self.assertEqual(1, len(sorted_rules[0]['implies']))
+        # Check that 2 inference rules exist for "roles[0]": one between
+        # "roles[1]" and one between "roles[2]".
+        self.assertEqual(2, len(sorted_rules[1]['implies']))
+
+        # Check that "roles[2]" is the "prior_role" and that "role" is the
+        # "implies" role.
+        self.assertEqual(self.roles[2]['id'],
+                         sorted_rules[0]['prior_role']['id'])
+        self.assertEqual(self.role['id'],
+                         sorted_rules[0]['implies'][0]['id'])
+
+        # Check that "roles[0]" is the "prior_role" and that "roles[1]" and
+        # "roles[2]" are the "implies" roles.
+        self.assertEqual(self.roles[0]['id'],
+                         sorted_rules[1]['prior_role']['id'])
+
+        implies_ids = [r['id'] for r in sorted_rules[1]['implies']]
+        self.assertIn(self.roles[1]['id'], implies_ids)
+        self.assertIn(self.roles[2]['id'], implies_ids)
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 7a569b7..ec64e0c 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -46,21 +46,21 @@
 
     def create_trustor_and_roles(self):
         # create a project that trusts will be granted on
-        self.trustor_project_name = data_utils.rand_name(name='project')
+        trustor_project_name = data_utils.rand_name(name='project')
         project = self.projects_client.create_project(
-            self.trustor_project_name, domain_id='default')['project']
+            trustor_project_name, domain_id='default')['project']
         self.trustor_project_id = project['id']
         self.assertIsNotNone(self.trustor_project_id)
 
         # Create a trustor User
-        self.trustor_username = data_utils.rand_name('user')
-        u_desc = self.trustor_username + 'description'
-        u_email = self.trustor_username + '@testmail.xx'
-        self.trustor_password = data_utils.rand_password()
+        trustor_username = data_utils.rand_name('user')
+        u_desc = trustor_username + 'description'
+        u_email = trustor_username + '@testmail.xx'
+        trustor_password = data_utils.rand_password()
         user = self.users_client.create_user(
-            name=self.trustor_username,
+            name=trustor_username,
             description=u_desc,
-            password=self.trustor_password,
+            password=trustor_password,
             email=u_email,
             project_id=self.trustor_project_id,
             domain_id='default')['user']
@@ -95,10 +95,10 @@
         # Initialize a new client with the trustor credentials
         creds = common_creds.get_credentials(
             identity_version='v3',
-            username=self.trustor_username,
-            password=self.trustor_password,
+            username=trustor_username,
+            password=trustor_password,
             user_domain_id='default',
-            tenant_name=self.trustor_project_name,
+            tenant_name=trustor_project_name,
             project_domain_id='default',
             domain_id='default')
         os = clients.Manager(credentials=creds)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 9339d3c..8317535 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -212,6 +212,7 @@
         cls.groups_client = cls.os_adm.groups_client
         cls.projects_client = cls.os_adm.projects_client
         cls.role_assignments = cls.os_admin.role_assignments_client
+        cls.oauth_consumers_client = cls.os_adm.oauth_consumers_client
         if CONF.identity.admin_domain_scope:
             # NOTE(andreaf) When keystone policy requires it, the identity
             # admin clients for these tests shall use 'domain' scoped tokens.
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index f263258..e7998ee 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -34,8 +34,6 @@
         super(IdentityV3UsersTest, cls).resource_setup()
         cls.creds = cls.os.credentials
         cls.user_id = cls.creds.user_id
-        cls.username = cls.creds.username
-        cls.password = cls.creds.password
 
     def _update_password(self, original_password, password):
         self.non_admin_users_client.update_user_password(
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 04c752a..6e5e726 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -98,3 +98,16 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           name='test', container_format='bare',
                           disk_format='wrong')
+
+    @test.attr(type=['negative'])
+    @decorators.idempotent_id('ab980a34-8410-40eb-872b-f264752f46e5')
+    def test_delete_protected_image(self):
+        # Create a protected image
+        image = self.create_image(protected=True)
+        self.addCleanup(self.client.update_image, image['id'],
+                        [dict(replace="/protected", value=False)])
+
+        # Try deleting the protected image
+        self.assertRaises(lib_exc.Forbidden,
+                          self.client.delete_image,
+                          image['id'])
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 742fe59..8df5248 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -243,6 +243,7 @@
     @test.requires_ext(extension='ext-gw-mode', service='network')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
+    @decorators.skip_because(bug='1676207')
     def test_create_router_set_gateway_with_fixed_ip(self):
         # Don't know public_network_address, so at first create address
         # from public_network and delete
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 4e17c3d..8d3d344 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -47,13 +47,8 @@
         cls.servers_client = cls.os.servers_client
         cls.keypairs_client = cls.os.keypairs_client
         cls.networks_client = cls.os.networks_client
-        cls.volumes_client = cls.os.volumes_client
         cls.images_v2_client = cls.os.image_client_v2
-
-        if CONF.volume_feature_enabled.api_v2:
-            cls.volumes_client = cls.os.volumes_v2_client
-        else:
-            cls.volumes_client = cls.os.volumes_client
+        cls.volumes_client = cls.os.volumes_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 86323e1..7ddf7af 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -35,18 +35,10 @@
         self.assertEqual('available', volume.get('status'))
         self.assertEqual(CONF.volume.volume_size, volume.get('size'))
 
-        # Some volume properties have been renamed with Cinder v2
-        if CONF.volume_feature_enabled.api_v2:
-            description_field = 'description'
-            name_field = 'name'
-        else:
-            description_field = 'display_description'
-            name_field = 'display_name'
-
         self.assertEqual(template['resources']['volume']['properties'][
-            'description'], volume.get(description_field))
+            'description'], volume.get('description'))
         self.assertEqual(template['resources']['volume']['properties'][
-            'name'], volume.get(name_field))
+            'name'], volume.get('name'))
 
     def _outputs_verify(self, stack_identifier, template):
         self.assertEqual('available',
diff --git a/tempest/api/volume/admin/v2/test_backends_capabilities.py b/tempest/api/volume/admin/test_backends_capabilities.py
similarity index 94%
rename from tempest/api/volume/admin/v2/test_backends_capabilities.py
rename to tempest/api/volume/admin/test_backends_capabilities.py
index 1060f2b..607fc43 100644
--- a/tempest/api/volume/admin/v2/test_backends_capabilities.py
+++ b/tempest/api/volume/admin/test_backends_capabilities.py
@@ -19,7 +19,7 @@
 from tempest.lib import decorators
 
 
-class BackendsCapabilitiesAdminV2TestsJSON(base.BaseVolumeAdminTest):
+class BackendsCapabilitiesAdminTestsJSON(base.BaseVolumeAdminTest):
 
     CAPABILITIES = ('namespace',
                     'vendor_name',
@@ -34,7 +34,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(BackendsCapabilitiesAdminV2TestsJSON, cls).resource_setup()
+        super(BackendsCapabilitiesAdminTestsJSON, cls).resource_setup()
         # Get host list, formation: host@backend-name
         cls.hosts = [
             pool['name'] for pool in
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index eea918a..2db8010 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -20,18 +20,18 @@
 CONF = config.CONF
 
 
-class VolumeMultiBackendV2Test(base.BaseVolumeAdminTest):
+class VolumeMultiBackendTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeMultiBackendV2Test, cls).skip_checks()
+        super(VolumeMultiBackendTest, cls).skip_checks()
 
         if not CONF.volume_feature_enabled.multi_backend:
             raise cls.skipException("Cinder multi-backend feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeMultiBackendV2Test, cls).resource_setup()
+        super(VolumeMultiBackendTest, cls).resource_setup()
 
         # read backend name from a list .
         backend_names = set(CONF.volume.backend_names)
@@ -89,7 +89,7 @@
             cls.admin_volume_client.delete_volume(volume_id)
             cls.admin_volume_client.wait_for_resource_deletion(volume_id)
 
-        super(VolumeMultiBackendV2Test, cls).resource_cleanup()
+        super(VolumeMultiBackendTest, cls).resource_cleanup()
 
     @decorators.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
     def test_backend_name_reporting(self):
diff --git a/tempest/api/volume/admin/test_qos.py b/tempest/api/volume/admin/test_qos.py
index aa6aa98..e31c0ef 100644
--- a/tempest/api/volume/admin/test_qos.py
+++ b/tempest/api/volume/admin/test_qos.py
@@ -18,16 +18,16 @@
 from tempest.lib import decorators
 
 
-class QosSpecsV2TestJSON(base.BaseVolumeAdminTest):
+class QosSpecsTestJSON(base.BaseVolumeAdminTest):
     """Test the Cinder QoS-specs.
 
     Tests for  create, list, delete, show, associate,
-    disassociate, set/unset key V2 APIs.
+    disassociate, set/unset key APIs.
     """
 
     @classmethod
     def resource_setup(cls):
-        super(QosSpecsV2TestJSON, cls).resource_setup()
+        super(QosSpecsTestJSON, cls).resource_setup()
         # Create admin qos client
         # Create a test shared qos-specs for tests
         cls.qos_name = utils.rand_name(cls.__name__ + '-QoS')
diff --git a/tempest/api/volume/admin/v2/test_snapshot_manage.py b/tempest/api/volume/admin/test_snapshot_manage.py
similarity index 97%
rename from tempest/api/volume/admin/v2/test_snapshot_manage.py
rename to tempest/api/volume/admin/test_snapshot_manage.py
index e8bd477..a2d5fb1 100644
--- a/tempest/api/volume/admin/v2/test_snapshot_manage.py
+++ b/tempest/api/volume/admin/test_snapshot_manage.py
@@ -23,7 +23,7 @@
 CONF = config.CONF
 
 
-class SnapshotManageAdminV2Test(base.BaseVolumeAdminTest):
+class SnapshotManageAdminTest(base.BaseVolumeAdminTest):
     """Unmanage & manage snapshots
 
      This feature provides the ability to import/export volume snapshot
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 4d8e5bf..471f39a 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -20,16 +20,16 @@
 CONF = config.CONF
 
 
-class SnapshotsActionsV2Test(base.BaseVolumeAdminTest):
+class SnapshotsActionsTest(base.BaseVolumeAdminTest):
     @classmethod
     def skip_checks(cls):
-        super(SnapshotsActionsV2Test, cls).skip_checks()
+        super(SnapshotsActionsTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(SnapshotsActionsV2Test, cls).resource_setup()
+        super(SnapshotsActionsTest, cls).resource_setup()
 
         # Create a test shared volume for tests
         cls.volume = cls.create_volume()
@@ -43,7 +43,7 @@
         snapshot_id = self.snapshot['id']
         self.admin_snapshots_client.reset_snapshot_status(snapshot_id,
                                                           status)
-        super(SnapshotsActionsV2Test, self).tearDown()
+        super(SnapshotsActionsTest, self).tearDown()
 
     def _create_reset_and_force_delete_temp_snapshot(self, status=None):
         # Create snapshot, reset snapshot status,
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/test_user_messages.py
similarity index 96%
rename from tempest/api/volume/admin/v3/test_user_messages.py
rename to tempest/api/volume/admin/test_user_messages.py
index 991397a..20c3538 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/test_user_messages.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api.volume.v3 import base
+from tempest.api.volume import base
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
@@ -33,7 +33,8 @@
     'links']
 
 
-class UserMessagesTest(base.VolumesV3AdminTest):
+class UserMessagesTest(base.BaseVolumeAdminTest):
+    _api_version = 3
     min_microversion = '3.3'
     max_microversion = 'latest'
 
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index 1686582..04d6cf9 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -17,7 +17,7 @@
 from tempest.lib import decorators
 
 
-class VolumeHostsAdminV2TestsJSON(base.BaseVolumeAdminTest):
+class VolumeHostsAdminTestsJSON(base.BaseVolumeAdminTest):
 
     @decorators.idempotent_id('d5f3efa2-6684-4190-9ced-1c2f526352ad')
     def test_list_hosts(self):
diff --git a/tempest/api/volume/admin/test_volume_manage.py b/tempest/api/volume/admin/test_volume_manage.py
new file mode 100644
index 0000000..a039085
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_manage.py
@@ -0,0 +1,81 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.volume import base
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+CONF = config.CONF
+
+
+class VolumeManageAdminTest(base.BaseVolumeAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeManageAdminTest, cls).skip_checks()
+
+        if not CONF.volume_feature_enabled.manage_volume:
+            raise cls.skipException("Manage volume tests are disabled")
+
+        if len(CONF.volume.manage_volume_ref) != 2:
+            raise cls.skipException("Manage volume ref is not correctly "
+                                    "configured")
+
+    @decorators.idempotent_id('70076c71-0ce1-4208-a8ff-36a66e65cc1e')
+    def test_unmanage_manage_volume(self):
+        # Create original volume
+        org_vol_id = self.create_volume()['id']
+        org_vol_info = self.admin_volume_client.show_volume(
+            org_vol_id)['volume']
+
+        # Unmanage the original volume
+        self.admin_volume_client.unmanage_volume(org_vol_id)
+        self.admin_volume_client.wait_for_resource_deletion(org_vol_id)
+
+        # Verify the original volume does not exist in volume list
+        params = {'all_tenants': 1}
+        all_tenants_volumes = self.admin_volume_client.list_volumes(
+            detail=True, params=params)['volumes']
+        self.assertNotIn(org_vol_id, [v['id'] for v in all_tenants_volumes])
+
+        # Manage volume
+        new_vol_name = data_utils.rand_name(
+            self.__class__.__name__ + '-volume')
+        new_vol_ref = {
+            'name': new_vol_name,
+            'host': org_vol_info['os-vol-host-attr:host'],
+            'ref': {CONF.volume.manage_volume_ref[0]:
+                    CONF.volume.manage_volume_ref[1] % org_vol_id},
+            'volume_type': org_vol_info['volume_type'],
+            'availability_zone': org_vol_info['availability_zone']}
+        new_vol_id = self.admin_volume_manage_client.manage_volume(
+            **new_vol_ref)['volume']['id']
+        self.addCleanup(self.delete_volume,
+                        self.admin_volume_client, new_vol_id)
+        waiters.wait_for_volume_resource_status(self.admin_volume_client,
+                                                new_vol_id, 'available')
+
+        # Compare the managed volume with the original
+        new_vol_info = self.admin_volume_client.show_volume(
+            new_vol_id)['volume']
+        self.assertNotIn(new_vol_id, [org_vol_id])
+        self.assertEqual(new_vol_info['name'], new_vol_name)
+        for key in ['size',
+                    'volume_type',
+                    'availability_zone',
+                    'os-vol-host-attr:host']:
+            self.assertEqual(new_vol_info[key], org_vol_info[key])
diff --git a/tempest/api/volume/admin/v2/test_volume_pools.py b/tempest/api/volume/admin/test_volume_pools.py
similarity index 61%
rename from tempest/api/volume/admin/v2/test_volume_pools.py
rename to tempest/api/volume/admin/test_volume_pools.py
index 91d092d..60a3bda 100644
--- a/tempest/api/volume/admin/v2/test_volume_pools.py
+++ b/tempest/api/volume/admin/test_volume_pools.py
@@ -14,29 +14,26 @@
 #    under the License.
 
 from tempest.api.volume import base
+from tempest import config
 from tempest.lib import decorators
 
+CONF = config.CONF
 
-class VolumePoolsAdminV2TestsJSON(base.BaseVolumeAdminTest):
 
-    @classmethod
-    def resource_setup(cls):
-        super(VolumePoolsAdminV2TestsJSON, cls).resource_setup()
-        # Create a test shared volume for tests
-        cls.volume = cls.create_volume()
-
-    def _assert_host_volume_in_pools(self, with_detail=False):
-        volume_info = self.admin_volume_client.show_volume(
-            self.volume['id'])['volume']
+class VolumePoolsAdminTestsJSON(base.BaseVolumeAdminTest):
+    def _assert_pools(self, with_detail=False):
         cinder_pools = self.admin_volume_client.show_pools(
             detail=with_detail)['pools']
-        self.assertIn(volume_info['os-vol-host-attr:host'],
-                      [pool['name'] for pool in cinder_pools])
+        self.assertIn('name', cinder_pools[0])
+        if with_detail:
+            self.assertIn(CONF.volume.vendor_name,
+                          [pool['capabilities']['vendor_name']
+                           for pool in cinder_pools])
 
     @decorators.idempotent_id('0248a46c-e226-4933-be10-ad6fca8227e7')
     def test_get_pools_without_details(self):
-        self._assert_host_volume_in_pools()
+        self._assert_pools()
 
     @decorators.idempotent_id('d4bb61f7-762d-4437-b8a4-5785759a0ced')
     def test_get_pools_with_details(self):
-        self._assert_host_volume_in_pools(with_detail=True)
+        self._assert_pools(with_detail=True)
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 97f61c1..8bf416a 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -21,14 +21,14 @@
 QUOTA_USAGE_KEYS = ['reserved', 'limit', 'in_use']
 
 
-class BaseVolumeQuotasAdminV2TestJSON(base.BaseVolumeAdminTest):
+class BaseVolumeQuotasAdminTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_credentials(cls):
-        super(BaseVolumeQuotasAdminV2TestJSON, cls).setup_credentials()
+        super(BaseVolumeQuotasAdminTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
         cls.alt_client = cls.os_alt.volumes_client
 
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 1051445..10cf890 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -22,17 +22,17 @@
 CONF = config.CONF
 
 
-class BaseVolumeQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
+class BaseVolumeQuotasNegativeTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     @classmethod
     def setup_credentials(cls):
-        super(BaseVolumeQuotasNegativeV2TestJSON, cls).setup_credentials()
+        super(BaseVolumeQuotasNegativeTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
 
     @classmethod
     def resource_setup(cls):
-        super(BaseVolumeQuotasNegativeV2TestJSON, cls).resource_setup()
+        super(BaseVolumeQuotasNegativeTestJSON, cls).resource_setup()
         cls.shared_quota_set = {'gigabytes': 2 * CONF.volume.volume_size,
                                 'volumes': 1}
 
diff --git a/tempest/api/volume/admin/test_volume_retype_with_migration.py b/tempest/api/volume/admin/test_volume_retype_with_migration.py
index 4d32fdd..94d5299 100644
--- a/tempest/api/volume/admin/test_volume_retype_with_migration.py
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -23,11 +23,11 @@
 LOG = logging.getLogger(__name__)
 
 
-class VolumeRetypeWithMigrationV2Test(base.BaseVolumeAdminTest):
+class VolumeRetypeWithMigrationTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeRetypeWithMigrationV2Test, cls).skip_checks()
+        super(VolumeRetypeWithMigrationTest, cls).skip_checks()
 
         if not CONF.volume_feature_enabled.multi_backend:
             raise cls.skipException("Cinder multi-backend feature disabled.")
@@ -38,7 +38,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeRetypeWithMigrationV2Test, cls).resource_setup()
+        super(VolumeRetypeWithMigrationTest, cls).resource_setup()
         # read backend name from a list.
         backend_src = CONF.volume.backend_names[0]
         backend_dst = CONF.volume.backend_names[1]
@@ -73,7 +73,7 @@
                     fetched_vol['id'])
                 break
 
-        super(VolumeRetypeWithMigrationV2Test, cls).resource_cleanup()
+        super(VolumeRetypeWithMigrationTest, cls).resource_cleanup()
 
     @decorators.idempotent_id('a1a41f3f-9dad-493e-9f09-3ff197d477cd')
     def test_available_volume_retype_with_migration(self):
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index aa5145d..4aab9c1 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -13,18 +13,14 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 from tempest.api.volume import base
-from tempest import config
 from tempest.lib import decorators
 
 
-CONF = config.CONF
-
-
 def _get_host(host):
     return host.split('@')[0]
 
 
-class VolumesServicesV2TestJSON(base.BaseVolumeAdminTest):
+class VolumesServicesTestJSON(base.BaseVolumeAdminTest):
     """Tests Volume Services API.
 
     volume service list requires admin privileges.
@@ -32,7 +28,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesServicesV2TestJSON, cls).resource_setup()
+        super(VolumesServicesTestJSON, cls).resource_setup()
         cls.services = (cls.admin_volume_services_client.list_services()
                         ['services'])
         # NOTE: Cinder service-list API returns the list contains
@@ -71,6 +67,20 @@
         # on order.
         self.assertEqual(sorted(s1), sorted(s2))
 
+    @decorators.idempotent_id('67ec6902-f91d-4dec-91fa-338523208bbc')
+    def test_get_service_by_volume_host_name(self):
+        volume_id = self.create_volume()['id']
+        volume = self.admin_volume_client.show_volume(volume_id)['volume']
+        hostname = _get_host(volume['os-vol-host-attr:host'])
+
+        services = (self.admin_volume_services_client.list_services(
+            host=hostname, binary='cinder-volume')['services'])
+
+        self.assertNotEqual(0, len(services),
+                            'cinder-volume not found on host %s' % hostname)
+        self.assertEqual(hostname, _get_host(services[0]['host']))
+        self.assertEqual('cinder-volume', services[0]['binary'])
+
     @decorators.idempotent_id('ffa6167c-4497-4944-a464-226bbdb53908')
     def test_get_service_by_service_and_host_name(self):
 
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
index 6320fb1..e5c78cb 100644
--- a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -22,23 +22,23 @@
 CONF = config.CONF
 
 
-class VolumeSnapshotQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
+class VolumeSnapshotQuotasNegativeTestJSON(base.BaseVolumeAdminTest):
     force_tenant_isolation = True
 
     @classmethod
     def skip_checks(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).skip_checks()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException('Cinder volume snapshots are disabled')
 
     @classmethod
     def setup_credentials(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).setup_credentials()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).setup_credentials()
         cls.demo_tenant_id = cls.os.credentials.tenant_id
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeSnapshotQuotasNegativeV2TestJSON, cls).resource_setup()
+        super(VolumeSnapshotQuotasNegativeTestJSON, cls).resource_setup()
         cls.default_volume_size = CONF.volume.volume_size
         cls.shared_quota_set = {'gigabytes': 3 * cls.default_volume_size,
                                 'volumes': 1, 'snapshots': 1}
diff --git a/tempest/api/volume/admin/v2/test_volume_type_access.py b/tempest/api/volume/admin/test_volume_type_access.py
similarity index 96%
rename from tempest/api/volume/admin/v2/test_volume_type_access.py
rename to tempest/api/volume/admin/test_volume_type_access.py
index b60b33b..297ab6e 100644
--- a/tempest/api/volume/admin/v2/test_volume_type_access.py
+++ b/tempest/api/volume/admin/test_volume_type_access.py
@@ -23,13 +23,13 @@
 CONF = config.CONF
 
 
-class VolumeTypesAccessV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesAccessTest(base.BaseVolumeAdminTest):
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_clients(cls):
-        super(VolumeTypesAccessV2Test, cls).setup_clients()
+        super(VolumeTypesAccessTest, cls).setup_clients()
         cls.alt_client = cls.os_alt.volumes_client
 
     @decorators.idempotent_id('d4dd0027-835f-4554-a6e5-50903fb79184')
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index fd333eb..ac717f8 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -22,7 +22,7 @@
 CONF = config.CONF
 
 
-class VolumeTypesV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesTest(base.BaseVolumeAdminTest):
 
     @decorators.idempotent_id('9d9b28e3-1b2e-4483-a2cc-24aa0ea1de54')
     def test_volume_type_list(self):
@@ -122,43 +122,55 @@
             fetched_volume_type['os-volume-type-access:is_public'])
 
     @decorators.idempotent_id('7830abd0-ff99-4793-a265-405684a54d46')
-    def test_volume_type_encryption_create_get_delete(self):
-        # Create/get/delete encryption type.
-        provider = "LuksEncryptor"
-        control_location = "front-end"
-        body = self.create_volume_type()
+    def test_volume_type_encryption_create_get_update_delete(self):
+        # Create/get/update/delete encryption type.
+        create_kwargs = {'provider': 'LuksEncryptor',
+                         'control_location': 'front-end'}
+        volume_type_id = self.create_volume_type()['id']
+
         # Create encryption type
         encryption_type = \
             self.admin_encryption_types_client.create_encryption_type(
-                body['id'], provider=provider,
-                control_location=control_location)['encryption']
+                volume_type_id, **create_kwargs)['encryption']
         self.assertIn('volume_type_id', encryption_type)
-        self.assertEqual(provider, encryption_type['provider'],
-                         "The created encryption_type provider is not equal "
-                         "to the requested provider")
-        self.assertEqual(control_location, encryption_type['control_location'],
-                         "The created encryption_type control_location is not "
-                         "equal to the requested control_location")
+        for key in create_kwargs:
+            self.assertEqual(create_kwargs[key], encryption_type[key],
+                             'The created encryption_type %s is different '
+                             'from the requested encryption_type' % key)
 
         # Get encryption type
+        encrypt_type_id = encryption_type['volume_type_id']
         fetched_encryption_type = (
             self.admin_encryption_types_client.show_encryption_type(
-                encryption_type['volume_type_id']))
-        self.assertEqual(provider,
-                         fetched_encryption_type['provider'],
-                         'The fetched encryption_type provider is different '
-                         'from the created encryption_type')
-        self.assertEqual(control_location,
-                         fetched_encryption_type['control_location'],
-                         'The fetched encryption_type control_location is '
-                         'different from the created encryption_type')
+                encrypt_type_id))
+        for key in create_kwargs:
+            self.assertEqual(create_kwargs[key], fetched_encryption_type[key],
+                             'The fetched encryption_type %s is different '
+                             'from the created encryption_type' % key)
+
+        # Update encryption type
+        update_kwargs = {'key_size': 128,
+                         'provider': 'SomeProvider',
+                         'cipher': 'aes-xts-plain64',
+                         'control_location': 'back-end'}
+        self.admin_encryption_types_client.update_encryption_type(
+            encrypt_type_id, **update_kwargs)
+        updated_encryption_type = (
+            self.admin_encryption_types_client.show_encryption_type(
+                encrypt_type_id))
+        for key in update_kwargs:
+            self.assertEqual(update_kwargs[key], updated_encryption_type[key],
+                             'The fetched encryption_type %s is different '
+                             'from the updated encryption_type' % key)
 
         # Delete encryption type
-        type_id = encryption_type['volume_type_id']
-        self.admin_encryption_types_client.delete_encryption_type(type_id)
-        self.admin_encryption_types_client.wait_for_resource_deletion(type_id)
+        self.admin_encryption_types_client.delete_encryption_type(
+            encrypt_type_id)
+        self.admin_encryption_types_client.wait_for_resource_deletion(
+            encrypt_type_id)
         deleted_encryption_type = (
-            self.admin_encryption_types_client.show_encryption_type(type_id))
+            self.admin_encryption_types_client.show_encryption_type(
+                encrypt_type_id))
         self.assertEmpty(deleted_encryption_type)
 
     @decorators.idempotent_id('cf9f07c6-db9e-4462-a243-5933ad65e9c8')
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 6a7ee3b..b5a2fb7 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -18,11 +18,11 @@
 from tempest.lib import exceptions as lib_exc
 
 
-class VolumeTypesExtraSpecsV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesExtraSpecsTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeTypesExtraSpecsV2Test, cls).resource_setup()
+        super(VolumeTypesExtraSpecsTest, cls).resource_setup()
         cls.volume_type = cls.create_volume_type()
 
     @decorators.idempotent_id('b42923e9-0452-4945-be5b-d362ae533e60')
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 37422ca..4efc44b 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
@@ -20,11 +20,11 @@
 from tempest import test
 
 
-class ExtraSpecsNegativeV2Test(base.BaseVolumeAdminTest):
+class ExtraSpecsNegativeTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(ExtraSpecsNegativeV2Test, cls).resource_setup()
+        super(ExtraSpecsNegativeTest, cls).resource_setup()
         extra_specs = {"spec1": "val1"}
         cls.volume_type = cls.create_volume_type(extra_specs=extra_specs)
 
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 4017de6..bac2ea3 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -20,7 +20,7 @@
 from tempest import test
 
 
-class VolumeTypesNegativeV2Test(base.BaseVolumeAdminTest):
+class VolumeTypesNegativeTest(base.BaseVolumeAdminTest):
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('b48c98f2-e662-4885-9b71-032256906314')
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index ba8032f..7f291e9 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -17,7 +17,7 @@
 from tempest.lib import decorators
 
 
-class VolumesActionsV2Test(base.BaseVolumeAdminTest):
+class VolumesActionsTest(base.BaseVolumeAdminTest):
 
     def _create_reset_and_force_delete_temp_volume(self, status=None):
         # Create volume, reset volume status, and force delete temp volume
@@ -32,7 +32,9 @@
     def test_volume_reset_status(self):
         # test volume reset status : available->error->available
         volume = self.create_volume()
-        for status in ['error', 'available']:
+        self.addCleanup(self.admin_volume_client.reset_volume_status,
+                        volume['id'], status='available')
+        for status in ['error', 'available', 'maintenance']:
             self.admin_volume_client.reset_volume_status(
                 volume['id'], status=status)
             volume_get = self.admin_volume_client.show_volume(
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 29c79f9..afc3281 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -25,11 +25,11 @@
 CONF = config.CONF
 
 
-class VolumesBackupsAdminV2Test(base.BaseVolumeAdminTest):
+class VolumesBackupsAdminTest(base.BaseVolumeAdminTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesBackupsAdminV2Test, cls).skip_checks()
+        super(VolumesBackupsAdminTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
diff --git a/tempest/api/volume/admin/v2/test_volumes_list.py b/tempest/api/volume/admin/test_volumes_list.py
similarity index 95%
rename from tempest/api/volume/admin/v2/test_volumes_list.py
rename to tempest/api/volume/admin/test_volumes_list.py
index 6bab373..9d98b7a 100644
--- a/tempest/api/volume/admin/v2/test_volumes_list.py
+++ b/tempest/api/volume/admin/test_volumes_list.py
@@ -23,11 +23,11 @@
 CONF = config.CONF
 
 
-class VolumesListAdminV2TestJSON(base.BaseVolumeAdminTest):
+class VolumesListAdminTestJSON(base.BaseVolumeAdminTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesListAdminV2TestJSON, cls).resource_setup()
+        super(VolumesListAdminTestJSON, cls).resource_setup()
         # Create 3 test volumes
         # NOTE(zhufl): When using pre-provisioned credentials, the project
         # may have volumes other than those created below.
diff --git a/tempest/api/volume/admin/v2/__init__.py b/tempest/api/volume/admin/v2/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/admin/v2/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/admin/v3/__init__.py b/tempest/api/volume/admin/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/admin/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 5e4fada..0cd5ec7 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,9 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.api.volume import api_microversion_fixture
 from tempest.common import compute
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common import api_version_utils
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
@@ -24,7 +26,8 @@
 CONF = config.CONF
 
 
-class BaseVolumeTest(tempest.test.BaseTestCase):
+class BaseVolumeTest(api_version_utils.BaseMicroversionTest,
+                     tempest.test.BaseTestCase):
     """Base test case class for all Cinder API tests."""
 
     _api_version = 2
@@ -49,6 +52,10 @@
             msg = ("Invalid Cinder API version (%s)" % cls._api_version)
             raise exceptions.InvalidConfiguration(msg)
 
+        api_version_utils.check_skip_with_microversion(
+            cls.min_microversion, cls.max_microversion,
+            CONF.volume.min_microversion, CONF.volume.max_microversion)
+
     @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
@@ -68,10 +75,21 @@
         cls.availability_zone_client = (
             cls.os.volume_v2_availability_zone_client)
         cls.volume_limits_client = cls.os.volume_v2_limits_client
+        cls.messages_client = cls.os.volume_v3_messages_client
+        cls.versions_client = cls.os.volume_v3_versions_client
+
+    def setUp(self):
+        super(BaseVolumeTest, self).setUp()
+        self.useFixture(api_microversion_fixture.APIMicroversionFixture(
+            self.request_microversion))
 
     @classmethod
     def resource_setup(cls):
         super(BaseVolumeTest, cls).resource_setup()
+        cls.request_microversion = (
+            api_version_utils.select_request_microversion(
+                cls.min_microversion,
+                CONF.volume.min_microversion))
 
         cls.snapshots = []
         cls.volumes = []
@@ -225,6 +243,7 @@
         cls.admin_volume_services_client = \
             cls.os_adm.volume_services_v2_client
         cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+        cls.admin_volume_manage_client = cls.os_adm.volume_manage_v2_client
         cls.admin_volume_client = cls.os_adm.volumes_v2_client
         cls.admin_hosts_client = cls.os_adm.volume_hosts_v2_client
         cls.admin_snapshot_manage_client = \
@@ -239,6 +258,8 @@
             cls.os_adm.volume_capabilities_v2_client
         cls.admin_scheduler_stats_client = \
             cls.os_adm.volume_scheduler_stats_v2_client
+        cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index f0d653f..666efdf 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -17,12 +17,12 @@
 from tempest.lib import decorators
 
 
-class AvailabilityZoneV2TestJSON(base.BaseVolumeTest):
-    """Tests Availability Zone V2 API List"""
+class AvailabilityZoneTestJSON(base.BaseVolumeTest):
+    """Tests Availability Zone API List"""
 
     @classmethod
     def setup_clients(cls):
-        super(AvailabilityZoneV2TestJSON, cls).setup_clients()
+        super(AvailabilityZoneTestJSON, cls).setup_clients()
         cls.client = cls.availability_zone_client
 
     @decorators.idempotent_id('01f1ae88-eba9-4c6b-a011-6f7ace06b725')
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index ac3742c..91bfa33 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -25,7 +25,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class ExtensionsV2TestJSON(base.BaseVolumeTest):
+class ExtensionsTestJSON(base.BaseVolumeTest):
 
     @decorators.idempotent_id('94607eb0-43a5-47ca-82aa-736b41bd2e2c')
     def test_list_extensions(self):
diff --git a/tempest/api/volume/v2/test_image_metadata.py b/tempest/api/volume/test_image_metadata.py
similarity index 87%
rename from tempest/api/volume/v2/test_image_metadata.py
rename to tempest/api/volume/test_image_metadata.py
index 9c082b3..77baf18 100644
--- a/tempest/api/volume/v2/test_image_metadata.py
+++ b/tempest/api/volume/test_image_metadata.py
@@ -23,11 +23,18 @@
 CONF = config.CONF
 
 
-class VolumesV2ImageMetadata(base.BaseVolumeTest):
+class VolumesImageMetadata(base.BaseVolumeTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesImageMetadata, cls).skip_checks()
+        if not CONF.service_available.glance:
+            skip_msg = ("%s skipped as Glance is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ImageMetadata, cls).resource_setup()
+        super(VolumesImageMetadata, cls).resource_setup()
         # Create a volume from image ID
         cls.volume = cls.create_volume(imageRef=CONF.compute.image_ref)
 
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index c1d4e05..164ed37 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -22,16 +22,16 @@
 CONF = config.CONF
 
 
-class SnapshotV2MetadataTestJSON(base.BaseVolumeTest):
+class SnapshotMetadataTestJSON(base.BaseVolumeTest):
     @classmethod
     def skip_checks(cls):
-        super(SnapshotV2MetadataTestJSON, cls).skip_checks()
+        super(SnapshotMetadataTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder snapshot feature disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(SnapshotV2MetadataTestJSON, cls).resource_setup()
+        super(SnapshotMetadataTestJSON, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
         # Create a snapshot
@@ -41,7 +41,7 @@
         # Update the metadata to {}
         self.snapshots_client.update_snapshot_metadata(
             self.snapshot['id'], metadata={})
-        super(SnapshotV2MetadataTestJSON, self).tearDown()
+        super(SnapshotMetadataTestJSON, self).tearDown()
 
     @decorators.idempotent_id('a2f20f99-e363-4584-be97-bc33afb1a56c')
     def test_crud_snapshot_metadata(self):
diff --git a/tempest/api/volume/v3/test_versions.py b/tempest/api/volume/test_versions.py
similarity index 90%
rename from tempest/api/volume/v3/test_versions.py
rename to tempest/api/volume/test_versions.py
index 20f1657..76f2a99 100644
--- a/tempest/api/volume/v3/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -12,12 +12,14 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-from tempest.api.volume.v3 import base
+from tempest.api.volume import base
 from tempest.lib import decorators
 from tempest import test
 
 
-class VersionsTest(base.VolumesV3Test):
+class VersionsTest(base.BaseVolumeTest):
+
+    _api_version = 3
 
     @decorators.idempotent_id('77838fc4-b49b-4c64-9533-166762517369')
     @test.attr(type='smoke')
diff --git a/tempest/api/volume/test_volume_absolute_limits.py b/tempest/api/volume/test_volume_absolute_limits.py
index 8e3c343..836e489 100644
--- a/tempest/api/volume/test_volume_absolute_limits.py
+++ b/tempest/api/volume/test_volume_absolute_limits.py
@@ -21,14 +21,14 @@
 CONF = config.CONF
 
 
-class AbsoluteLimitsV2Tests(base.BaseVolumeTest):
+class AbsoluteLimitsTests(base.BaseVolumeTest):
 
     # avoid existing volumes of pre-defined tenant
     force_tenant_isolation = True
 
     @classmethod
     def resource_setup(cls):
-        super(AbsoluteLimitsV2Tests, cls).resource_setup()
+        super(AbsoluteLimitsTests, cls).resource_setup()
         # Create a shared volume for tests
         cls.volume = cls.create_volume()
 
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index bbe1765..b4d22fe 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -19,18 +19,18 @@
 from tempest.lib import decorators
 
 
-class VolumesV2MetadataTest(base.BaseVolumeTest):
+class VolumesMetadataTest(base.BaseVolumeTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2MetadataTest, cls).resource_setup()
+        super(VolumesMetadataTest, cls).resource_setup()
         # Create a volume
         cls.volume = cls.create_volume()
 
     def tearDown(self):
         # Update the metadata to {}
         self.volumes_client.update_volume_metadata(self.volume['id'], {})
-        super(VolumesV2MetadataTest, self).tearDown()
+        super(VolumesMetadataTest, self).tearDown()
 
     @decorators.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
     def test_crud_volume_metadata(self):
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 22cbd85..bfb42c6 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -20,13 +20,13 @@
 from tempest.lib import decorators
 
 
-class VolumesV2TransfersTest(base.BaseVolumeTest):
+class VolumesTransfersTest(base.BaseVolumeTest):
 
     credentials = ['primary', 'alt', 'admin']
 
     @classmethod
     def setup_clients(cls):
-        super(VolumesV2TransfersTest, cls).setup_clients()
+        super(VolumesTransfersTest, cls).setup_clients()
 
         cls.client = cls.volumes_client
         cls.alt_client = cls.os_alt.volumes_client
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 4fc1a69..a2a3d27 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -25,12 +25,11 @@
 CONF = config.CONF
 
 
-class VolumesV2ActionsTest(base.BaseVolumeTest):
+class VolumesActionsTest(base.BaseVolumeTest):
 
     @classmethod
     def setup_clients(cls):
-        super(VolumesV2ActionsTest, cls).setup_clients()
-        cls.client = cls.volumes_client
+        super(VolumesActionsTest, cls).setup_clients()
         if CONF.service_available.glance:
             # Check if glance v1 is available to determine which client to use.
             if CONF.image_feature_enabled.api_v1:
@@ -44,7 +43,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ActionsTest, cls).resource_setup()
+        super(VolumesActionsTest, cls).resource_setup()
 
         # Create a test shared volume for attach/detach tests
         cls.volume = cls.create_volume()
@@ -56,23 +55,23 @@
         # Create a server
         server = self.create_server(wait_until='ACTIVE')
         # Volume is attached and detached successfully from an instance
-        self.client.attach_volume(self.volume['id'],
-                                  instance_uuid=server['id'],
-                                  mountpoint='/dev/%s' %
-                                             CONF.compute.volume_device_name)
-        waiters.wait_for_volume_resource_status(self.client,
+        self.volumes_client.attach_volume(self.volume['id'],
+                                          instance_uuid=server['id'],
+                                          mountpoint='/dev/%s' %
+                                          CONF.compute.volume_device_name)
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'in-use')
-        self.client.detach_volume(self.volume['id'])
-        waiters.wait_for_volume_resource_status(self.client,
+        self.volumes_client.detach_volume(self.volume['id'])
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'available')
 
     @decorators.idempotent_id('63e21b4c-0a0c-41f6-bfc3-7c2816815599')
     def test_volume_bootable(self):
         # Verify that a volume bootable flag is retrieved
         for bool_bootable in [True, False]:
-            self.client.set_bootable_volume(self.volume['id'],
-                                            bootable=bool_bootable)
-            fetched_volume = self.client.show_volume(
+            self.volumes_client.set_bootable_volume(self.volume['id'],
+                                                    bootable=bool_bootable)
+            fetched_volume = self.volumes_client.show_volume(
                 self.volume['id'])['volume']
             # Get Volume information
             # NOTE(masayukig): 'bootable' is "true" or "false" in the current
@@ -87,16 +86,18 @@
         # Create a server
         server = self.create_server(wait_until='ACTIVE')
         # Verify that a volume's attachment information is retrieved
-        self.client.attach_volume(self.volume['id'],
-                                  instance_uuid=server['id'],
-                                  mountpoint='/dev/%s' %
-                                             CONF.compute.volume_device_name)
-        waiters.wait_for_volume_resource_status(self.client, self.volume['id'],
+        self.volumes_client.attach_volume(self.volume['id'],
+                                          instance_uuid=server['id'],
+                                          mountpoint='/dev/%s' %
+                                          CONF.compute.volume_device_name)
+        waiters.wait_for_volume_resource_status(self.volumes_client,
+                                                self.volume['id'],
                                                 'in-use')
-        self.addCleanup(waiters.wait_for_volume_resource_status, self.client,
+        self.addCleanup(waiters.wait_for_volume_resource_status,
+                        self.volumes_client,
                         self.volume['id'], 'available')
-        self.addCleanup(self.client.detach_volume, self.volume['id'])
-        volume = self.client.show_volume(self.volume['id'])['volume']
+        self.addCleanup(self.volumes_client.detach_volume, self.volume['id'])
+        volume = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('attachments', volume)
         attachment = volume['attachments'][0]
 
@@ -115,7 +116,7 @@
         # there is no way to delete it from Cinder, so we delete it from Glance
         # using the Glance image_client and from Cinder via tearDownClass.
         image_name = data_utils.rand_name(self.__class__.__name__ + '-Image')
-        body = self.client.upload_volume(
+        body = self.volumes_client.upload_volume(
             self.volume['id'], image_name=image_name,
             disk_format=CONF.volume.disk_format)['os-volume_upload_image']
         image_id = body["image_id"]
@@ -123,30 +124,30 @@
                         self.image_client.delete_image,
                         image_id)
         waiters.wait_for_image_status(self.image_client, image_id, 'active')
-        waiters.wait_for_volume_resource_status(self.client,
+        waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 self.volume['id'], 'available')
 
     @decorators.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33')
     def test_reserve_unreserve_volume(self):
         # Mark volume as reserved.
-        body = self.client.reserve_volume(self.volume['id'])
+        body = self.volumes_client.reserve_volume(self.volume['id'])
         # To get the volume info
-        body = self.client.show_volume(self.volume['id'])['volume']
+        body = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('attaching', body['status'])
         # Unmark volume as reserved.
-        body = self.client.unreserve_volume(self.volume['id'])
+        body = self.volumes_client.unreserve_volume(self.volume['id'])
         # To get the volume info
-        body = self.client.show_volume(self.volume['id'])['volume']
+        body = self.volumes_client.show_volume(self.volume['id'])['volume']
         self.assertIn('available', body['status'])
 
     @decorators.idempotent_id('fff74e1e-5bd3-4b33-9ea9-24c103bc3f59')
     def test_volume_readonly_update(self):
         for readonly in [True, False]:
             # Update volume readonly
-            self.client.update_volume_readonly(self.volume['id'],
-                                               readonly=readonly)
+            self.volumes_client.update_volume_readonly(self.volume['id'],
+                                                       readonly=readonly)
             # Get Volume information
-            fetched_volume = self.client.show_volume(
+            fetched_volume = self.volumes_client.show_volume(
                 self.volume['id'])['volume']
             # NOTE(masayukig): 'readonly' is "True" or "False" in the current
             # cinder implementation. So we need to cast boolean values to str
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index e0b54b5..925beee 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
 from testtools import matchers
 
 from tempest.api.volume import base
@@ -25,11 +26,11 @@
 CONF = config.CONF
 
 
-class VolumesBackupsV2Test(base.BaseVolumeTest):
+class VolumesBackupsTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesBackupsV2Test, cls).skip_checks()
+        super(VolumesBackupsTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
@@ -65,7 +66,8 @@
         description = data_utils.rand_name("volume-backup-description")
         backup = self.create_backup(volume_id=volume['id'],
                                     name=backup_name,
-                                    description=description)
+                                    description=description,
+                                    container='container')
         self.assertEqual(backup_name, backup['name'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
@@ -74,6 +76,7 @@
         backup = self.backups_client.show_backup(backup['id'])['backup']
         self.assertEqual(backup_name, backup['name'])
         self.assertEqual(description, backup['description'])
+        self.assertEqual('container', backup['container'])
 
         # Get all backups with detail
         backups = self.backups_client.list_backups(
@@ -113,6 +116,8 @@
                                     name=backup_name, force=True)
         self.assertEqual(backup_name, backup['name'])
 
+    @testtools.skipUnless(CONF.service_available.glance,
+                          "Glance is not available")
     @decorators.idempotent_id('2a8ba340-dff2-4511-9db7-646f07156b15')
     def test_bootable_volume_backup_and_restore(self):
         # Create volume from image
diff --git a/tempest/api/volume/test_volumes_clone.py b/tempest/api/volume/test_volumes_clone.py
index 620f3d4..a6bbb0a 100644
--- a/tempest/api/volume/test_volumes_clone.py
+++ b/tempest/api/volume/test_volumes_clone.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.volume import base
 from tempest import config
 from tempest.lib import decorators
@@ -21,11 +23,11 @@
 CONF = config.CONF
 
 
-class VolumesV2CloneTest(base.BaseVolumeTest):
+class VolumesCloneTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2CloneTest, cls).skip_checks()
+        super(VolumesCloneTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
@@ -45,6 +47,8 @@
         self.assertEqual(volume['source_volid'], src_vol['id'])
         self.assertEqual(volume['size'], src_size + 1)
 
+    @testtools.skipUnless(CONF.service_available.glance,
+                          "Glance is not available")
     @decorators.idempotent_id('cbbcd7c6-5a6c-481a-97ac-ca55ab715d16')
     def test_create_from_bootable_volume(self):
         # Create volume from image
diff --git a/tempest/api/volume/test_volumes_clone_negative.py b/tempest/api/volume/test_volumes_clone_negative.py
index 28327f4..9169c19 100644
--- a/tempest/api/volume/test_volumes_clone_negative.py
+++ b/tempest/api/volume/test_volumes_clone_negative.py
@@ -22,11 +22,11 @@
 CONF = config.CONF
 
 
-class VolumesV2CloneNegativeTest(base.BaseVolumeTest):
+class VolumesCloneNegativeTest(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2CloneNegativeTest, cls).skip_checks()
+        super(VolumesCloneNegativeTest, cls).skip_checks()
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 3b09b60..84ecb22 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -18,7 +18,7 @@
 from tempest.lib import decorators
 
 
-class VolumesV2ExtendTest(base.BaseVolumeTest):
+class VolumesExtendTest(base.BaseVolumeTest):
 
     @decorators.idempotent_id('9a36df71-a257-43a5-9555-dc7c88e66e0e')
     def test_volume_extend(self):
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 9eff97a..65027bf 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -26,7 +26,7 @@
 CONF = config.CONF
 
 
-class VolumesV2GetTest(base.BaseVolumeTest):
+class VolumesGetTest(base.BaseVolumeTest):
 
     def _volume_create_get_update_delete(self, **kwargs):
         # Create a volume, Get it's details and Delete the volume
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index a852cea..0570797 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -23,7 +23,7 @@
 from tempest import test
 
 
-class VolumesV2ListTestJSON(base.BaseVolumeTest):
+class VolumesListTestJSON(base.BaseVolumeTest):
     # NOTE: This test creates a number of 1G volumes. To run successfully,
     # ensure that the backing file for the volume group that Nova uses
     # has space for at least 3 1G volumes!
@@ -57,7 +57,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ListTestJSON, cls).resource_setup()
+        super(VolumesListTestJSON, cls).resource_setup()
         cls.name = cls.VOLUME_FIELDS[1]
         # Create 3 test volumes
         cls.volume_list = []
@@ -78,11 +78,7 @@
                 params=params)['volumes']
 
         # Validating params of fetched volumes
-        # In v2, only list detail view includes items in params.
-        # In v1, list view and list detail view are same. So the
-        # following check should be run when 'with_detail' is True
-        # or v1 tests.
-        if with_detail or self._api_version == 1:
+        if with_detail:
             for volume in fetched_vol_list:
                 for key in params:
                     msg = "Failed to list volumes %s by %s" % \
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 8990a15..609a031 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -20,11 +20,11 @@
 from tempest import test
 
 
-class VolumesV2NegativeTest(base.BaseVolumeTest):
+class VolumesNegativeTest(base.BaseVolumeTest):
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2NegativeTest, cls).resource_setup()
+        super(VolumesNegativeTest, cls).resource_setup()
 
         # Create a test shared instance and volume for attach/detach tests
         cls.volume = cls.create_volume()
@@ -47,99 +47,70 @@
     @test.attr(type=['negative'])
     @decorators.idempotent_id('1ed83a8a-682d-4dfb-a30e-ee63ffd6c049')
     def test_create_volume_with_invalid_size(self):
-        # Should not be able to create volume with invalid size
-        # in request
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
+        # Should not be able to create volume with invalid size in request
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='#$%', params=params)
+                          self.volumes_client.create_volume, size='#$%')
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
     def test_create_volume_without_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='', params=params)
+                          self.volumes_client.create_volume, size='')
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('41331caa-eaf4-4001-869d-bc18c1869360')
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='0', params=params)
+                          self.volumes_client.create_volume, size='0')
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('8b472729-9eba-446e-a83b-916bdb34bef7')
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.BadRequest,
-                          self.volumes_client.create_volume,
-                          size='-1', params=params)
+                          self.volumes_client.create_volume, size='-1')
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('10254ed8-3849-454e-862e-3ab8e6aa01d2')
     def test_create_volume_with_nonexistent_volume_type(self):
         # Should not be able to create volume with non-existent volume type
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', volume_type=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', volume_type=data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('0c36f6ae-4604-4017-b0a9-34fdc63096f9')
     def test_create_volume_with_nonexistent_snapshot_id(self):
         # Should not be able to create volume with non-existent snapshot
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', snapshot_id=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', snapshot_id=data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('47c73e08-4be8-45bb-bfdf-0c4e79b88344')
     def test_create_volume_with_nonexistent_source_volid(self):
         # Should not be able to create volume with non-existent source volume
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
-                          size='1', source_volid=data_utils.rand_uuid(),
-                          params=params)
+                          size='1', source_volid=data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('0186422c-999a-480e-a026-6a665744c30c')
     def test_update_volume_with_nonexistent_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id=data_utils.rand_uuid(), params=params)
+                          volume_id=data_utils.rand_uuid())
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('e66e40d6-65e6-4e75-bdc7-636792fa152d')
     def test_update_volume_with_invalid_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id=data_utils.rand_name('invalid'),
-                          params=params)
+                          volume_id=data_utils.rand_name('invalid'))
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('72aeca85-57a5-4c1f-9057-f320f9ea575b')
     def test_update_volume_with_empty_volume_id(self):
-        v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
-        params = {'name': v_name}
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
-                          volume_id='', params=params)
+                          volume_id='')
 
     @test.attr(type=['negative'])
     @decorators.idempotent_id('30799cfd-7ee4-446c-b66c-45b383ed211b')
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 82f456b..504875b 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -21,17 +21,17 @@
 CONF = config.CONF
 
 
-class VolumesV2SnapshotTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotTestJSON, cls).skip_checks()
+        super(VolumesSnapshotTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2SnapshotTestJSON, cls).resource_setup()
+        super(VolumesSnapshotTestJSON, cls).resource_setup()
         cls.volume_origin = cls.create_volume()
 
     @decorators.idempotent_id('b467b54c-07a4-446d-a1cf-651dedcc3ff1')
diff --git a/tempest/api/volume/test_volumes_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
index 0ea8ec7..68eb181 100644
--- a/tempest/api/volume/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -17,17 +17,17 @@
 CONF = config.CONF
 
 
-class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotListTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+        super(VolumesSnapshotListTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
+        super(VolumesSnapshotListTestJSON, cls).resource_setup()
         volume_origin = cls.create_volume()
         # Create snapshots with params
         for _ in range(2):
@@ -97,7 +97,6 @@
         self._list_snapshots_by_param_limit(limit=100000,
                                             expected_elements=len(snap_list))
 
-    @decorators.skip_because(bug='1540893')
     @decorators.idempotent_id('e3b44b7f-ae87-45b5-8a8c-66110eb24d0a')
     def test_snapshot_list_param_limit_equals_zero(self):
         # List returns zero elements
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 285d3f5..2e30d04 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -20,11 +20,11 @@
 CONF = config.CONF
 
 
-class VolumesV2SnapshotNegativeTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotNegativeTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotNegativeTestJSON, cls).skip_checks()
+        super(VolumesSnapshotNegativeTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
@@ -68,3 +68,17 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.snapshots_client.list_snapshots,
                           limit='invalid')
+
+    @test.attr(type=['negative'])
+    @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
+    def test_list_snapshots_invalid_param_sort(self):
+        self.assertRaises(lib_exc.BadRequest,
+                          self.snapshots_client.list_snapshots,
+                          sort_key='invalid')
+
+    @test.attr(type=['negative'])
+    @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
+    def test_list_snapshots_invalid_param_marker(self):
+        self.assertRaises(lib_exc.NotFound,
+                          self.snapshots_client.list_snapshots,
+                          marker=data_utils.rand_uuid())
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index d2328c8..e7adcd6 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -22,8 +22,8 @@
 from tempest.lib import decorators
 
 
-class VolumesV2ListTestJSON(base.BaseVolumeTest):
-    """volumes v2 specific tests.
+class VolumesListTestJSON(base.BaseVolumeTest):
+    """volumes tests.
 
     This test creates a number of 1G volumes. To run successfully,
     ensure that the backing file for the volume group that Nova uses
@@ -34,7 +34,7 @@
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2ListTestJSON, cls).resource_setup()
+        super(VolumesListTestJSON, cls).resource_setup()
 
         # Create 3 test volumes
         # NOTE(zhufl): When using pre-provisioned credentials, the project
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_list.py b/tempest/api/volume/v2/test_volumes_snapshots_list.py
index d385f65..bfed67b 100644
--- a/tempest/api/volume/v2/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/v2/test_volumes_snapshots_list.py
@@ -20,17 +20,17 @@
 CONF = config.CONF
 
 
-class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+class VolumesSnapshotListTestJSON(base.BaseVolumeTest):
 
     @classmethod
     def skip_checks(cls):
-        super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+        super(VolumesSnapshotListTestJSON, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
+        super(VolumesSnapshotListTestJSON, cls).resource_setup()
         cls.snapshot_id_list = []
         # Create a volume
         volume_origin = cls.create_volume()
@@ -46,7 +46,7 @@
         self.assertNotEmpty(snap_list)
         if sort_key is 'display_name':
             sort_key = 'name'
-        # Note: On Cinder V2 API, 'display_name' works as a sort key
+        # Note: On Cinder API, 'display_name' works as a sort key
         # on a request, a volume name appears as 'name' on the response.
         # So Tempest needs to change the key name here for this inconsistent
         # API behavior.
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_negative.py b/tempest/api/volume/v2/test_volumes_snapshots_negative.py
deleted file mode 100644
index 4608b07..0000000
--- a/tempest/api/volume/v2/test_volumes_snapshots_negative.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2017 Red Hat, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.api.volume import base
-from tempest 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/api/volume/v3/__init__.py b/tempest/api/volume/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/api/volume/v3/__init__.py
+++ /dev/null
diff --git a/tempest/api/volume/v3/base.py b/tempest/api/volume/v3/base.py
deleted file mode 100644
index 7f76e6f..0000000
--- a/tempest/api/volume/v3/base.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2016 Andrew Kerr
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-from tempest.api.volume import api_microversion_fixture
-from tempest.api.volume import base
-from tempest import config
-from tempest.lib.common import api_version_utils
-
-CONF = config.CONF
-
-
-class VolumesV3Test(api_version_utils.BaseMicroversionTest,
-                    base.BaseVolumeTest):
-    """Base test case class for all v3 Cinder API tests."""
-
-    _api_version = 3
-
-    @classmethod
-    def skip_checks(cls):
-        super(VolumesV3Test, cls).skip_checks()
-        api_version_utils.check_skip_with_microversion(
-            cls.min_microversion, cls.max_microversion,
-            CONF.volume.min_microversion, CONF.volume.max_microversion)
-
-    @classmethod
-    def resource_setup(cls):
-        super(VolumesV3Test, cls).resource_setup()
-        cls.request_microversion = (
-            api_version_utils.select_request_microversion(
-                cls.min_microversion,
-                CONF.volume.min_microversion))
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV3Test, cls).setup_clients()
-        cls.messages_client = cls.os.volume_v3_messages_client
-        cls.versions_client = cls.os.volume_v3_versions_client
-
-    def setUp(self):
-        super(VolumesV3Test, self).setUp()
-        self.useFixture(api_microversion_fixture.APIMicroversionFixture(
-            self.request_microversion))
-
-
-class VolumesV3AdminTest(VolumesV3Test,
-                         base.BaseVolumeAdminTest):
-    """Base test case class for all v3 Volume Admin API tests."""
-
-    credentials = ['primary', 'admin']
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesV3AdminTest, cls).setup_clients()
-        cls.admin_messages_client = cls.os_adm.volume_v3_messages_client
-        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
diff --git a/tempest/clients.py b/tempest/clients.py
index 0654110..71c3d41 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -229,6 +229,8 @@
         self.groups_client = self.identity_v3.GroupsClient(**params_v3)
         self.identity_versions_v3_client = self.identity_v3.VersionsClient(
             **params_v3)
+        self.oauth_consumers_client = self.identity_v3.OAUTHConsumerClient(
+            **params_v3)
 
         # Token clients do not use the catalog. They only need default_params.
         # They read auth_url, so they should only be set if the corresponding
@@ -262,6 +264,7 @@
         self.snapshot_manage_v2_client = self.volume_v2.SnapshotManageClient()
         self.snapshots_client = self.volume_v1.SnapshotsClient()
         self.snapshots_v2_client = self.volume_v2.SnapshotsClient()
+        self.volume_manage_v2_client = self.volume_v2.VolumeManageClient()
         self.volumes_client = self.volume_v1.VolumesClient()
         self.volumes_v2_client = self.volume_v2.VolumesClient()
         self.volume_v3_messages_client = self.volume_v3.MessagesClient()
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index b2667e5..38daffe 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -14,8 +14,13 @@
 #    limitations under the License.
 
 import base64
+import socket
+import struct
 import textwrap
 
+import six
+from six.moves.urllib import parse as urlparse
+
 from oslo_log import log as logging
 from oslo_utils import excutils
 
@@ -25,6 +30,11 @@
 from tempest.lib.common import rest_client
 from tempest.lib.common.utils import data_utils
 
+if six.PY2:
+    ord_func = ord
+else:
+    ord_func = int
+
 CONF = config.CONF
 
 LOG = logging.getLogger(__name__)
@@ -132,11 +142,7 @@
     if volume_backed:
         volume_name = data_utils.rand_name(__name__ + '-volume')
         volumes_client = clients.volumes_v2_client
-        name_field = 'name'
-        if not CONF.volume_feature_enabled.api_v2:
-            volumes_client = clients.volumes_client
-            name_field = 'display_name'
-        params = {name_field: volume_name,
+        params = {'name': volume_name,
                   'imageRef': image_id,
                   'size': CONF.volume.volume_size}
         volume = volumes_client.create_volume(**params)
@@ -226,3 +232,87 @@
             servers_client.shelve_offload_server(server_id)
             waiters.wait_for_server_status(servers_client, server_id,
                                            'SHELVED_OFFLOADED')
+
+
+def create_websocket(url):
+    url = urlparse.urlparse(url)
+    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    client_socket.connect((url.hostname, url.port))
+    # Turn the Socket into a WebSocket to do the communication
+    return _WebSocket(client_socket, url)
+
+
+class _WebSocket(object):
+    def __init__(self, client_socket, url):
+        """Contructor for the WebSocket wrapper to the socket."""
+        self._socket = client_socket
+        # Upgrade the HTTP connection to a WebSocket
+        self._upgrade(url)
+
+    def receive_frame(self):
+        """Wrapper for receiving data to parse the WebSocket frame format"""
+        # We need to loop until we either get some bytes back in the frame
+        # or no data was received (meaning the socket was closed).  This is
+        # done to handle the case where we get back some empty frames
+        while True:
+            header = self._socket.recv(2)
+            # If we didn't receive any data, just return None
+            if len(header) == 0:
+                return None
+            # We will make the assumption that we are only dealing with
+            # frames less than 125 bytes here (for the negotiation) and
+            # that only the 2nd byte contains the length, and since the
+            # server doesn't do masking, we can just read the data length
+            if ord_func(header[1]) & 127 > 0:
+                return self._socket.recv(ord_func(header[1]) & 127)
+
+    def send_frame(self, data):
+        """Wrapper for sending data to add in the WebSocket frame format."""
+        frame_bytes = list()
+        # For the first byte, want to say we are sending binary data (130)
+        frame_bytes.append(130)
+        # Only sending negotiation data so don't need to worry about > 125
+        # We do need to add the bit that says we are masking the data
+        frame_bytes.append(len(data) | 128)
+        # We don't really care about providing a random mask for security
+        # So we will just hard-code a value since a test program
+        mask = [7, 2, 1, 9]
+        for i in range(len(mask)):
+            frame_bytes.append(mask[i])
+        # Mask each of the actual data bytes that we are going to send
+        for i in range(len(data)):
+            frame_bytes.append(ord_func(data[i]) ^ mask[i % 4])
+        # Convert our integer list to a binary array of bytes
+        frame_bytes = struct.pack('!%iB' % len(frame_bytes), * frame_bytes)
+        self._socket.sendall(frame_bytes)
+
+    def close(self):
+        """Helper method to close the connection."""
+        # Close down the real socket connection and exit the test program
+        if self._socket is not None:
+            self._socket.shutdown(1)
+            self._socket.close()
+            self._socket = None
+
+    def _upgrade(self, url):
+        """Upgrade the HTTP connection to a WebSocket and verify."""
+        # The real request goes to the /websockify URI always
+        reqdata = 'GET /websockify HTTP/1.1\r\n'
+        reqdata += 'Host: %s:%s\r\n' % (url.hostname, url.port)
+        # Tell the HTTP Server to Upgrade the connection to a WebSocket
+        reqdata += 'Upgrade: websocket\r\nConnection: Upgrade\r\n'
+        # The token=xxx is sent as a Cookie not in the URI
+        reqdata += 'Cookie: %s\r\n' % url.query
+        # Use a hard-coded WebSocket key since a test program
+        reqdata += 'Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n'
+        reqdata += 'Sec-WebSocket-Version: 13\r\n'
+        # We are choosing to use binary even though browser may do Base64
+        reqdata += 'Sec-WebSocket-Protocol: binary\r\n\r\n'
+        # Send the HTTP GET request and get the response back
+        self._socket.sendall(reqdata.encode('utf8'))
+        self.response = data = self._socket.recv(4096)
+        # Loop through & concatenate all of the data in the response body
+        while len(data) > 0 and self.response.find(b'\r\n\r\n') < 0:
+            data = self._socket.recv(4096)
+            self.response += data
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 6dfc579..9319d2a 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -50,6 +50,8 @@
             ping_count=CONF.validation.ping_count,
             ping_size=CONF.validation.ping_size)
 
+    # Note that this method will not work on SLES11 guests, as they do
+    # not support the TYPE column on lsblk
     def get_disks(self):
         # Select root disk devices as shown by lsblk
         command = 'lsblk -lb --nodeps'
@@ -79,12 +81,6 @@
         cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
         return self.exec_command(cmd)
 
-    def set_mac_address(self, nic, address):
-        self.set_nic_state(nic=nic, state="down")
-        cmd = "sudo ip link set dev {0} address {1}".format(nic, address)
-        self.exec_command(cmd)
-        self.set_nic_state(nic=nic, state="up")
-
     def get_mac_address(self, nic=""):
         show_nic = "show {nic} ".format(nic=nic) if nic else ""
         cmd = "ip addr %s| awk '/ether/ {print $2}'" % show_nic
@@ -100,15 +96,6 @@
         nic = self.exec_command(cmd)
         return nic.strip().strip(":").lower()
 
-    def assign_static_ip(self, nic, addr, network_mask_bits=28):
-        cmd = "sudo ip addr add {ip}/{mask} dev {nic}".format(
-            ip=addr, mask=network_mask_bits, nic=nic)
-        return self.exec_command(cmd)
-
-    def set_nic_state(self, nic, state="up"):
-        cmd = "sudo ip link set {nic} {state}".format(nic=nic, state=state)
-        return self.exec_command(cmd)
-
     def get_dns_servers(self):
         cmd = 'cat /etc/resolv.conf'
         resolve_file = self.exec_command(cmd).strip().split('\n')
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 3e5600c..9c83c99 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -261,16 +261,16 @@
         time.sleep(client.build_interval)
 
 
-def wait_for_interface_status(client, server, port_id, status):
+def wait_for_interface_status(client, server_id, port_id, status):
     """Waits for an interface to reach a given status."""
-    body = (client.show_interface(server, port_id)
+    body = (client.show_interface(server_id, port_id)
             ['interfaceAttachment'])
     interface_status = body['port_state']
     start = int(time.time())
 
     while(interface_status != status):
         time.sleep(client.build_interval)
-        body = (client.show_interface(server, port_id)
+        body = (client.show_interface(server_id, port_id)
                 ['interfaceAttachment'])
         interface_status = body['port_state']
 
diff --git a/tempest/config.py b/tempest/config.py
index 93b8ab2..35eb187 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -291,7 +291,9 @@
     cfg.StrOpt('volume_device_name',
                default='vdb',
                help="Expected device name when a volume is attached to "
-                    "an instance"),
+                    "an instance. Not all hypervisors guarantee that they "
+                    "will respect the user defined device name, tests may "
+                    "fail if inappropriate device name is set."),
     cfg.IntOpt('shelved_offload_time',
                default=0,
                help='Time in seconds before a shelved instance is eligible '
@@ -503,7 +505,7 @@
                      "users can specify."),
     cfg.ListOpt('disk_formats',
                 default=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2',
-                         'vdi', 'iso'],
+                         'vdi', 'iso', 'vhdx'],
                 help="A list of image's disk formats "
                      "users can specify.")
 ]
@@ -619,7 +621,10 @@
                      "in L3 agent scheduler test. Extra resources need to be "
                      "provisioned in order to bind router to L3 agent in the "
                      "Liberty release or older, and are not required since "
-                     "the Mitaka release.")
+                     "the Mitaka release.",
+                deprecated_for_removal=True,
+                deprecated_reason='This config switch was added for Liberty '
+                                  'which is not supported anymore.')
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -681,9 +686,7 @@
                help='Default IP version for ssh connections.'),
     cfg.IntOpt('ping_timeout',
                default=120,
-               help='Timeout in seconds to wait for ping to succeed.',
-               deprecated_opts=[cfg.DeprecatedOpt('ping_timeout',
-                                                  group='compute')]),
+               help='Timeout in seconds to wait for ping to succeed.'),
     cfg.IntOpt('connect_timeout',
                default=60,
                help='Timeout in seconds to wait for the TCP connection to be '
@@ -693,13 +696,7 @@
                help='Timeout in seconds to wait for the ssh banner.'),
     cfg.StrOpt('image_ssh_user',
                default="root",
-               help="User name used to authenticate to an instance.",
-               deprecated_opts=[cfg.DeprecatedOpt('image_ssh_user',
-                                                  group='compute'),
-                                cfg.DeprecatedOpt('ssh_user',
-                                                  group='compute'),
-                                cfg.DeprecatedOpt('ssh_user',
-                                                  group='scenario')]),
+               help="User name used to authenticate to an instance."),
     cfg.StrOpt('image_ssh_password',
                default="password",
                help="Password used to authenticate to an instance."),
@@ -724,9 +721,7 @@
     cfg.StrOpt('network_for_ssh',
                default='public',
                help="Network used for SSH connections. Ignored if "
-                    "connect_method=floating.",
-               deprecated_opts=[cfg.DeprecatedOpt('network_for_ssh',
-                                                  group='compute')]),
+                    "connect_method=floating."),
 ]
 
 volume_group = cfg.OptGroup(name='volume',
@@ -770,6 +765,12 @@
     cfg.IntOpt('volume_size',
                default=1,
                help='Default size in GB for volumes created by volumes tests'),
+    cfg.ListOpt('manage_volume_ref',
+                default=['source-name', 'volume-%s'],
+                help="A reference to existing volume for volume manage. "
+                     "It contains two elements, the first is ref type "
+                     "(like 'source-name', 'source-id', etc), the second is "
+                     "volume name template used in storage backend"),
     cfg.StrOpt('min_microversion',
                default=None,
                help="Lower version of the test target microversion range. "
@@ -809,6 +810,9 @@
     cfg.BoolOpt('manage_snapshot',
                 default=False,
                 help='Runs Cinder manage snapshot tests'),
+    cfg.BoolOpt('manage_volume',
+                default=False,
+                help='Runs Cinder manage volume tests'),
     cfg.ListOpt('api_extensions',
                 default=['all'],
                 help='A list of enabled volume extensions with a special '
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index 4ccca6f..33a7757 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -100,8 +100,10 @@
                 'id': {'type': 'string'},
                 'links': parameter_types.links
             },
-            'additionalProperties': False,
-            'required': ['id', 'links']
+            # NOTE(gmann): This will be empty object if there is no
+            # flavor info present in DB. This can happen when flavor info is
+            # deleted after server creation.
+            'additionalProperties': False
         },
         'fault': {
             'type': 'object',
@@ -564,3 +566,19 @@
 update_attached_volume = {
     'status_code': [202]
 }
+
+evacuate_server = {
+    'status_code': [200]
+}
+
+evacuate_server_with_admin_pass = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'adminPass': {'type': 'string'}
+        },
+        'additionalProperties': False,
+        'required': ['adminPass']
+    }
+}
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index eafde44..e911776 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -29,7 +29,7 @@
 DECORATOR_MODULE = 'decorators'
 DECORATOR_NAME = 'idempotent_id'
 DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
-IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
+IMPORT_LINE = 'from tempest.lib import %s' % DECORATOR_MODULE
 DECORATOR_TEMPLATE = "@%s.%s('%%s')" % (DECORATOR_MODULE,
                                         DECORATOR_NAME)
 UNIT_TESTS_EXCLUDE = 'tempest.tests'
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index b37afb3..0d355a1 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -814,3 +814,19 @@
         schema = self.get_schema(self.schema_versions_info)
         self.validate_response(schema.delete_tag, resp, body)
         return rest_client.ResponseBody(resp, body)
+
+    def evacuate_server(self, server_id, **kwargs):
+        """Evacuate the given server.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/compute/#evacuate-server-evacuate-action
+        """
+        if self.enable_instance_password:
+            evacuate_schema = schema.evacuate_server_with_admin_pass
+        else:
+            evacuate_schema = schema.evacuate_server
+
+        return self.action(server_id, 'evacuate',
+                           evacuate_schema,
+                           **kwargs)
diff --git a/tempest/lib/services/identity/v3/__init__.py b/tempest/lib/services/identity/v3/__init__.py
index 88801e7..1489b50 100644
--- a/tempest/lib/services/identity/v3/__init__.py
+++ b/tempest/lib/services/identity/v3/__init__.py
@@ -20,6 +20,8 @@
 from tempest.lib.services.identity.v3.identity_client import IdentityClient
 from tempest.lib.services.identity.v3.inherited_roles_client import \
     InheritedRolesClient
+from tempest.lib.services.identity.v3.oauth_consumers_client import \
+    OAUTHConsumerClient
 from tempest.lib.services.identity.v3.policies_client import PoliciesClient
 from tempest.lib.services.identity.v3.projects_client import ProjectsClient
 from tempest.lib.services.identity.v3.regions_client import RegionsClient
@@ -36,4 +38,5 @@
            'GroupsClient', 'IdentityClient', 'InheritedRolesClient',
            'PoliciesClient', 'ProjectsClient', 'RegionsClient',
            'RoleAssignmentsClient', 'RolesClient', 'ServicesClient',
-           'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient']
+           'V3TokenClient', 'TrustsClient', 'UsersClient', 'VersionsClient',
+           'OAUTHConsumerClient']
diff --git a/tempest/lib/services/identity/v3/oauth_consumers_client.py b/tempest/lib/services/identity/v3/oauth_consumers_client.py
new file mode 100644
index 0000000..582c9e0
--- /dev/null
+++ b/tempest/lib/services/identity/v3/oauth_consumers_client.py
@@ -0,0 +1,95 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class OAUTHConsumerClient(rest_client.RestClient):
+    api_version = "v3"
+
+    def create_consumer(self, description=None):
+        """Creates a consumer.
+
+        :param str description: Optional field to add notes about the consumer
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#create-consumer
+        """
+        post_body = {"description": description}
+        post_body = json.dumps({'consumer': post_body})
+        resp, body = self.post('OS-OAUTH1/consumers', post_body)
+        self.expected_success(201, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_consumer(self, consumer_id):
+        """Deletes a consumer.
+
+        :param str consumer_id: The ID of the consumer that will be deleted
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#delete-consumer
+        """
+        resp, body = self.delete('OS-OAUTH1/consumers/%s' % consumer_id)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def update_consumer(self, consumer_id, description=None):
+        """Updates a consumer.
+
+        :param str consumer_id: The ID of the consumer that will be updated
+        :param str description: Optional field to add notes about the consumer
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#update-consumers
+        """
+        post_body = {"description": description}
+        post_body = json.dumps({'consumer': post_body})
+        resp, body = self.patch('OS-OAUTH1/consumers/%s' % consumer_id,
+                                post_body)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_consumer(self, consumer_id):
+        """Show consumer details.
+
+        :param str consumer_id: The ID of the consumer that will be shown
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#show-consumer-details
+        """
+        resp, body = self.get('OS-OAUTH1/consumers/%s' % consumer_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_consumers(self):
+        """List all consumers.
+
+        For more information, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3-ext/#list-consumers
+        """
+        resp, body = self.get('OS-OAUTH1/consumers')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/roles_client.py b/tempest/lib/services/identity/v3/roles_client.py
index 0df23ce..43e3c01 100644
--- a/tempest/lib/services/identity/v3/roles_client.py
+++ b/tempest/lib/services/identity/v3/roles_client.py
@@ -214,6 +214,18 @@
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
 
+    def list_all_role_inference_rules(self):
+        """Lists all role inference rules.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/identity/v3/index.html#list-all-role-inference-rules
+        """
+        resp, body = self.get('role_inferences')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
     def check_role_inference_rule(self, prior_role, implies_role):
         """Check a role inference rule."""
         resp, body = self.head('roles/%s/implies/%s' %
diff --git a/tempest/lib/services/volume/v2/__init__.py b/tempest/lib/services/volume/v2/__init__.py
index 8acad0f..b4eb771 100644
--- a/tempest/lib/services/volume/v2/__init__.py
+++ b/tempest/lib/services/volume/v2/__init__.py
@@ -31,10 +31,12 @@
     SnapshotManageClient
 from tempest.lib.services.volume.v2.snapshots_client import SnapshotsClient
 from tempest.lib.services.volume.v2.types_client import TypesClient
+from tempest.lib.services.volume.v2.volume_manage_client import \
+    VolumeManageClient
 from tempest.lib.services.volume.v2.volumes_client import VolumesClient
 
 __all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
            'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
            'ServicesClient', 'SnapshotsClient', 'TypesClient', 'VolumesClient',
            'LimitsClient', 'CapabilitiesClient', 'SchedulerStatsClient',
-           'SnapshotManageClient']
+           'SnapshotManageClient', 'VolumeManageClient']
diff --git a/tempest/lib/services/volume/v2/encryption_types_client.py b/tempest/lib/services/volume/v2/encryption_types_client.py
index 8b01f11..eeff537 100755
--- a/tempest/lib/services/volume/v2/encryption_types_client.py
+++ b/tempest/lib/services/volume/v2/encryption_types_client.py
@@ -67,3 +67,17 @@
             "/types/%s/encryption/provider" % volume_type_id)
         self.expected_success(202, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def update_encryption_type(self, volume_type_id, **kwargs):
+        """Update an encryption type for an existing volume type.
+
+        TODO: Current api-site doesn't contain this API description.
+        After fixing the api-site, we need to fix here also for putting
+        the link to api-site.
+        """
+        url = "/types/%s/encryption/provider" % volume_type_id
+        put_body = json.dumps({'encryption': kwargs})
+        resp, body = self.put(url, put_body)
+        body = json.loads(body)
+        self.expected_success(200, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
index 2bdf1b1..983ed89 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -27,7 +27,8 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots-with-details
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-snapshots
         """
         url = 'snapshots'
         if detail:
@@ -45,7 +46,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-details
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -71,7 +72,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -84,7 +85,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-snapshot
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -136,7 +137,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-snapshot-metadata
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -149,7 +150,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-snapshot-metadata
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v2/types_client.py b/tempest/lib/services/volume/v2/types_client.py
index 31597d7..5d30615 100644
--- a/tempest/lib/services/volume/v2/types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -41,7 +41,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-types
         """
         url = 'types'
         if params:
@@ -57,7 +57,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-volume-type-details
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -70,7 +70,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-type
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -83,7 +83,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#delete-volume-type
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -138,7 +138,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -156,7 +156,7 @@
                      updated value.
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-type-extra-specs-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-extra-specs-for-a-volume-type
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
@@ -170,7 +170,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#add-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#add-private-volume-type-access
         """
         post_body = json.dumps({'addProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -183,7 +183,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#remove-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#remove-private-volume-type-access
         """
         post_body = json.dumps({'removeProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -196,7 +196,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-type-access-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-private-volume-type-access-details
         """
         url = 'types/%s/os-volume-type-access' % volume_type_id
         resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/volume_manage_client.py b/tempest/lib/services/volume/v2/volume_manage_client.py
new file mode 100644
index 0000000..12f4240
--- /dev/null
+++ b/tempest/lib/services/volume/v2/volume_manage_client.py
@@ -0,0 +1,37 @@
+# Copyright 2017 FiberHome Telecommunication Technologies CO.,LTD
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class VolumeManageClient(rest_client.RestClient):
+    """Volume manage V2 client."""
+
+    api_version = "v2"
+
+    def manage_volume(self, **kwargs):
+        """Manage existing volume.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#manage-existing-volume
+        """
+        post_body = json.dumps({'volume': kwargs})
+        resp, body = self.post('os-volume-manage', post_body)
+        self.expected_success(202, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index 8b8e249..72823c0 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -65,7 +65,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -78,7 +78,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -106,7 +106,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#attach-volume-to-server
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -163,7 +163,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#extend-volume-size
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -176,7 +176,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-status-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#reset-volume-statuses
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -188,7 +188,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-volume-transfer
         """
         post_body = json.dumps({'transfer': kwargs})
         resp, body = self.post('os-volume-transfer', post_body)
@@ -209,7 +209,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#list-volume-transfers
         """
         url = 'os-volume-transfer'
         if params:
@@ -230,7 +230,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#accept-volume-transfer
         """
         url = 'os-volume-transfer/%s/accept' % transfer_id
         post_body = json.dumps({'accept': kwargs})
@@ -307,7 +307,7 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#update-volume-image-metadata-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#set-image-metadata-for-volume
         """
         post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
         url = "volumes/%s/action" % (volume_id)
@@ -344,10 +344,22 @@
 
         For a full list of available parameters, please refer to the official
         API reference:
-        http://developer.openstack.org/api-ref/block-storage/v2/#show_backend_capabilities-v2
+        http://developer.openstack.org/api-ref/block-storage/v2/#show-back-end-capabilities
         """
         url = 'capabilities/%s' % host
         resp, body = self.get(url)
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def unmanage_volume(self, volume_id):
+        """Unmanage volume.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://developer.openstack.org/api-ref/block-storage/v2/#unmanage-volume
+        """
+        post_body = json.dumps({'os-unmanage': {}})
+        resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+        self.expected_success(202, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 727afd6..c1270c7 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -79,13 +79,8 @@
         cls.security_groups_client = cls.manager.security_groups_client
         cls.security_group_rules_client = (
             cls.manager.security_group_rules_client)
-
-        if CONF.volume_feature_enabled.api_v2:
-            cls.volumes_client = cls.manager.volumes_v2_client
-            cls.snapshots_client = cls.manager.snapshots_v2_client
-        else:
-            cls.volumes_client = cls.manager.volumes_client
-            cls.snapshots_client = cls.manager.snapshots_client
+        cls.volumes_client = cls.manager.volumes_v2_client
+        cls.snapshots_client = cls.manager.snapshots_v2_client
 
     # ## Test functions library
     #
@@ -235,12 +230,7 @@
                         volume['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.volumes_client.delete_volume, volume['id'])
-
-        # NOTE(e0ne): Cinder API v2 uses name instead of display_name
-        if 'display_name' in volume:
-            self.assertEqual(name, volume['display_name'])
-        else:
-            self.assertEqual(name, volume['name'])
+        self.assertEqual(name, volume['name'])
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
         # The volume retrieved on creation has a non-up-to-date status.
@@ -888,16 +878,16 @@
                       show_floatingip(floatingip_id)['floatingip'])
             return status == result['status']
 
-        test_utils.call_until_true(refresh,
-                                   CONF.network.build_timeout,
-                                   CONF.network.build_interval)
-        floating_ip = self.floating_ips_client.show_floatingip(
-            floatingip_id)['floatingip']
-        self.assertEqual(status, floating_ip['status'],
-                         message="FloatingIP: {fp} is at status: {cst}. "
-                                 "failed  to reach status: {st}"
-                         .format(fp=floating_ip, cst=floating_ip['status'],
-                                 st=status))
+        if not test_utils.call_until_true(refresh,
+                                          CONF.network.build_timeout,
+                                          CONF.network.build_interval):
+            floating_ip = self.floating_ips_client.show_floatingip(
+                floatingip_id)['floatingip']
+            self.assertEqual(status, floating_ip['status'],
+                             message="FloatingIP: {fp} is at status: {cst}. "
+                                     "failed  to reach status: {st}"
+                             .format(fp=floating_ip, cst=floating_ip['status'],
+                                     st=status))
         LOG.info("FloatingIP: {fp} is at status: {st}"
                  .format(fp=floating_ip, st=status))
 
@@ -1251,14 +1241,9 @@
     @classmethod
     def setup_clients(cls):
         super(EncryptionScenarioTest, cls).setup_clients()
-        if CONF.volume_feature_enabled.api_v2:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
-            cls.admin_encryption_types_client =\
-                cls.os_adm.encryption_types_v2_client
-        else:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_client
-            cls.admin_encryption_types_client =\
-                cls.os_adm.encryption_types_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+        cls.admin_encryption_types_client =\
+            cls.os_adm.encryption_types_v2_client
 
     def create_encryption_type(self, client=None, type_id=None, provider=None,
                                key_size=None, cipher=None,
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 15a0a70..dec0ad0 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -286,10 +286,11 @@
                                               % CONF.network.build_timeout)
 
         num, new_nic = self.diff_list[0]
-        ssh_client.assign_static_ip(
-            nic=new_nic, addr=new_port['fixed_ips'][0]['ip_address'],
-            network_mask_bits=CONF.network.project_network_mask_bits)
-        ssh_client.set_nic_state(nic=new_nic)
+        ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
+                                new_port['fixed_ips'][0]['ip_address'],
+                                CONF.network.project_network_mask_bits,
+                                new_nic))
+        ssh_client.exec_command("sudo ip link set %s up" % new_nic)
 
     def _get_server_nics(self, ssh_client):
         reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
@@ -833,7 +834,13 @@
         peer_address = peer['addresses'][self.new_net['name']][0]['addr']
         self.check_remote_connectivity(ssh_client, dest=peer_address,
                                        nic=spoof_nic, should_succeed=True)
-        ssh_client.set_mac_address(spoof_nic, spoof_mac)
+        # Set a mac address by making nic down temporary
+        cmd = ("sudo ip link set {nic} down;"
+               "sudo ip link set dev {nic} address {mac};"
+               "sudo ip link set {nic} up").format(nic=spoof_nic,
+                                                   mac=spoof_mac)
+        ssh_client.exec_command(cmd)
+
         new_mac = ssh_client.get_mac_address(nic=spoof_nic)
         self.assertEqual(spoof_mac, new_mac)
         self.check_remote_connectivity(ssh_client, dest=peer_address,
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index cfd83d0..4e8b004 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -153,7 +153,8 @@
                                   "ports: %s")
                          % (network_id, ports))
         mac6 = ports[0]
-        ssh.set_nic_state(ssh.get_nic_name_by_mac(mac6))
+        nic = ssh.get_nic_name_by_mac(mac6)
+        ssh.exec_command("sudo ip link set %s up" % nic)
 
     def _prepare_and_test(self, address6_mode, n_subnets6=1, dualnet=False):
         net_list = self.prepare_network(address6_mode=address6_mode,
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 1960e9a..cc3687f 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -37,13 +37,6 @@
     """
 
     @classmethod
-    def skip_checks(cls):
-        super(TestServerAdvancedOps, cls).skip_checks()
-        if CONF.compute.flavor_ref_alt == CONF.compute.flavor_ref:
-            msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
-            raise cls.skipException(msg)
-
-    @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
         super(TestServerAdvancedOps, cls).setup_credentials()
@@ -52,6 +45,11 @@
     @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
+    @testtools.skipUnless(CONF.compute.flavor_ref !=
+                          CONF.compute.flavor_ref_alt
+                          and CONF.compute.flavor_ref_alt != "",
+                          'The flavor_ref_alt option should not be empty and '
+                          'should not be identical with flavor_ref')
     @test.services('compute', 'volume')
     def test_resize_volume_backed_server_confirm(self):
         # We create an instance for use in this test
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 96b423d..5f5d701 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -68,10 +68,7 @@
                                                 volume['id'], 'available')
         waiters.wait_for_volume_resource_status(self.snapshots_client,
                                                 snapshot['id'], 'available')
-        if 'display_name' in snapshot:
-            self.assertEqual(snapshot_name, snapshot['display_name'])
-        else:
-            self.assertEqual(snapshot_name, snapshot['name'])
+        self.assertEqual(snapshot_name, snapshot['name'])
         return snapshot
 
     def _wait_for_volume_available_on_the_system(self, ip_address,
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index ae0230e..888bff2 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -81,13 +81,7 @@
         self.addCleanup(self.snapshots_client.delete_snapshot, snap['id'])
         waiters.wait_for_volume_resource_status(self.snapshots_client,
                                                 snap['id'], 'available')
-
-        # NOTE(e0ne): Cinder API v2 uses name instead of display_name
-        if 'display_name' in snap:
-            self.assertEqual(snap_name, snap['display_name'])
-        else:
-            self.assertEqual(snap_name, snap['name'])
-
+        self.assertEqual(snap_name, snap['name'])
         return snap
 
     def _delete_server(self, server):
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index f580ea6..f04947c 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -40,10 +40,7 @@
     @classmethod
     def setup_clients(cls):
         super(TestVolumeMigrateRetypeAttached, cls).setup_clients()
-        if CONF.volume_feature_enabled.api_v1:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_client
-        else:
-            cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
+        cls.admin_volume_types_client = cls.os_adm.volume_types_v2_client
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 48cb86b..ecb8e64 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -139,23 +139,6 @@
         self._assert_exec_called_with(
             "ip addr | awk '/ether/ {print $2}'")
 
-    def test_assign_static_ip(self):
-        self.ssh_mock.mock.exec_command.return_value = ''
-        ip = '10.0.0.2'
-        nic = 'eth0'
-        self.assertEqual(self.conn.assign_static_ip(nic, ip), '')
-        self._assert_exec_called_with(
-            "sudo ip addr add %s/%s dev %s" % (ip, '28', nic))
-
-    def test_set_nic_state(self):
-        nic = 'eth0'
-        self.conn.set_nic_state(nic)
-        self._assert_exec_called_with(
-            'sudo ip link set %s up' % nic)
-        self.conn.set_nic_state(nic, "down")
-        self._assert_exec_called_with(
-            'sudo ip link set %s down' % nic)
-
 
 class TestRemoteClientWithServer(base.TestCase):
 
diff --git a/tempest/tests/lib/services/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index 8d391c1..a277dfe 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -168,6 +168,10 @@
         "url": "http://os.co/v2/616fb98f-46ca-475e-917e-2563e5a8cd19"
     }
 
+    FAKE_SERVER_PASSWORD = {
+        "adminPass": "fake-password",
+    }
+
     FAKE_INSTANCE_ACTION_EVENTS = {
         "event": "fake-event",
         "start_time": "2016-10-02T10:00:00-05:00",
@@ -322,6 +326,21 @@
             name='fake-name'
             )
 
+    def test_evacuate_server_with_str_body(self):
+        self._test_evacuate_server()
+
+    def test_evacuate_server_with_bytes_body(self):
+        self._test_evacuate_server(bytes_body=True)
+
+    def _test_evacuate_server(self, bytes_body=False):
+        kwargs = {'server_id': self.server_id,
+                  'host': 'fake-target-host'}
+        self.check_service_client_function(
+            self.client.evacuate_server,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_SERVER_PASSWORD,
+            **kwargs)
+
     def test_change_password_with_str_body(self):
         self._test_change_password()
 
diff --git a/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
new file mode 100644
index 0000000..8d53792
--- /dev/null
+++ b/tempest/tests/lib/services/identity/v3/test_oauth_consumers_client.py
@@ -0,0 +1,160 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.services.identity.v3 import oauth_consumers_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestOAUTHConsumerClient(base.BaseServiceTest):
+    FAKE_CREATE_CONSUMER = {
+        "consumer": {
+            'description': 'A fake description 1'
+        }
+
+    }
+
+    FAKE_CONSUMER_INFO = {
+        "consumer": {
+            'id': '6392c7d3b7a2062e09a07aa377',
+            'links': {
+                'self': 'http://example.com/identity/v3/' +
+                        'OS-OAUTH1/consumers/g6f2l9'
+            },
+            'description': 'A description that is fake'
+        }
+
+    }
+
+    FAKE_LIST_CONSUMERS = {
+        'links': {
+            'self': 'http://example.com/identity/v3/OS-OAUTH1/consumers/',
+            'next': None,
+            'previous': None
+        },
+        'consumers': [
+            {
+                'id': '6392c7d3b7a2062e09a07aa377',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/6b9f2g5'
+                },
+                'description': 'A description that is fake'
+            },
+            {
+                'id': '677a855c9e3eb3a3954b36aca6',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/6a9f2366'
+                },
+                'description': 'A very fake description 2'
+            },
+            {
+                'id': '9d3ac57b08d65e07826b5e506',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/626b5e506'
+                },
+                'description': 'A very fake description 3'
+            },
+            {
+                'id': 'b522d163b1a18e928aca9y426',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/g7ca9426'
+                },
+                'description': 'A very fake description 4'
+            },
+            {
+                'id': 'b7e47321b5ef9051f93c2049e',
+                'links': {
+                    'self': 'http://example.com/identity/v3/' +
+                            'OS-OAUTH1/consumers/23d82049e'
+                },
+                'description': 'A very fake description 5'
+            }
+        ]
+    }
+
+    def setUp(self):
+        super(TestOAUTHConsumerClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = oauth_consumers_client.OAUTHConsumerClient(fake_auth,
+                                                                 'identity',
+                                                                 'regionOne')
+
+    def _test_create_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.create_consumer,
+            'tempest.lib.common.rest_client.RestClient.post',
+            self.FAKE_CREATE_CONSUMER,
+            bytes_body,
+            description=self.FAKE_CREATE_CONSUMER["consumer"]["description"],
+            status=201)
+
+    def _test_show_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_consumer,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_CONSUMER_INFO,
+            bytes_body,
+            consumer_id="6392c7d3b7a2062e09a07aa377")
+
+    def _test_list_consumers(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_consumers,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_CONSUMERS,
+            bytes_body)
+
+    def _test_update_consumer(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.update_consumer,
+            'tempest.lib.common.rest_client.RestClient.patch',
+            self.FAKE_CONSUMER_INFO,
+            bytes_body,
+            consumer_id="6392c7d3b7a2062e09a07aa377")
+
+    def test_create_consumer_with_str_body(self):
+        self._test_create_consumer()
+
+    def test_create_consumer_with_bytes_body(self):
+        self._test_create_consumer(bytes_body=True)
+
+    def test_show_consumer_with_str_body(self):
+        self._test_show_consumer()
+
+    def test_show_consumer_with_bytes_body(self):
+        self._test_show_consumer(bytes_body=True)
+
+    def test_list_consumers_with_str_body(self):
+        self._test_list_consumers()
+
+    def test_list_consumers_with_bytes_body(self):
+        self._test_list_consumers(bytes_body=True)
+
+    def test_update_consumer_with_str_body(self):
+        self._test_update_consumer()
+
+    def test_update_consumer_with_bytes_body(self):
+        self._test_update_consumer(bytes_body=True)
+
+    def test_delete_consumer(self):
+        self.check_service_client_function(
+            self.client.delete_consumer,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            consumer_id="6392c7d3b7a2062e09a07aa377",
+            status=204)
diff --git a/tempest/tests/lib/services/identity/v3/test_roles_client.py b/tempest/tests/lib/services/identity/v3/test_roles_client.py
index 41cea85..8d6bb42 100644
--- a/tempest/tests/lib/services/identity/v3/test_roles_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_roles_client.py
@@ -26,6 +26,18 @@
     FAKE_ROLE_ID_2 = "2"
     FAKE_ROLE_NAME_2 = "test2"
 
+    FAKE_ROLE_ID_3 = "3"
+    FAKE_ROLE_NAME_3 = "test3"
+
+    FAKE_ROLE_ID_4 = "4"
+    FAKE_ROLE_NAME_4 = "test4"
+
+    FAKE_ROLE_ID_5 = "5"
+    FAKE_ROLE_NAME_5 = "test5"
+
+    FAKE_ROLE_ID_6 = "6"
+    FAKE_ROLE_NAME_6 = "test6"
+
     FAKE_ROLE_INFO = {
         "role": {
             "domain_id": FAKE_DOMAIN_ID,
@@ -77,8 +89,8 @@
         }
     }
 
-    FAKE_LIST_ROLE_INFERENCES_RULES = {
-        "role_inference": {
+    COMMON_FAKE_LIST_ROLE_INFERENCE_RULES = [
+        {
             "prior_role": {
                 "id": FAKE_ROLE_ID,
                 "name": FAKE_ROLE_NAME,
@@ -97,20 +109,60 @@
                     }
                 },
                 {
-                    "id": "3",
-                    "name": "test3",
+                    "id": FAKE_ROLE_ID_3,
+                    "name": FAKE_ROLE_NAME_3,
                     "links": {
-                        "self": "http://example.com/identity/v3/roles/3"
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_3)
                     }
                 }
             ]
         },
+        {
+            "prior_role": {
+                "id": FAKE_ROLE_ID_4,
+                "name": FAKE_ROLE_NAME_4,
+                "links": {
+                    "self": "http://example.com/identity/v3/roles/%s" % (
+                        FAKE_ROLE_ID_4)
+                }
+            },
+            "implies": [
+                {
+                    "id": FAKE_ROLE_ID_5,
+                    "name": FAKE_ROLE_NAME_5,
+                    "links": {
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_5)
+                    }
+                },
+                {
+                    "id": FAKE_ROLE_ID_6,
+                    "name": FAKE_ROLE_NAME_6,
+                    "links": {
+                        "self": "http://example.com/identity/v3/roles/%s" % (
+                            FAKE_ROLE_ID_6)
+                    }
+                }
+            ]
+        }
+    ]
+
+    FAKE_LIST_ROLE_INFERENCE_RULES = {
+        "role_inference": COMMON_FAKE_LIST_ROLE_INFERENCE_RULES[0],
         "links": {
             "self": "http://example.com/identity/v3/roles/"
                     "%s/implies" % FAKE_ROLE_ID
         }
     }
 
+    FAKE_LIST_ALL_ROLE_INFERENCE_RULES = {
+        "role_inferences": COMMON_FAKE_LIST_ROLE_INFERENCE_RULES,
+        "links": {
+            "self": "http://example.com/identity/v3/role_inferences"
+        }
+    }
+
     def setUp(self):
         super(TestRolesClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -254,10 +306,17 @@
         self.check_service_client_function(
             self.client.list_role_inferences_rules,
             'tempest.lib.common.rest_client.RestClient.get',
-            self.FAKE_LIST_ROLE_INFERENCES_RULES,
+            self.FAKE_LIST_ROLE_INFERENCE_RULES,
             bytes_body,
             prior_role=self.FAKE_ROLE_ID)
 
+    def _test_list_all_role_inference_rules(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_all_role_inference_rules,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_ALL_ROLE_INFERENCE_RULES,
+            bytes_body)
+
     def test_create_role_with_str_body(self):
         self._test_create_role()
 
@@ -441,3 +500,9 @@
             status=204,
             prior_role=self.FAKE_ROLE_ID,
             implies_role=self.FAKE_ROLE_ID_2)
+
+    def test_list_all_role_inference_rules_with_str_body(self):
+        self._test_list_all_role_inference_rules()
+
+    def test_list_all_role_inference_rules_with_bytes_body(self):
+        self._test_list_all_role_inference_rules(bytes_body=True)
diff --git a/tox.ini b/tox.ini
index e2a9b3f..892f834 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = pep8,py35,py34,py27,pip-check-reqs
+envlist = pep8,py35,py27,pip-check-reqs
 minversion = 2.3.1
 skipsdist = True
 
@@ -36,7 +36,6 @@
 commands = oslo-config-generator --config-file tempest/cmd/config-generator.tempest.conf
 
 [testenv:cover]
-setenv = OS_TEST_PATH=./tempest/tests
 commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}'
 
 [testenv:all]