From 71b64e27520c35c43529a74743a29b45e3ea9468 Mon Sep 17 00:00:00 2001 From: Ryan Liang Date: Sat, 27 May 2017 16:24:54 +0800 Subject: [PATCH] VNX: failed to create from image cache Failed to create from image cache before the async migration was completed. So the fix is that change the migration mode of creating image cache volume from async to sync. Change-Id: I446fbd063a20291edf405085e7d1f3b6417beb2c Closes-Bug: 1698047 --- .../drivers/dell_emc/vnx/mocked_cinder.yaml | 13 ++++++++ .../volume/drivers/dell_emc/vnx/test_utils.py | 32 +++++++++++++++++++ cinder/volume/drivers/dell_emc/vnx/adapter.py | 6 ++-- cinder/volume/drivers/dell_emc/vnx/driver.py | 4 ++- cinder/volume/drivers/dell_emc/vnx/utils.py | 24 ++++++++++++++ 5 files changed, 74 insertions(+), 5 deletions(-) diff --git a/cinder/tests/unit/volume/drivers/dell_emc/vnx/mocked_cinder.yaml b/cinder/tests/unit/volume/drivers/dell_emc/vnx/mocked_cinder.yaml index 4d9dde49695..68aa325bd97 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/vnx/mocked_cinder.yaml +++ b/cinder/tests/unit/volume/drivers/dell_emc/vnx/mocked_cinder.yaml @@ -455,6 +455,19 @@ test_require_consistent_group_snapshot_enabled: _uuid: group_id group_type_id: _uuid: group_type_id + +test_is_image_cache_volume_false: + volume: *volume_base + +test_is_image_cache_volume_true: + volume: *volume_base + +test_calc_migrate_and_provision_image_cache: + volume: *volume_base + +test_calc_migrate_and_provision: + volume: *volume_base + ########################################################### # TestClient ########################################################### diff --git a/cinder/tests/unit/volume/drivers/dell_emc/vnx/test_utils.py b/cinder/tests/unit/volume/drivers/dell_emc/vnx/test_utils.py index 7986432de59..c6d860e00e0 100644 --- a/cinder/tests/unit/volume/drivers/dell_emc/vnx/test_utils.py +++ b/cinder/tests/unit/volume/drivers/dell_emc/vnx/test_utils.py @@ -178,3 +178,35 @@ class TestUtils(test.TestCase): driver = FakeDriver() is_called = driver.fake_group_method('context', input['group']) self.assertTrue(is_called) + + @res_mock.mock_driver_input + def test_is_image_cache_volume_false(self, mocked): + volume = mocked['volume'] + volume.display_name = 'volume-ca86b9a0-d0d5-4267-8cd5-c62274056cc0' + self.assertFalse(vnx_utils.is_image_cache_volume(volume)) + volume.display_name = 'volume-ca86b9a0-d0d5-c62274056cc0' + self.assertFalse(vnx_utils.is_image_cache_volume(volume)) + + @res_mock.mock_driver_input + def test_is_image_cache_volume_true(self, mocked): + volume = mocked['volume'] + volume.display_name = 'image-ca86b9a0-d0d5-4267-8cd5-c62274056cc0' + self.assertTrue(vnx_utils.is_image_cache_volume(volume)) + + @res_mock.mock_driver_input + def test_calc_migrate_and_provision_image_cache(self, mocked): + volume = mocked['volume'] + volume.display_name = 'image-ca86b9a0-d0d5-4267-8cd5-c62274056cc0' + self.assertTrue(vnx_utils.is_image_cache_volume(volume)) + async_migrate, provision = vnx_utils.calc_migrate_and_provision(volume) + self.assertFalse(async_migrate) + self.assertEqual(provision.name, 'THIN') + + @res_mock.mock_driver_input + def test_calc_migrate_and_provision(self, mocked): + volume = mocked['volume'] + volume.display_name = 'volume-ca86b9a0-d0d5-4267-8cd5-c62274056cc0' + async_migrate, provision = vnx_utils.calc_migrate_and_provision(volume) + self.assertEqual(vnx_utils.is_async_migrate_enabled(volume), + async_migrate) + self.assertEqual(provision.name, 'THICK') diff --git a/cinder/volume/drivers/dell_emc/vnx/adapter.py b/cinder/volume/drivers/dell_emc/vnx/adapter.py index fba9d745d86..6d72847c337 100644 --- a/cinder/volume/drivers/dell_emc/vnx/adapter.py +++ b/cinder/volume/drivers/dell_emc/vnx/adapter.py @@ -313,7 +313,6 @@ class CommonAdapter(object): pool = utils.get_pool_from_host(volume.host) specs = common.ExtraSpecs.from_volume(volume) - provision = specs.provision tier = specs.tier base_lun_name = utils.get_base_lun_name(snapshot.volume) rep_update = dict() @@ -333,7 +332,7 @@ class CommonAdapter(object): volume_metadata['snapcopy'] = 'True' volume_metadata['async_migrate'] = 'False' else: - async_migrate = utils.is_async_migrate_enabled(volume) + async_migrate, provision = utils.calc_migrate_and_provision(volume) new_snap_name = ( utils.construct_snap_name(volume) if async_migrate else None) new_lun_id = emc_taskflow.create_volume_from_snapshot( @@ -366,7 +365,6 @@ class CommonAdapter(object): pool = utils.get_pool_from_host(volume.host) specs = common.ExtraSpecs.from_volume(volume) - provision = specs.provision tier = specs.tier base_lun_name = utils.get_base_lun_name(src_vref) @@ -389,7 +387,7 @@ class CommonAdapter(object): volume_metadata['snapcopy'] = 'True' volume_metadata['async_migrate'] = 'False' else: - async_migrate = utils.is_async_migrate_enabled(volume) + async_migrate, provision = utils.calc_migrate_and_provision(volume) new_lun_id = emc_taskflow.create_cloned_volume( client=self.client, snap_name=snap_name, diff --git a/cinder/volume/drivers/dell_emc/vnx/driver.py b/cinder/volume/drivers/dell_emc/vnx/driver.py index 43f03a1e654..e14bcbd2cf4 100644 --- a/cinder/volume/drivers/dell_emc/vnx/driver.py +++ b/cinder/volume/drivers/dell_emc/vnx/driver.py @@ -70,9 +70,11 @@ class VNXDriver(driver.ManageableVD, Configurable migration rate support 8.0.0 - New VNX Cinder driver 9.0.0 - Use asynchronous migration for cloning + 10.0.1 - Extend SMP size before aync migration when cloning from an + image cache volume """ - VERSION = '09.00.00' + VERSION = '10.00.01' VENDOR = 'Dell EMC' # ThirdPartySystems wiki page CI_WIKI_NAME = "EMC_VNX_CI" diff --git a/cinder/volume/drivers/dell_emc/vnx/utils.py b/cinder/volume/drivers/dell_emc/vnx/utils.py index 6d4800f7824..9d3c699cc6c 100644 --- a/cinder/volume/drivers/dell_emc/vnx/utils.py +++ b/cinder/volume/drivers/dell_emc/vnx/utils.py @@ -20,6 +20,7 @@ from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import excutils from oslo_utils import importutils +from oslo_utils import uuidutils from cinder.i18n import _ from cinder.volume.drivers.dell_emc.vnx import common @@ -356,3 +357,26 @@ def get_remote_pool(config, volume): rep_list = common.ReplicationDeviceList(config) remote_pool_name = rep_list[0].pool_name return remote_pool_name if remote_pool_name else pool_name + + +def is_image_cache_volume(volume): + display_name = volume.display_name + if (display_name.startswith('image-') + and uuidutils.is_uuid_like(display_name[6:])): + LOG.debug('Volume: %s is for image cache. Use sync migration and ' + 'thin provisioning.', volume.name) + return True + return False + + +def calc_migrate_and_provision(volume): + """Returns a tuple of async migrate and provision type. + + The first element is the flag whether to enable async migrate, + the second is the provision type (thin or thick). + """ + if is_image_cache_volume(volume): + return False, storops.VNXProvisionEnum.THIN + else: + specs = common.ExtraSpecs.from_volume(volume) + return is_async_migrate_enabled(volume), specs.provision