VMAX driver - Support for compression on All Flash.

Compression is enabled by default on an VMAX All Flash.
This feature allows the user to create different storage groups
with compression disabled, if the user requires it.

Change-Id: I28ecb0a9975ae9a6ec46f0a48135a295f6a398da
Implements: blueprint vmax-compression-support
This commit is contained in:
Helen Walsh 2016-11-22 15:25:34 +00:00
parent 6624c3197b
commit a9a3eddaf2
8 changed files with 389 additions and 54 deletions

View File

@ -102,6 +102,10 @@ class CIM_IPProtocolEndpoint(dict):
pass
class Symm_ArrayChassis(dict):
pass
class SE_ReplicationSettingData(dict):
def __init__(self, *args, **kwargs):
self['DefaultInstance'] = self.createInstance()
@ -598,7 +602,7 @@ class EMCVMAXCommonData(object):
'controller': {'host': '10.00.00.00'},
'hostlunid': 3}
test_ctxt = {}
new_type = {}
new_type = {'extra_specs': {}}
diff = {}
extra_specs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'V3_BE',
@ -781,6 +785,8 @@ class FakeEcomConnection(object):
result = self._enum_storageSyncSvSv()
elif name == 'Symm_SRPStoragePool':
result = self._enum_srpstoragepool()
elif name == 'Symm_ArrayChassis':
result = self._enum_arraychassis()
else:
result = self._default_enum()
return result
@ -1858,6 +1864,20 @@ class FakeEcomConnection(object):
ipprotocolendpoints.append(iqnprotocolendpoint)
return ipprotocolendpoints
def _enum_arraychassis(self):
arraychassiss = []
arraychassis = Symm_ArrayChassis()
arraychassis['CreationClassName'] = (
'Symm_ArrayChassis')
arraychassis['SystemName'] = self.data.storage_system_v3
arraychassis['Tag'] = self.data.storage_system_v3
cimproperty = Fake_CIMProperty()
cimproperty.value = 'VMAX250F'
properties = {u'Model': cimproperty}
arraychassis.properties = properties
arraychassiss.append(arraychassis)
return arraychassiss
def _default_enum(self):
names = []
name = {}
@ -7271,7 +7291,8 @@ class EMCV3MultiPoolDriverTestCase(test.TestCase):
self.driver.create_snapshot(self.data.test_snapshot_1_v3)
utils = self.driver.common.provisionv3.utils
utils.get_v3_default_sg_instance_name.assert_called_once_with(
self.conn, u'SRP_1', u'Bronze', u'DSS', u'SYMMETRIX+000195900551')
self.conn, u'SRP_1', u'Bronze', u'DSS', u'SYMMETRIX+000195900551',
False)
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
@ -7518,7 +7539,7 @@ class EMCVMAXProvisionV3Test(test.TestCase):
return_value=self.data.default_sg_instance_name)
newstoragegroup = provisionv3.create_storage_group_v3(
conn, controllerConfigService, groupName, srp, slo, workload,
extraSpecs)
extraSpecs, False)
self.assertEqual(self.data.default_sg_instance_name, newstoragegroup)
def test_create_element_replica(self):
@ -8514,6 +8535,24 @@ class EMCVMAXUtilsTest(test.TestCase):
issynched = self.driver.common.utils._is_sync_complete(conn, syncname)
self.assertFalse(issynched)
def test_get_v3_storage_group_name_compression_disabled(self):
poolName = 'SRP_1'
slo = 'Diamond'
workload = 'DSS'
isCompressionDisabled = True
storageGroupName = self.driver.utils.get_v3_storage_group_name(
poolName, slo, workload, isCompressionDisabled)
self.assertEqual("OS-SRP_1-Diamond-DSS-CD-SG", storageGroupName)
@mock.patch.object(
emc_vmax_utils.EMCVMAXUtils,
'get_smi_version',
return_value=831)
def test_is_all_flash(self, mock_version):
conn = FakeEcomConnection()
array = '000197200056'
self.assertTrue(self.driver.utils.is_all_flash(conn, array))
class EMCVMAXCommonTest(test.TestCase):
def setUp(self):
@ -8878,6 +8917,140 @@ class EMCVMAXCommonTest(test.TestCase):
self.assertEqual('OS-fakehost-SRP_1-Diamond-DSS-I-MV',
maskingViewDict['maskingViewName'])
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_find_lun',
return_value=(
{'SystemName': EMCVMAXCommonData.storage_system}))
def test_populate_masking_dict_v3_compression(self, mock_find_lun):
extraSpecs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'COMPRESSION_BE',
'storagetype:array': u'1234567891011',
'isV3': True,
'portgroupname': u'OS-portgroup-PG',
'storagetype:slo': u'Diamond',
'storagetype:workload': u'DSS',
'storagetype:disablecompression': 'True'}
connector = self.data.connector
maskingViewDict = self.driver.common._populate_masking_dict(
self.data.test_volume, connector, extraSpecs)
self.assertEqual(
'OS-fakehost-SRP_1-Diamond-DSS-I-CD-SG',
maskingViewDict['sgGroupName'])
self.assertEqual(
'OS-fakehost-SRP_1-Diamond-DSS-I-CD-MV',
maskingViewDict['maskingViewName'])
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_find_lun',
return_value=(
{'SystemName': EMCVMAXCommonData.storage_system}))
def test_populate_masking_dict_v3_compression_no_slo(self, mock_find_lun):
# Compression is no applicable when there is no slo
extraSpecs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'COMPRESSION_BE',
'storagetype:array': u'1234567891011',
'isV3': True,
'portgroupname': u'OS-portgroup-PG',
'storagetype:slo': None,
'storagetype:workload': None,
'storagetype:disablecompression': 'True'}
connector = self.data.connector
maskingViewDict = self.driver.common._populate_masking_dict(
self.data.test_volume, connector, extraSpecs)
self.assertEqual(
'OS-fakehost-No_SLO-I-SG', maskingViewDict['sgGroupName'])
self.assertEqual(
'OS-fakehost-No_SLO-I-MV', maskingViewDict['maskingViewName'])
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_migrate_volume_v3',
return_value=True)
def test_slo_workload_migration_compression_enabled(self, mock_migrate):
extraSpecs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'COMPRESSION_BE',
'storagetype:array': u'1234567891011',
'isV3': True,
'portgroupname': u'OS-portgroup-PG',
'storagetype:slo': u'Diamond',
'storagetype:workload': u'DSS',
'storagetype:disablecompression': 'True'}
new_type_extra_specs = extraSpecs.copy()
new_type_extra_specs.pop('storagetype:disablecompression', None)
new_type = {'extra_specs': new_type_extra_specs}
common = self.driver.common
common.conn = FakeEcomConnection()
volumeName = 'retype_compression'
volumeInstanceName = (
common.conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
volumeInstance = common.conn.GetInstance(volumeInstanceName)
self.assertTrue(self.driver.common._slo_workload_migration(
volumeInstance, self.data.test_source_volume_1_v3,
self.data.test_host_1_v3, volumeName, 'retyping', new_type,
extraSpecs))
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_migrate_volume_v3',
return_value=True)
def test_slo_workload_migration_compression_disabled(self, mock_migrate):
extraSpecs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'COMPRESSION_BE',
'storagetype:array': u'1234567891011',
'isV3': True,
'portgroupname': u'OS-portgroup-PG',
'storagetype:slo': u'Diamond',
'storagetype:workload': u'DSS'}
new_type_extra_specs = extraSpecs.copy()
new_type_extra_specs['storagetype:disablecompression'] = 'True'
new_type = {'extra_specs': new_type_extra_specs}
common = self.driver.common
common.conn = FakeEcomConnection()
volumeName = 'retype_compression'
volumeInstanceName = (
common.conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
volumeInstance = common.conn.GetInstance(volumeInstanceName)
self.assertTrue(self.driver.common._slo_workload_migration(
volumeInstance, self.data.test_source_volume_1_v3,
self.data.test_host_1_v3, volumeName, 'retyping', new_type,
extraSpecs))
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_migrate_volume_v3',
return_value=True)
def test_slo_workload_migration_compression_false(self, mock_migrate):
# Cannot retype because both volume types have the same slo/workload
# and both are false for disable compression, one by omission
extraSpecs = {'storagetype:pool': u'SRP_1',
'volume_backend_name': 'COMPRESSION_BE',
'storagetype:array': u'1234567891011',
'isV3': True,
'portgroupname': u'OS-portgroup-PG',
'storagetype:slo': u'Diamond',
'storagetype:workload': u'DSS'}
new_type_extra_specs = extraSpecs.copy()
new_type_extra_specs['storagetype:disablecompression'] = 'false'
new_type = {'extra_specs': new_type_extra_specs}
common = self.driver.common
common.conn = FakeEcomConnection()
volumeName = 'retype_compression'
volumeInstanceName = (
common.conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
volumeInstance = common.conn.GetInstance(volumeInstanceName)
self.assertFalse(self.driver.common._slo_workload_migration(
volumeInstance, self.data.test_source_volume_1_v3,
self.data.test_host_1_v3, volumeName, 'retyping', new_type,
extraSpecs))
class EMCVMAXProvisionTest(test.TestCase):
def setUp(self):

View File

@ -1320,7 +1320,8 @@ class EMCVMAXCommon(object):
def _is_valid_for_storage_assisted_migration_v3(
self, volumeInstanceName, host, sourceArraySerialNumber,
sourcePoolName, volumeName, volumeStatus, sgName):
sourcePoolName, volumeName, volumeStatus, sgName,
doChangeCompression):
"""Check if volume is suitable for storage assisted (pool) migration.
:param volumeInstanceName: the volume instance id
@ -1331,6 +1332,7 @@ class EMCVMAXCommon(object):
:param volumeName: the name of the volume to be migrated
:param volumeStatus: the status of the volume
:param sgName: storage group name
:param doChangeCompression: do change compression
:returns: boolean -- True/False
:returns: string -- targetSlo
:returns: string -- targetWorkload
@ -1390,13 +1392,16 @@ class EMCVMAXCommon(object):
% {'targetSlo': targetSlo,
'targetWorkload': targetWorkload})
if targetCombination in emcFastSetting:
LOG.error(_LE(
"No action required. Volume: %(volumeName)s is "
"already part of slo/workload combination: "
"%(targetCombination)s."),
{'volumeName': volumeName,
'targetCombination': targetCombination})
return falseRet
# Check if migration is from compression to non compression
# of vice versa
if not doChangeCompression:
LOG.error(_LE(
"No action required. Volume: %(volumeName)s is "
"already part of slo/workload combination: "
"%(targetCombination)s."),
{'volumeName': volumeName,
'targetCombination': targetCombination})
return falseRet
return (True, targetSlo, targetWorkload)
@ -2036,6 +2041,7 @@ class EMCVMAXCommon(object):
protocol = self.utils.get_short_protocol_type(self.protocol)
shortHostName = self.utils.get_host_short_name(hostName)
if isV3:
maskingViewDict['isCompressionDisabled'] = False
slo = extraSpecs[SLO]
workload = extraSpecs[WORKLOAD]
maskingViewDict['slo'] = slo
@ -2050,6 +2056,12 @@ class EMCVMAXCommon(object):
'slo': slo,
'workload': workload,
'protocol': protocol}))
doDisableCompression = self.utils.is_compression_disabled(
extraSpecs)
if doDisableCompression:
prefix = ("%(prefix)s-CD"
% {'prefix': prefix})
maskingViewDict['isCompressionDisabled'] = True
else:
prefix = (
("OS-%(shortHostName)s-No_SLO-%(protocol)s"
@ -3148,13 +3160,15 @@ class EMCVMAXCommon(object):
storageConfigService = self.utils.find_storage_configuration_service(
self.conn, storageSystemName)
doDisableCompression = self.utils.is_compression_disabled(extraSpecs)
# A volume created without specifying a storage group during
# creation time is allocated from the default SRP pool and
# assigned the optimized SLO.
sgInstanceName = self._get_or_create_storage_group_v3(
extraSpecs[POOL], extraSpecs[SLO],
extraSpecs[WORKLOAD], storageSystemName, extraSpecs)
extraSpecs[WORKLOAD], doDisableCompression,
storageSystemName, extraSpecs)
volumeDict, rc = self.provisionv3.create_volume_from_sg(
self.conn, storageConfigService, volumeName,
sgInstanceName, volumeSize, extraSpecs)
@ -3162,23 +3176,40 @@ class EMCVMAXCommon(object):
return rc, volumeDict, storageSystemName
def _get_or_create_storage_group_v3(
self, poolName, slo, workload, storageSystemName, extraSpecs):
self, poolName, slo, workload, doDisableCompression,
storageSystemName, extraSpecs):
"""Get or create storage group_v3 (V3).
:param poolName: the SRP pool nsmr
:param slo: the SLO
:param workload: the workload
:param doDisableCompression: flag for compression
:param storageSystemName: storage system name
:param extraSpecs: extra specifications
:returns: sgInstanceName
"""
storageGroupName, controllerConfigService, sgInstanceName = (
self.utils.get_v3_default_sg_instance_name(
self.conn, poolName, slo, workload, storageSystemName))
self.conn, poolName, slo, workload, storageSystemName,
doDisableCompression))
if sgInstanceName is None:
sgInstanceName = self.provisionv3.create_storage_group_v3(
self.conn, controllerConfigService, storageGroupName,
poolName, slo, workload, extraSpecs)
poolName, slo, workload, extraSpecs, doDisableCompression)
else:
# Check that SG is not part of a masking view
mvInstanceName = self.masking.get_masking_view_from_storage_group(
self.conn, sgInstanceName)
if mvInstanceName:
exceptionMessage = (_(
"Default storage group %(storageGroupName)s is part of "
"masking view %(mvInstanceName)s. Please remove it "
"from this and all masking views")
% {'storageGroupName': storageGroupName,
'mvInstanceName': mvInstanceName})
LOG.error(exceptionMessage)
raise exception.VolumeBackendAPIException(
data=exceptionMessage)
# If qos exists, update storage group to reflect qos parameters
if 'qos' in extraSpecs:
self.utils.update_storagegroup_qos(
@ -3273,14 +3304,20 @@ class EMCVMAXCommon(object):
:param extraSpecs: extra specifications
:returns: boolean -- True if migration succeeded, False if error.
"""
isCompressionDisabled = self.utils.is_compression_disabled(extraSpecs)
storageGroupName = self.utils.get_v3_storage_group_name(
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD])
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD],
isCompressionDisabled)
# Check if old type and new type have different compression types
doChangeCompression = (
self.utils.change_compression_type(
isCompressionDisabled, newType))
volumeInstanceName = volumeInstance.path
isValid, targetSlo, targetWorkload = (
self._is_valid_for_storage_assisted_migration_v3(
volumeInstanceName, host, extraSpecs[ARRAY],
extraSpecs[POOL], volumeName, volumeStatus,
storageGroupName))
storageGroupName, doChangeCompression))
storageSystemName = volumeInstance['SystemName']
if not isValid:
@ -3289,13 +3326,14 @@ class EMCVMAXCommon(object):
"assisted migration using retype."),
{'name': volumeName})
return False
if volume['host'] != host['host']:
if volume['host'] != host['host'] or doChangeCompression:
LOG.debug(
"Retype Volume %(name)s from source host %(sourceHost)s "
"to target host %(targetHost)s.",
"to target host %(targetHost)s. Compression change is %(cc)r.",
{'name': volumeName,
'sourceHost': volume['host'],
'targetHost': host['host']})
'targetHost': host['host'],
'cc': doChangeCompression})
return self._migrate_volume_v3(
volume, volumeInstance, extraSpecs[POOL], targetSlo,
targetWorkload, storageSystemName, newType, extraSpecs)
@ -3325,10 +3363,10 @@ class EMCVMAXCommon(object):
controllerConfigService = (
self.utils.find_controller_configuration_service(
self.conn, storageSystemName))
isCompressionDisabled = self.utils.is_compression_disabled(extraSpecs)
defaultSgName = self.utils.get_v3_storage_group_name(
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD])
extraSpecs[POOL], extraSpecs[SLO], extraSpecs[WORKLOAD],
isCompressionDisabled)
foundStorageGroupInstanceName = (
self.utils.get_storage_group_from_volume(
self.conn, volumeInstance.path, defaultSgName))
@ -3342,12 +3380,16 @@ class EMCVMAXCommon(object):
self.conn, controllerConfigService, volumeInstance,
volumeName, extraSpecs, None, False)
targetExtraSpecs = newType['extra_specs']
isCompressionDisabled = self.utils.is_compression_disabled(
targetExtraSpecs)
storageGroupName = self.utils.get_v3_storage_group_name(
poolName, targetSlo, targetWorkload)
poolName, targetSlo, targetWorkload, isCompressionDisabled)
targetSgInstanceName = self._get_or_create_storage_group_v3(
poolName, targetSlo, targetWorkload, storageSystemName,
extraSpecs)
poolName, targetSlo, targetWorkload, isCompressionDisabled,
storageSystemName, extraSpecs)
if targetSgInstanceName is None:
LOG.error(_LE(
"Failed to get or create storage group %(storageGroupName)s."),
@ -3561,6 +3603,17 @@ class EMCVMAXCommon(object):
extraSpecs[ISV3] = True
extraSpecs = self._set_common_extraSpecs(extraSpecs, poolRecord)
if self.utils.is_all_flash(self.conn, extraSpecs[ARRAY]):
try:
extraSpecs[self.utils.DISABLECOMPRESSION]
# If not True remove it.
if not self.utils.str2bool(
extraSpecs[self.utils.DISABLECOMPRESSION]):
extraSpecs.pop(self.utils.DISABLECOMPRESSION, None)
except KeyError:
pass
else:
extraSpecs.pop(self.utils.DISABLECOMPRESSION, None)
LOG.debug("Pool is: %(pool)s "
"Array is: %(array)s "
"SLO is: %(slo)s "

View File

@ -74,6 +74,7 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
- MVs and SGs not reflecting correct protocol (bug #1640222)
- Storage assisted volume migration via retype
(bp vmax-volume-migration)
- Support for compression on All Flash
"""

View File

@ -80,6 +80,7 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver):
- MVs and SGs not reflecting correct protocol (bug #1640222)
- Storage assisted volume migration via retype
(bp vmax-volume-migration)
- Support for compression on All Flash
"""

View File

@ -203,7 +203,8 @@ class EMCVMAXMasking(object):
defaultSgGroupName = self.utils.get_v3_storage_group_name(
maskingviewdict['pool'],
maskingviewdict['slo'],
maskingviewdict['workload'])
maskingviewdict['workload'],
maskingviewdict['isCompressionDisabled'])
assocStorageGroupInstanceNames = (
self.utils.get_storage_groups_from_volume(
conn, volumeinstance.path))
@ -777,7 +778,8 @@ class EMCVMAXMasking(object):
foundStorageGroupInstanceName = (
self.provisionv3.create_storage_group_v3(
conn, controllerConfigService, storageGroupName,
pool, slo, workload, maskingViewDict['extraSpecs']))
pool, slo, workload, maskingViewDict['extraSpecs'],
maskingViewDict['isCompressionDisabled']))
else:
fastPolicyName = maskingViewDict['fastPolicy']
volumeInstance = maskingViewDict['volumeInstance']
@ -2234,9 +2236,10 @@ class EMCVMAXMasking(object):
:param extraSpecs: additional info
:raises: VolumeBackendAPIException
"""
isCompressionDisabled = self.utils.is_compression_disabled(extraSpecs)
storageGroupName = self.utils.get_v3_storage_group_name(
extraSpecs[self.utils.POOL], extraSpecs[self.utils.SLO],
extraSpecs[self.utils.WORKLOAD])
extraSpecs[self.utils.WORKLOAD], isCompressionDisabled)
storageGroupInstanceName = self.utils.find_storage_masking_group(
conn, controllerConfigurationService, storageGroupName)
@ -2245,7 +2248,8 @@ class EMCVMAXMasking(object):
self.provisionv3.create_storage_group_v3(
conn, controllerConfigurationService, storageGroupName,
extraSpecs[self.utils.POOL], extraSpecs[self.utils.SLO],
extraSpecs[self.utils.WORKLOAD], extraSpecs))
extraSpecs[self.utils.WORKLOAD], extraSpecs,
isCompressionDisabled))
if not storageGroupInstanceName:
errorMessage = (_("Failed to create storage group "
"%(storageGroupName)s.") %

View File

@ -256,11 +256,13 @@ class EMCVMAXProvisionV3(object):
'syncType': syncType,
'source': sourceInstance.path})
storageSystemName = sourceInstance['SystemName']
doDisableCompression = self.utils.is_compression_disabled(extraSpecs)
__, __, sgInstanceName = (
self.utils.get_v3_default_sg_instance_name(
conn, extraSpecs[self.utils.POOL],
extraSpecs[self.utils.SLO],
extraSpecs[self.utils.WORKLOAD], storageSystemName))
extraSpecs[self.utils.WORKLOAD], storageSystemName,
doDisableCompression))
try:
storageGroupInstance = conn.GetInstance(sgInstanceName)
except Exception:
@ -377,7 +379,8 @@ class EMCVMAXProvisionV3(object):
extraSpecs, force)
def create_storage_group_v3(self, conn, controllerConfigService,
groupName, srp, slo, workload, extraSpecs):
groupName, srp, slo, workload, extraSpecs,
doDisableCompression):
"""Create the volume in the specified pool.
:param conn: the connection information to the ecom server
@ -387,28 +390,40 @@ class EMCVMAXProvisionV3(object):
:param slo: the SLO (String)
:param workload: the workload (String)
:param extraSpecs: additional info
:param doDisableCompression: disable compression flag
:returns: storageGroupInstanceName - storage group instance name
"""
startTime = time.time()
@lockutils.synchronized(groupName, "emc-sg-", True)
def do_create_storage_group_v3():
if slo and workload:
rc, job = conn.InvokeMethod(
'CreateGroup',
controllerConfigService,
GroupName=groupName,
Type=self.utils.get_num(4, '16'),
EMCSRP=srp,
EMCSLO=slo,
EMCWorkload=workload)
if doDisableCompression:
if slo and workload:
rc, job = conn.InvokeMethod(
'CreateGroup',
controllerConfigService,
GroupName=groupName,
Type=self.utils.get_num(4, '16'),
EMCSRP=srp,
EMCSLO=slo,
EMCWorkload=workload,
EMCDisableCompression=True)
else:
rc, job = conn.InvokeMethod(
'CreateGroup',
controllerConfigService,
GroupName=groupName,
Type=self.utils.get_num(4, '16'))
if slo and workload:
rc, job = conn.InvokeMethod(
'CreateGroup',
controllerConfigService,
GroupName=groupName,
Type=self.utils.get_num(4, '16'),
EMCSRP=srp,
EMCSLO=slo,
EMCWorkload=workload)
else:
rc, job = conn.InvokeMethod(
'CreateGroup',
controllerConfigService,
GroupName=groupName,
Type=self.utils.get_num(4, '16'))
if rc != 0:
rc, errordesc = self.utils.wait_for_job_complete(
conn, job, extraSpecs)

View File

@ -63,6 +63,7 @@ RETRIES = 'storagetype:retries'
CIM_ERR_NOT_FOUND = 6
VOLUME_ELEMENT_NAME_PREFIX = 'OS-'
SYNCHRONIZED = 4
SMI_VERSION_83 = 830
class EMCVMAXUtils(object):
@ -74,6 +75,7 @@ class EMCVMAXUtils(object):
SLO = 'storagetype:slo'
WORKLOAD = 'storagetype:workload'
POOL = 'storagetype:pool'
DISABLECOMPRESSION = 'storagetype:disablecompression'
def __init__(self, prtcl):
if not pywbemAvailable:
@ -1571,21 +1573,31 @@ class EMCVMAXUtils(object):
return isValidSLO, isValidWorkload
def get_v3_storage_group_name(self, poolName, slo, workload):
def get_v3_storage_group_name(self, poolName, slo, workload,
isCompressionDisabled):
"""Determine default v3 storage group from extraSpecs.
:param poolName: the poolName
:param slo: the SLO string e.g Bronze
:param workload: the workload string e.g DSS
:param isCompressionDisabled: is compression disabled
:returns: storageGroupName
"""
if slo and workload:
storageGroupName = ("OS-%(poolName)s-%(slo)s-%(workload)s-SG"
% {'poolName': poolName,
'slo': slo,
'workload': workload})
if isCompressionDisabled:
postfix = 'CD-SG'
else:
postfix = 'SG'
storageGroupName = (
"OS-%(poolName)s-%(slo)s-%(workload)s-%(postfix)s"
% {'poolName': poolName,
'slo': slo,
'workload': workload,
'postfix': postfix})
else:
storageGroupName = ("OS-no_SLO-SG")
return storageGroupName
def _get_fast_settings_from_storage_group(self, storageGroupInstance):
@ -2611,7 +2623,8 @@ class EMCVMAXUtils(object):
return rsdInstance
def get_v3_default_sg_instance_name(
self, conn, poolName, slo, workload, storageSystemName):
self, conn, poolName, slo, workload, storageSystemName,
isCompressionDisabled):
"""Get the V3 default instance name
:param conn: the connection to the ecom server
@ -2619,10 +2632,11 @@ class EMCVMAXUtils(object):
:param slo: the SLO
:param workload: the workload
:param storageSystemName: the storage system name
:param isCompressionDisabled: is compression disabled
:returns: the storage group instance name
"""
storageGroupName = self.get_v3_storage_group_name(
poolName, slo, workload)
poolName, slo, workload, isCompressionDisabled)
controllerConfigService = (
self.find_controller_configuration_service(
conn, storageSystemName))
@ -2823,3 +2837,74 @@ class EMCVMAXUtils(object):
"%(igName)s.",
{'igName': foundinitiatorGroupInstanceName})
return foundinitiatorGroupInstanceName
def is_all_flash(self, conn, array):
"""Check if array is all flash.
:param conn: connection the ecom server
:param array:
:returns: True/False
"""
smi_version = self.get_smi_version(conn)
if smi_version >= SMI_VERSION_83:
return self._is_all_flash(conn, array)
else:
return False
def _is_all_flash(self, conn, array):
"""Check if array is all flash.
:param conn: connection the ecom server
:param array:
:returns: True/False
"""
is_all_flash = False
arrayChassisInstanceNames = conn.EnumerateInstanceNames(
'Symm_ArrayChassis')
for arrayChassisInstanceName in arrayChassisInstanceNames:
tag = arrayChassisInstanceName['Tag']
if array in tag:
arrayChassisInstance = (
conn.GetInstance(arrayChassisInstanceName))
propertiesList = arrayChassisInstance.properties.items()
for properties in propertiesList:
if properties[0] == 'Model':
cimProperties = properties[1]
model = cimProperties.value
if re.search('^VMAX\s?[0-9]+FX?$', model):
is_all_flash = True
return is_all_flash
def is_compression_disabled(self, extraSpecs):
"""Check is compression is to be disabled.
:param extraSpecs: extra specifications
:returns: dict -- a dictionary with masking view information
"""
doDisableCompression = False
if self.DISABLECOMPRESSION in extraSpecs:
if self.str2bool(extraSpecs[self.DISABLECOMPRESSION]):
doDisableCompression = True
return doDisableCompression
def change_compression_type(self, isSourceCompressionDisabled, newType):
"""Check if volume type have different compression types.
:param isCompressionDisabled: from source
:param newType: from target
:returns: boolean
"""
extraSpecs = newType['extra_specs']
isTargetCompressionDisabled = self.is_compression_disabled(extraSpecs)
if isTargetCompressionDisabled == isSourceCompressionDisabled:
return False
else:
return True
def str2bool(self, value):
"""Check if value is yes or true.
:param value - string value
:returns: boolean
"""
return value.lower() in ("yes", "true")

View File

@ -0,0 +1,3 @@
---
features:
- Support for compression on VMAX All Flash in the VMAX driver.