Merge "VMAX Driver - QoS support for the VMAX3"

This commit is contained in:
Jenkins 2016-08-16 01:02:10 +00:00 committed by Gerrit Code Review
commit be7c9d4a44
6 changed files with 148 additions and 7 deletions

View File

@ -726,7 +726,7 @@ class FakeEcomConnection(object):
return result
def ModifyInstance(self, objectpath, PropertyList=None):
pass
pass
def DeleteInstance(self, objectpath):
pass
@ -1164,6 +1164,14 @@ class FakeEcomConnection(object):
else:
targetmaskinggroup['ElementName'] = (
self.data.storagegroupname)
if 'EMCMaximumIO' in objectpath:
targetmaskinggroup['EMCMaximumIO'] = objectpath['EMCMaximumIO']
if 'EMCMaximumBandwidth' in objectpath:
targetmaskinggroup['EMCMaximumBandwidth'] = (
objectpath['EMCMaximumBandwidth'])
if 'EMCMaxIODynamicDistributionType' in objectpath:
targetmaskinggroup['EMCMaxIODynamicDistributionType'] = (
objectpath['EMCMaxIODynamicDistributionType'])
return targetmaskinggroup
def _getinstance_unit(self, objectpath):
@ -6242,8 +6250,8 @@ class EMCV3DriverTestCase(test.TestCase):
'get_volume_type_extra_specs',
return_value={'volume_backend_name': 'V3_BE'})
def test_create_cgsnapshot_v3_success(
self, _mock_volume_type, _mock_storage, _mock_cg, _mock_members,
mock_rg):
self, _mock_volume_type, _mock_storage, _mock_cg,
_mock_members, mock_rg):
provisionv3 = self.driver.common.provisionv3
provisionv3.create_group_replica = mock.Mock(return_value=(0, None))
self.driver.create_cgsnapshot(
@ -6448,6 +6456,9 @@ class EMCV3DriverTestCase(test.TestCase):
targetInstance = (
conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
deviceID = targetInstance['DeviceID']
common._delete_from_pool_v3(storageConfigService, targetInstance,
targetInstance['Name'], deviceID,
extraSpecs)
common._delete_from_pool_v3.assert_called_with(storageConfigService,
targetInstance,
targetInstance['Name'],
@ -7162,7 +7173,6 @@ class EMCV2MultiPoolDriverMultipleEcomsTestCase(test.TestCase):
self.fake_sleep)
self.stubs.Set(emc_vmax_utils.EMCVMAXUtils, 'isArrayV3',
self.fake_is_v3)
driver = emc_vmax_fc.EMCVMAXFCDriver(configuration=configuration)
driver.db = FakeDB()
driver.common.conn = FakeEcomConnection()
@ -8001,6 +8011,51 @@ class EMCVMAXUtilsTest(test.TestCase):
self.driver.utils.get_ratio_from_max_sub_per(str(0)))
self.assertIsNone(max_subscription_percent_float)
def test_update_storage_QOS(self):
conn = FakeEcomConnection()
pywbem = mock.Mock()
pywbem.cim_obj = mock.Mock()
pywbem.cim_obj.CIMInstance = mock.Mock()
emc_vmax_utils.pywbem = pywbem
extraSpecs = {'volume_backend_name': 'V3_BE',
'qos': {
'maxIOPS': '6000',
'maxMBPS': '6000',
'DistributionType': 'Always'
}}
storageGroupInstanceName = {
'CreationClassName': 'CIM_DeviceMaskingGroup',
'EMCMaximumIO': 6000,
'EMCMaximumBandwidth': 5000,
'EMCMaxIODynamicDistributionType': 1
}
modifiedstorageGroupInstance = {
'CreationClassName': 'CIM_DeviceMaskingGroup',
'EMCMaximumIO': 6000,
'EMCMaximumBandwidth': 6000,
'EMCMaxIODynamicDistributionType': 1
}
conn.ModifyInstance = (
mock.Mock(return_value=modifiedstorageGroupInstance))
self.driver.common.utils.update_storagegroup_qos(
conn, storageGroupInstanceName, extraSpecs)
modifiedInstance = self.driver.common.utils.update_storagegroup_qos(
conn, storageGroupInstanceName, extraSpecs)
self.assertIsNotNone(modifiedInstance)
self.assertEqual(
6000, modifiedInstance['EMCMaximumIO'])
self.assertEqual(
6000, modifiedInstance['EMCMaximumBandwidth'])
self.assertEqual(
1, modifiedInstance['EMCMaxIODynamicDistributionType'])
self.assertEqual('CIM_DeviceMaskingGroup',
modifiedInstance['CreationClassName'])
class EMCVMAXCommonTest(test.TestCase):
def setUp(self):

View File

@ -1306,6 +1306,7 @@ class EMCVMAXCommon(object):
:returns: string -- configuration file
"""
extraSpecs = self.utils.get_volumetype_extraspecs(volume, volumeTypeId)
qosSpecs = self.utils.get_volumetype_qosspecs(volume, volumeTypeId)
configGroup = None
# If there are no extra specs then the default case is assumed.
@ -1313,8 +1314,7 @@ class EMCVMAXCommon(object):
configGroup = self.configuration.config_group
configurationFile = self._register_config_file_from_config_group(
configGroup)
return extraSpecs, configurationFile
return extraSpecs, configurationFile, qosSpecs
def _get_ecom_connection(self):
"""Get the ecom connection.
@ -1751,7 +1751,7 @@ class EMCVMAXCommon(object):
:raises: VolumeBackendAPIException
"""
try:
extraSpecs, configurationFile = (
extraSpecs, configurationFile, qosSpecs = (
self._set_config_file_and_get_extra_specs(
volume, volumeTypeId))
@ -1777,6 +1777,9 @@ class EMCVMAXCommon(object):
else:
# V2 extra specs
extraSpecs = self._set_v2_extra_specs(extraSpecs, poolRecord)
if (qosSpecs.get('qos_spec')
and qosSpecs['qos_specs']['consumer'] != "front-end"):
extraSpecs['qos'] = qosSpecs['qos_specs']['specs']
except Exception:
import sys
exceptionMessage = (_(
@ -2893,6 +2896,10 @@ class EMCVMAXCommon(object):
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(
self.conn, defaultStorageGroupInstanceName, extraSpecs)
self._add_volume_to_default_storage_group_on_create(
volumeDict, volumeName, storageConfigService,
@ -2981,6 +2988,10 @@ class EMCVMAXCommon(object):
sgInstanceName = self.provisionv3.create_storage_group_v3(
self.conn, controllerConfigService, storageGroupName,
poolName, slo, workload, extraSpecs)
# If qos exists, update storage group to reflect qos parameters
if 'qos' in extraSpecs:
self.utils.update_storagegroup_qos(
self.conn, sgInstanceName, extraSpecs)
return sgInstanceName

View File

@ -70,6 +70,7 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver):
2.4.0 - EMC VMAX - locking SG for concurrent threads (bug #1554634)
- SnapVX licensing checks for VMAX3 (bug #1587017)
- VMAX oversubscription Support (blueprint vmax-oversubscription)
- QoS support (blueprint vmax-qos)
"""
VERSION = "2.4.0"

View File

@ -76,6 +76,7 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver):
2.4.0 - EMC VMAX - locking SG for concurrent threads (bug #1554634)
- SnapVX licensing checks for VMAX3 (bug #1587017)
- VMAX oversubscription Support (blueprint vmax-oversubscription)
- QoS support (blueprint vmax-qos)
"""

View File

@ -1083,6 +1083,28 @@ class EMCVMAXUtils(object):
return extraSpecs
def get_volumetype_qosspecs(self, volume, volumeTypeId=None):
"""Get the qos specs.
:param volume: the volume dictionary
:param volumeTypeId: Optional override for volume['volume_type_id']
:returns: dict -- qosSpecs - the qos specs
"""
qosSpecs = {}
try:
if volumeTypeId:
type_id = volumeTypeId
else:
type_id = volume['volume_type_id']
if type_id is not None:
qosSpecs = volume_types.get_volume_type_qos_specs(type_id)
except Exception:
LOG.debug("Unable to get QoS specifications.")
return qosSpecs
def get_volume_type_name(self, volume):
"""Get the volume type name.
@ -2645,3 +2667,51 @@ class EMCVMAXUtils(object):
max_over_sub_ratio = float(max_sub_ratio_from_per)
return max_over_sub_ratio
def update_storagegroup_qos(self, conn, storagegroup, extraspecs):
"""Update the storagegroupinstance with qos details.
If MaxIOPS or maxMBPS is in extraspecs, then DistributionType can be
modified in addition to MaxIOPS or/and maxMBPS
If MaxIOPS or maxMBPS is NOT in extraspecs, we check to see if
either is set in StorageGroup. If so, then DistributionType can be
modified
:param conn: connection to the ecom server
:param storagegroup: the storagegroup instance name
:param extraSpecs: extra specifications
"""
if type(storagegroup) is pywbem.cim_obj.CIMInstance:
storagegroupInstance = storagegroup
else:
storagegroupInstance = conn.GetInstance(storagegroup)
propertylist = []
if 'maxIOPS' in extraspecs.get('qos'):
maxiops = self.get_num(extraspecs.get('qos').get('maxIOPS'), '32')
if maxiops != storagegroupInstance['EMCMaximumIO']:
storagegroupInstance['EMCMaximumIO'] = maxiops
propertylist.append('EMCMaximumIO')
if 'maxMBPS' in extraspecs.get('qos'):
maxmbps = self.get_num(extraspecs.get('qos').get('maxMBPS'), '32')
if maxmbps != storagegroupInstance['EMCMaximumBandwidth']:
storagegroupInstance['EMCMaximumBandwidth'] = maxmbps
propertylist.append('EMCMaximumBandwidth')
if 'DistributionType' in extraspecs.get('qos') and (
propertylist or (
storagegroupInstance['EMCMaximumBandwidth'] != 0) or (
storagegroupInstance['EMCMaximumIO'] != 0)):
dynamicdict = {'never': 1, 'onfailure': 2, 'always': 3}
dynamicvalue = dynamicdict.get(
extraspecs.get('qos').get('DistributionType').lower())
if dynamicvalue:
distributiontype = self.get_num(dynamicvalue, '16')
if distributiontype != (
storagegroupInstance['EMCMaxIODynamicDistributionType']
):
storagegroupInstance['EMCMaxIODynamicDistributionType'] = (
distributiontype)
propertylist.append('EMCMaxIODynamicDistributionType')
if propertylist:
modifiedInstance = conn.ModifyInstance(storagegroupInstance,
PropertyList=propertylist)
return modifiedInstance

View File

@ -0,0 +1,3 @@
---
features:
- QoS support for the VMAX.