From f6fdae1438e5af67b6d7bf1919e25d8a8bc42bd6 Mon Sep 17 00:00:00 2001 From: Helen Walsh Date: Thu, 26 Nov 2015 15:29:06 +0000 Subject: [PATCH] EMC VMAX - Incorrect SG selected on an VMAX3 attach Use the default storage group for an SLO/Workload combination and not the storage group that will be part of the Masking View(contains the host name). Change-Id: I195dd0113103930af6e54e19afeebf33f979e8fa Closes-Bug: #1515176 --- cinder/tests/unit/test_emc_vmax.py | 64 +++++++++++++++++++ cinder/volume/drivers/emc/emc_vmax_fc.py | 1 + cinder/volume/drivers/emc/emc_vmax_iscsi.py | 1 + cinder/volume/drivers/emc/emc_vmax_masking.py | 64 ++++++++++++------- 4 files changed, 106 insertions(+), 24 deletions(-) diff --git a/cinder/tests/unit/test_emc_vmax.py b/cinder/tests/unit/test_emc_vmax.py index ec62c5881..29088b3c1 100644 --- a/cinder/tests/unit/test_emc_vmax.py +++ b/cinder/tests/unit/test_emc_vmax.py @@ -7174,3 +7174,67 @@ class EMCVMAXProvisionV3Test(test.TestCase): provisionv3.extend_volume_in_SG, conn, storageConfigService, theVolumeInstanceName, inVolumeInstanceName, volumeSize, extraSpecs) + + +class EMCVMAXMaskingTest(test.TestCase): + def setUp(self): + self.data = EMCVMAXCommonData() + + super(EMCVMAXMaskingTest, self).setUp() + + configuration = mock.Mock() + configuration.safe_get.return_value = 'MaskingTests' + configuration.config_group = 'MaskingTests' + emc_vmax_common.EMCVMAXCommon._get_ecom_connection = mock.Mock( + return_value=self.fake_ecom_connection()) + emc_vmax_common.EMCVMAXCommon._gather_info = mock.Mock( + return_value=self.fake_gather_info()) + instancename = FakeCIMInstanceName() + emc_vmax_utils.EMCVMAXUtils.get_instance_name = ( + instancename.fake_getinstancename) + driver = emc_vmax_iscsi.EMCVMAXISCSIDriver(configuration=configuration) + driver.db = FakeDB() + self.driver = driver + self.driver.utils = emc_vmax_utils.EMCVMAXUtils(object) + + def fake_ecom_connection(self): + conn = FakeEcomConnection() + return conn + + def fake_gather_info(self): + return + + def test_get_v3_default_storage_group_instance_name(self): + masking = self.driver.common.masking + conn = self.fake_ecom_connection() + extraSpecs = self.data.extra_specs + masking._get_and_remove_from_storage_group_v3 = mock.Mock() + controllerConfigService = ( + self.driver.utils.find_controller_configuration_service( + conn, self.data.storage_system)) + maskingviewdict = self.driver.common._populate_masking_dict( + self.data.test_volume, self.data.connector, extraSpecs) + result = ( + masking._get_v3_default_storagegroup_instancename( + conn, maskingviewdict['volumeInstance'], + maskingviewdict, + controllerConfigService, maskingviewdict['volumeName'])) + self.assertEqual('OS-SRP_1-Bronze-DSS-SG', result['ElementName']) + + def test_get_v3_default_storage_group_instance_name_warning(self): + masking = self.driver.common.masking + conn = self.fake_ecom_connection() + extraSpecs = self.data.extra_specs + masking.utils.get_storage_groups_from_volume = mock.Mock( + return_value=[]) + controllerConfigService = ( + self.driver.utils.find_controller_configuration_service( + conn, self.data.storage_system)) + maskingviewdict = self.driver.common._populate_masking_dict( + self.data.test_volume, self.data.connector, extraSpecs) + result = ( + masking._get_v3_default_storagegroup_instancename( + conn, maskingviewdict['volumeInstance'], + maskingviewdict, + controllerConfigService, maskingviewdict['volumeName'])) + self.assertIsNone(result) diff --git a/cinder/volume/drivers/emc/emc_vmax_fc.py b/cinder/volume/drivers/emc/emc_vmax_fc.py index 690faadd6..b909561c1 100644 --- a/cinder/volume/drivers/emc/emc_vmax_fc.py +++ b/cinder/volume/drivers/emc/emc_vmax_fc.py @@ -49,6 +49,7 @@ class EMCVMAXFCDriver(driver.FibreChannelDriver): - Proper error handling for invalid SLOs (bug #1512795) - Extend Volume for VMAX3, SE8.1.0.3 https://blueprints.launchpad.net/cinder/+spec/vmax3-extend-volume + - Incorrect SG selected on an attach (#1515176) """ VERSION = "2.3.0" diff --git a/cinder/volume/drivers/emc/emc_vmax_iscsi.py b/cinder/volume/drivers/emc/emc_vmax_iscsi.py index 97525de78..489ae583b 100644 --- a/cinder/volume/drivers/emc/emc_vmax_iscsi.py +++ b/cinder/volume/drivers/emc/emc_vmax_iscsi.py @@ -57,6 +57,7 @@ class EMCVMAXISCSIDriver(driver.ISCSIDriver): - Proper error handling for invalid SLOs (bug #1512795) - Extend Volume for VMAX3, SE8.1.0.3 https://blueprints.launchpad.net/cinder/+spec/vmax3-extend-volume + - Incorrect SG selected on an attach (#1515176) """ VERSION = "2.3.0" diff --git a/cinder/volume/drivers/emc/emc_vmax_masking.py b/cinder/volume/drivers/emc/emc_vmax_masking.py index f0627f0ae..b4b595bbc 100644 --- a/cinder/volume/drivers/emc/emc_vmax_masking.py +++ b/cinder/volume/drivers/emc/emc_vmax_masking.py @@ -91,30 +91,11 @@ class EMCVMAXMasking(object): assocStorageGroupName = None if isLiveMigration is False: if isV3: - assocStorageGroupInstanceName = ( - self.utils.get_storage_group_from_volume( - conn, volumeInstance.path, - maskingViewDict['sgGroupName'])) - instance = conn.GetInstance( - assocStorageGroupInstanceName, LocalOnly=False) - assocStorageGroupName = instance['ElementName'] - defaultSgGroupName = self.utils.get_v3_storage_group_name( - maskingViewDict['pool'], - maskingViewDict['slo'], - maskingViewDict['workload']) - - if assocStorageGroupName != defaultSgGroupName: - LOG.warning(_LW( - "Volume: %(volumeName)s Does not belong " - "to storage storage group %(defaultSgGroupName)s."), - {'volumeName': volumeName, - 'defaultSgGroupName': defaultSgGroupName}) - defaultStorageGroupInstanceName = assocStorageGroupInstanceName - - self._get_and_remove_from_storage_group_v3( - conn, controllerConfigService, volumeInstance.path, - volumeName, maskingViewDict, - defaultStorageGroupInstanceName) + defaultStorageGroupInstanceName = ( + self._get_v3_default_storagegroup_instancename( + conn, volumeInstance, maskingViewDict, + controllerConfigService, volumeName)) + else: fastPolicyName = maskingViewDict['fastPolicy'] # If FAST is enabled remove the volume from the default SG. @@ -191,6 +172,41 @@ class EMCVMAXMasking(object): return rollbackDict + def _get_v3_default_storagegroup_instancename(self, conn, volumeinstance, + maskingviewdict, + controllerConfigService, + volumeName): + defaultStorageGroupInstanceName = None + defaultSgGroupName = self.utils.get_v3_storage_group_name( + maskingviewdict['pool'], + maskingviewdict['slo'], + maskingviewdict['workload']) + assocStorageGroupInstanceNames = ( + self.utils.get_storage_groups_from_volume( + conn, volumeinstance.path)) + for assocStorageGroupInstanceName in ( + assocStorageGroupInstanceNames): + instance = conn.GetInstance( + assocStorageGroupInstanceName, LocalOnly=False) + assocStorageGroupName = instance['ElementName'] + + if assocStorageGroupName == defaultSgGroupName: + defaultStorageGroupInstanceName = ( + assocStorageGroupInstanceName) + break + if defaultStorageGroupInstanceName: + self._get_and_remove_from_storage_group_v3( + conn, controllerConfigService, volumeinstance.path, + volumeName, maskingviewdict, + defaultStorageGroupInstanceName) + else: + LOG.warning(_LW( + "Volume: %(volumeName)s does not belong " + "to storage group %(defaultSgGroupName)s."), + {'volumeName': volumeName, + 'defaultSgGroupName': defaultSgGroupName}) + return defaultStorageGroupInstanceName + def _validate_masking_view(self, conn, maskingViewDict, defaultStorageGroupInstanceName, extraSpecs): -- 2.45.2