Merge "Fix race in test_attach_detach_volume"
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/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/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 87265ec..7cbb513 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -22,9 +22,12 @@
 
     @decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
-        body, servers = compute.create_test_server(self.os,
-                                                   wait_until='ACTIVE',
-                                                   min_count=2)
+        tenant_network = self.get_tenant_network()
+        body, servers = compute.create_test_server(
+            self.os,
+            wait_until='ACTIVE',
+            min_count=2,
+            tenant_network=tenant_network)
         for server in servers:
             self.addCleanup(self.servers_client.delete_server, server['id'])
         # NOTE(maurosr): do status response check and also make sure that
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 3f6abab..a72df5e 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -87,29 +87,48 @@
                          'Token must be invalid because the connection '
                          'closed.')
         # Parse the RFB version from the data to make sure it is valid
-        # and greater than or equal to 3.3
+        # and belong to the known supported RFB versions.
         version = float("%d.%d" % (int(data[4:7], base=10),
                                    int(data[8:11], base=10)))
-        self.assertTrue(version >= 3.3, 'Bad RFB Version: ' + str(version))
-        # Send our RFB version to the server, which we will just go with 3.3
+        # Add the max RFB versions supported
+        supported_versions = [3.3, 3.8]
+        self.assertIn(version, supported_versions,
+                      'Bad RFB Version: ' + str(version))
+        # Send our RFB version to the server
         self._websocket.send_frame(data)
         # Get the sever authentication type and make sure None is supported
         data = self._websocket.receive_frame()
         self.assertIsNotNone(data, 'Expected authentication type None.')
-        self.assertGreaterEqual(
-            len(data), 2, 'Expected authentication type None.')
-        self.assertIn(
-            1, [ord_func(data[i + 1]) for i in range(ord_func(data[0]))],
-            'Expected authentication type None.')
-        # Send to the server that we only support authentication type None
-        self._websocket.send_frame(six.int2byte(1))
-        # The server should send 4 bytes of 0's if security handshake succeeded
-        data = self._websocket.receive_frame()
-        self.assertEqual(
-            len(data), 4, 'Server did not think security was successful.')
-        self.assertEqual(
-            [ord_func(i) for i in data], [0, 0, 0, 0],
-            'Server did not think security was successful.')
+        data_length = len(data)
+        if version == 3.3:
+            # For RFB 3.3: in the security handshake, rather than a two-way
+            # negotiation, the server decides the security type and sends a
+            # single word(4 bytes).
+            self.assertEqual(
+                data_length, 4, 'Expected authentication type None.')
+            self.assertIn(1, [ord_func(data[i]) for i in (0, 3)],
+                          'Expected authentication type None.')
+        else:
+            self.assertGreaterEqual(
+                len(data), 2, 'Expected authentication type None.')
+            self.assertIn(
+                1,
+                [ord_func(data[i + 1]) for i in range(ord_func(data[0]))],
+                'Expected authentication type None.')
+            # Send to the server that we only support authentication
+            # type None
+            self._websocket.send_frame(six.int2byte(1))
+
+            # The server should send 4 bytes of 0's if security
+            # handshake succeeded
+            data = self._websocket.receive_frame()
+            self.assertEqual(
+                len(data), 4,
+                'Server did not think security was successful.')
+            self.assertEqual(
+                [ord_func(i) for i in data], [0, 0, 0, 0],
+                'Server did not think security was successful.')
+
         # Say to leave the desktop as shared as part of client initialization
         self._websocket.send_frame(six.int2byte(1))
         # Get the server initialization packet back and make sure it is the
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index aa5145d..2088a44 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -71,6 +71,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_types.py b/tempest/api/volume/admin/test_volume_types.py
index fd333eb..ae57540 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -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/v2/test_volume_manage.py b/tempest/api/volume/admin/v2/test_volume_manage.py
new file mode 100644
index 0000000..f983490
--- /dev/null
+++ b/tempest/api/volume/admin/v2/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 VolumeManageAdminV2Test(base.BaseVolumeAdminTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumeManageAdminV2Test, 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/v2/test_volume_pools.py
index 91d092d..5041095 100644
--- a/tempest/api/volume/admin/v2/test_volume_pools.py
+++ b/tempest/api/volume/admin/v2/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']
+    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/base.py b/tempest/api/volume/base.py
index 5e4fada..2f719c8 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -225,6 +225,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 = \
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index a852cea..df98720 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -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_snapshots_list.py b/tempest/api/volume/test_volumes_snapshots_list.py
index 0ea8ec7..a1b514b 100644
--- a/tempest/api/volume/test_volumes_snapshots_list.py
+++ b/tempest/api/volume/test_volumes_snapshots_list.py
@@ -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/clients.py b/tempest/clients.py
index 0654110..49a046a 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -262,6 +262,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/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 6dfc579..414c016 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'
diff --git a/tempest/config.py b/tempest/config.py
index 93b8ab2..c7669b7 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 '
@@ -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',
@@ -770,6 +775,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 +820,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..4c4b5eb 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -564,3 +564,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/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/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/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..2c109ea 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -351,3 +351,15 @@
         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..cd2881b 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))
 
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/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()