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
This commit is contained in:
Ryan Liang
2017-05-27 16:24:54 +08:00
parent bd33bbffb7
commit 71b64e2752
5 changed files with 74 additions and 5 deletions

View File

@@ -455,6 +455,19 @@ test_require_consistent_group_snapshot_enabled:
_uuid: group_id _uuid: group_id
group_type_id: group_type_id:
_uuid: 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 # TestClient
########################################################### ###########################################################

View File

@@ -178,3 +178,35 @@ class TestUtils(test.TestCase):
driver = FakeDriver() driver = FakeDriver()
is_called = driver.fake_group_method('context', input['group']) is_called = driver.fake_group_method('context', input['group'])
self.assertTrue(is_called) 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')

View File

@@ -313,7 +313,6 @@ class CommonAdapter(object):
pool = utils.get_pool_from_host(volume.host) pool = utils.get_pool_from_host(volume.host)
specs = common.ExtraSpecs.from_volume(volume) specs = common.ExtraSpecs.from_volume(volume)
provision = specs.provision
tier = specs.tier tier = specs.tier
base_lun_name = utils.get_base_lun_name(snapshot.volume) base_lun_name = utils.get_base_lun_name(snapshot.volume)
rep_update = dict() rep_update = dict()
@@ -333,7 +332,7 @@ class CommonAdapter(object):
volume_metadata['snapcopy'] = 'True' volume_metadata['snapcopy'] = 'True'
volume_metadata['async_migrate'] = 'False' volume_metadata['async_migrate'] = 'False'
else: else:
async_migrate = utils.is_async_migrate_enabled(volume) async_migrate, provision = utils.calc_migrate_and_provision(volume)
new_snap_name = ( new_snap_name = (
utils.construct_snap_name(volume) if async_migrate else None) utils.construct_snap_name(volume) if async_migrate else None)
new_lun_id = emc_taskflow.create_volume_from_snapshot( new_lun_id = emc_taskflow.create_volume_from_snapshot(
@@ -366,7 +365,6 @@ class CommonAdapter(object):
pool = utils.get_pool_from_host(volume.host) pool = utils.get_pool_from_host(volume.host)
specs = common.ExtraSpecs.from_volume(volume) specs = common.ExtraSpecs.from_volume(volume)
provision = specs.provision
tier = specs.tier tier = specs.tier
base_lun_name = utils.get_base_lun_name(src_vref) base_lun_name = utils.get_base_lun_name(src_vref)
@@ -389,7 +387,7 @@ class CommonAdapter(object):
volume_metadata['snapcopy'] = 'True' volume_metadata['snapcopy'] = 'True'
volume_metadata['async_migrate'] = 'False' volume_metadata['async_migrate'] = 'False'
else: 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( new_lun_id = emc_taskflow.create_cloned_volume(
client=self.client, client=self.client,
snap_name=snap_name, snap_name=snap_name,

View File

@@ -70,9 +70,11 @@ class VNXDriver(driver.ManageableVD,
Configurable migration rate support Configurable migration rate support
8.0.0 - New VNX Cinder driver 8.0.0 - New VNX Cinder driver
9.0.0 - Use asynchronous migration for cloning 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' VENDOR = 'Dell EMC'
# ThirdPartySystems wiki page # ThirdPartySystems wiki page
CI_WIKI_NAME = "EMC_VNX_CI" CI_WIKI_NAME = "EMC_VNX_CI"

View File

@@ -20,6 +20,7 @@ from oslo_log import log as logging
from oslo_service import loopingcall from oslo_service import loopingcall
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import importutils from oslo_utils import importutils
from oslo_utils import uuidutils
from cinder.i18n import _ from cinder.i18n import _
from cinder.volume.drivers.dell_emc.vnx import common from cinder.volume.drivers.dell_emc.vnx import common
@@ -356,3 +357,26 @@ def get_remote_pool(config, volume):
rep_list = common.ReplicationDeviceList(config) rep_list = common.ReplicationDeviceList(config)
remote_pool_name = rep_list[0].pool_name remote_pool_name = rep_list[0].pool_name
return remote_pool_name if remote_pool_name else 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