Merge "Retype enhancement for EMC VNX cinder driver"

This commit is contained in:
Jenkins 2015-10-09 04:36:47 +00:00 committed by Gerrit Code Review
commit 2c721b9bd5
2 changed files with 107 additions and 47 deletions

View File

@ -596,6 +596,11 @@ class EMCVNXCLIDriverTestData(object):
return ('snap', '-modify', '-id', snap_name,
'-allowReadWrite', 'yes', '-allowAutoDelete', 'yes')
def MODIFY_TIERING_CMD(self, lun_name, tiering):
cmd = ['lun', '-modify', '-name', lun_name, '-o']
cmd.extend(self.tiering_values[tiering])
return tuple(cmd)
provisioning_values = {
'thin': ['-type', 'Thin'],
'thick': ['-type', 'NonThin'],
@ -3046,15 +3051,10 @@ Time Remaining: 0 second(s)
@mock.patch(
"cinder.volume.volume_types."
"get_volume_type_extra_specs",
mock.Mock(return_value={'storagetype:provisioning': 'thin'}))
def test_retype_thin_to_compressed_auto(self):
"""Unit test for retype thin to compressed and auto tiering."""
diff_data = {'encryption': {}, 'qos_specs': {},
'extra_specs':
{'storagetype:provsioning': ('thin',
'compressed'),
'storagetype:tiering': (None, 'auto')}}
mock.Mock(side_effect=[{'provisioning:type': 'thin'},
{'provisioning:type': 'thick'}]))
def test_retype_turn_on_compression_and_autotiering(self):
"""Unit test for retype a volume to compressed and auto tiering."""
new_type_data = {'name': 'voltype0', 'qos_specs_id': None,
'deleted': False,
'extra_specs': {'storagetype:provisioning':
@ -3062,20 +3062,15 @@ Time Remaining: 0 second(s)
'storagetype:tiering': 'auto'},
'id': 'f82f28c8-148b-416e-b1ae-32d3c02556c0'}
host_test_data = {'host': 'ubuntu-server12@pool_backend_1',
host_test_data = {'host': 'host@backendsec#unit_test_pool',
'capabilities':
{'location_info': 'unit_test_pool|FNM00124500890',
'volume_backend_name': 'pool_backend_1',
'storage_protocol': 'iSCSI'}}
cmd_migrate_verify = self.testData.MIGRATION_VERIFY_CMD(1)
output_migrate_verify = (r'The specified source LUN '
'is not currently migrating', 23)
commands = [self.testData.NDU_LIST_CMD,
self.testData.SNAP_LIST_CMD(),
cmd_migrate_verify]
self.testData.SNAP_LIST_CMD()]
results = [self.testData.NDU_LIST_RESULT,
('No snap', 1023),
output_migrate_verify]
('No snap', 1023)]
fake_cli = self.driverSetup(commands, results)
self.driver.cli.enablers = ['-Compression',
'-Deduplication',
@ -3083,21 +3078,69 @@ Time Remaining: 0 second(s)
'-FAST']
emc_vnx_cli.CommandLineHelper.get_array_serial = mock.Mock(
return_value={'array_serial': "FNM00124500890"})
# Retype a thin volume to a compressed volume
self.driver.retype(None, self.testData.test_volume3,
new_type_data,
diff_data,
host_test_data)
new_type_data, None, host_test_data)
expect_cmd = [
mock.call(*self.testData.SNAP_LIST_CMD(), poll=False),
mock.call(*self.testData.LUN_CREATION_CMD(
'vol3-123456', 2, 'unit_test_pool', 'compressed', 'auto')),
mock.call(*self.testData.ENABLE_COMPRESSION_CMD(1)),
mock.call(*self.testData.MIGRATION_CMD(),
retry_disable=True,
poll=True)]
mock.call(*self.testData.MODIFY_TIERING_CMD('vol3', 'auto'))
]
fake_cli.assert_has_calls(expect_cmd)
# Retype a thick volume to a compressed volume
self.driver.retype(None, self.testData.test_volume3,
new_type_data, None, host_test_data)
fake_cli.assert_has_calls(expect_cmd)
@mock.patch(
"cinder.volume.drivers.emc.emc_vnx_cli.EMCVnxCliBase.get_lun_id",
mock.Mock(return_value=1))
@mock.patch(
"cinder.volume.drivers.emc.emc_vnx_cli.CommandLineHelper." +
"get_lun_by_name",
mock.Mock(return_value={'lun_id': 1}))
@mock.patch(
"eventlet.event.Event.wait",
mock.Mock(return_value=None))
@mock.patch(
"time.time",
mock.Mock(return_value=123456))
@mock.patch(
"cinder.volume.volume_types."
"get_volume_type_extra_specs",
mock.Mock(return_value={'provisioning:type': 'thin'}))
def test_retype_turn_on_compression_volume_has_snap(self):
"""Unit test for retype a volume which has snap to compressed."""
new_type_data = {'name': 'voltype0', 'qos_specs_id': None,
'deleted': False,
'extra_specs': {'storagetype:provisioning':
'compressed'},
'id': 'f82f28c8-148b-416e-b1ae-32d3c02556c0'}
host_test_data = {'host': 'host@backendsec#unit_test_pool',
'capabilities':
{'location_info': 'unit_test_pool|FNM00124500890',
'volume_backend_name': 'pool_backend_1',
'storage_protocol': 'iSCSI'}}
commands = [self.testData.NDU_LIST_CMD,
self.testData.SNAP_LIST_CMD()]
results = [self.testData.NDU_LIST_RESULT,
('Has snap', 0)]
self.driverSetup(commands, results)
self.driver.cli.enablers = ['-Compression',
'-Deduplication',
'-ThinProvisioning',
'-FAST']
emc_vnx_cli.CommandLineHelper.get_array_serial = mock.Mock(
return_value={'array_serial': "FNM00124500890"})
# Retype a thin volume which has a snap to a compressed volume
retyped = self.driver.retype(None, self.testData.test_volume3,
new_type_data, None, host_test_data)
self.assertFalse(retyped,
"Retype should failed due to "
"the volume has snapshot")
@mock.patch(
"cinder.volume.drivers.emc.emc_vnx_cli.EMCVnxCliBase.get_lun_id",
mock.Mock(return_value=1))

