Add tempest tests for volume retype with migration
This patch proposes to add a test to test volume migration
from one backend to another. Before running the tests,
please configure your local cinder deployment with a proper
multi-backend support.
[volume]
backend_names = lvmdriver-1,lvmdriver-2
[volume_feature_enabled]
multi_backend = True
A minimum of two backends are required. The test will migrate the volume
from the first to the second backend in the list. Other backends will
be ignored.
This test can be tested by 'check experimental' and must run and pass
the job'lvm-multibackend'.
Change-Id: Iff4d880a0f8e928cbc07b84ff0c357ad59ef929c
Partial-Implements: blueprint migration-improvement
Co-Authored-By: Scott DAngelo <scott.dangelo@hpe.com>
Co-Authored-By: Erlon Cruz <erlon.cruz@fit-tecnologia.org.br>
diff --git a/tempest/api/volume/admin/test_volume_retype_with_migration.py b/tempest/api/volume/admin/test_volume_retype_with_migration.py
new file mode 100644
index 0000000..8a69ea3
--- /dev/null
+++ b/tempest/api/volume/admin/test_volume_retype_with_migration.py
@@ -0,0 +1,109 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+from oslo_log import log as logging
+
+from tempest.api.volume import base
+from tempest.common import waiters
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+class VolumeRetypeWithMigrationV2Test(base.BaseVolumeAdminTest):
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumeRetypeWithMigrationV2Test, cls).skip_checks()
+
+ if not CONF.volume_feature_enabled.multi_backend:
+ raise cls.skipException("Cinder multi-backend feature disabled.")
+
+ if len(set(CONF.volume.backend_names)) < 2:
+ raise cls.skipException("Requires at least two different "
+ "backend names")
+
+ @classmethod
+ def resource_setup(cls):
+ super(VolumeRetypeWithMigrationV2Test, cls).resource_setup()
+ # read backend name from a list.
+ cls.backend_src = CONF.volume.backend_names[0]
+ cls.backend_dst = CONF.volume.backend_names[1]
+
+ extra_specs_src = {"volume_backend_name": cls.backend_src}
+ extra_specs_dst = {"volume_backend_name": cls.backend_dst}
+
+ cls.src_vol_type = cls.create_volume_type(extra_specs=extra_specs_src)
+ cls.dst_vol_type = cls.create_volume_type(extra_specs=extra_specs_dst)
+
+ cls.src_vol = cls.create_volume(volume_type=cls.src_vol_type['name'])
+
+ @classmethod
+ def resource_cleanup(cls):
+ # When retyping a volume, Cinder creates an internal volume in the
+ # target backend. The volume in the source backend is deleted after
+ # the migration, so we need to wait for Cinder delete this volume
+ # before deleting the types we've created.
+
+ # This list should return 2 volumes until the copy and cleanup
+ # process is finished.
+ fetched_list = cls.admin_volume_client.list_volumes(
+ params={'all_tenants': True,
+ 'display_name': cls.src_vol['name']})['volumes']
+
+ for fetched_vol in fetched_list:
+ if fetched_vol['id'] != cls.src_vol['id']:
+ # This is the Cinder internal volume
+ LOG.debug('Waiting for internal volume %s deletion',
+ fetched_vol['id'])
+ cls.admin_volume_client.wait_for_resource_deletion(
+ fetched_vol['id'])
+ break
+
+ super(VolumeRetypeWithMigrationV2Test, cls).resource_cleanup()
+
+ @test.idempotent_id('a1a41f3f-9dad-493e-9f09-3ff197d477cd')
+ def test_available_volume_retype_with_migration(self):
+
+ keys_with_no_change = ('id', 'size', 'description', 'name', 'user_id',
+ 'os-vol-tenant-attr:tenant_id')
+ keys_with_change = ('volume_type', 'os-vol-host-attr:host')
+
+ volume_source = self.admin_volume_client.show_volume(
+ self.src_vol['id'])['volume']
+
+ # TODO(erlon): change this to volumes_client client after Bug
+ # #1657806 is fixed
+ self.admin_volume_client.retype_volume(
+ self.src_vol['id'],
+ new_type=self.dst_vol_type['name'],
+ migration_policy='on-demand')
+
+ waiters.wait_for_volume_retype(self.volumes_client, self.src_vol['id'],
+ self.dst_vol_type['name'])
+ volume_dest = self.admin_volume_client.show_volume(
+ self.src_vol['id'])['volume']
+
+ # Check the volume information after the migration.
+ self.assertEqual('success',
+ volume_dest['os-vol-mig-status-attr:migstat'])
+ self.assertEqual('success', volume_dest['migration_status'])
+
+ for key in keys_with_no_change:
+ self.assertEqual(volume_source[key], volume_dest[key])
+
+ for key in keys_with_change:
+ self.assertNotEqual(volume_source[key], volume_dest[key])