View File

@ -2262,17 +2262,24 @@ class EMCVnxCliBase(object):
self._get_and_validate_extra_specs(new_specs))
# Check what changes are needed
migration, tiering_change = self.determine_changes_when_retype(
volume, new_type, host)
changes = self.determine_changes_when_retype(volume, new_type, host)
# Reject if volume has snapshot when migration is needed
if migration and self._client.check_lun_has_snap(
self.get_lun_id(volume)):
LOG.debug('Driver is not able to do retype because the volume '
'has snapshot which is forbidden to migrate.')
return False
if self._client.check_lun_has_snap(self.get_lun_id(volume)):
# Reject if volume has snapshot when migration is needed
if changes['migration']:
LOG.debug('Driver is not able to do retype because the volume '
'%s has a snapshot which is forbidden to migrate.',
volume['id'])
return False
# Reject if volume has snapshot when trying to
# turn on compression
if changes['compression_on']:
LOG.debug('Driver is not able to do retype because the volume '
'%s has a snapshot which is forbidden to turn on '
'compression.', volume['id'])
return False
if migration:
if changes['migration']:
# Check whether the migration is valid
is_valid, target_pool_name = (
self._is_valid_for_storage_assisted_migration(
@ -2292,16 +2299,21 @@ class EMCVnxCliBase(object):
'storage-assisted migration is not valid '
'in this situation.')
return False
elif tiering_change:
if changes['compression_on']:
# Turn on compression feature on the volume
self._client.enable_or_disable_compression_on_lun(
volume['name'], 'on')
if changes['tiering']:
# Modify lun to change tiering policy
self._client.modify_lun_tiering(volume['name'], new_tiering)
return True
else:
return True
return True
def determine_changes_when_retype(self, volume, new_type, host):
migration = False
tiering_change = False
changes = {
'migration': False,
'tiering': False,
'compression_on': False
}
old_specs = self.get_volumetype_extraspecs(volume)
old_provisioning, old_tiering, old_snapcopy = (
@ -2314,15 +2326,20 @@ class EMCVnxCliBase(object):
lun_type = self._extract_provider_location_for_lun(
volume['provider_location'], 'type')
if volume['host'] != host['host'] or \
old_provisioning != new_provisioning:
migration = True
if volume['host'] != host['host']:
changes['migration'] = True
elif old_provisioning != new_provisioning:
if (old_provisioning in ['thin', 'thick'] and
new_provisioning == 'compressed'):
changes['compression_on'] = True
else:
changes['migration'] = True
if lun_type == 'smp':
migration = True
changes['migration'] = True
if new_tiering != old_tiering:
tiering_change = True
return migration, tiering_change
changes['tiering'] = True
return changes
def determine_all_enablers_exist(self, enablers):
"""Determine all wanted enablers whether exist."""