From 5d4a12cf6120d82654268d20ba50876a0f3a8c16 Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Thu, 2 Apr 2015 01:03:08 -0400 Subject: [PATCH] Fix issues with extra specs in VMAX driver This patch is related to https://review.openstack.org/162658. It continues to address the problem with the extra specs. Extra specs should not be overwritten by the config file settings. Change-Id: Ie30d0165b17ceb7c12aff6783232eb3b827df930 Closes-Bug: #1439506 --- cinder/tests/unit/test_emc_vmax.py | 43 ++++++- cinder/volume/drivers/emc/emc_vmax_common.py | 17 ++- cinder/volume/drivers/emc/emc_vmax_masking.py | 105 +++++++++++------- cinder/volume/drivers/emc/emc_vmax_utils.py | 21 ++-- 4 files changed, 132 insertions(+), 54 deletions(-) diff --git a/cinder/tests/unit/test_emc_vmax.py b/cinder/tests/unit/test_emc_vmax.py index f141a010c..bbf097d85 100644 --- a/cinder/tests/unit/test_emc_vmax.py +++ b/cinder/tests/unit/test_emc_vmax.py @@ -1810,7 +1810,6 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase): def test_wait_for_sync(self): mysync = 'fakesync' conn = self.fake_ecom_connection() - self.driver.utils._is_sync_complete = mock.Mock( return_value=True) rc = self.driver.utils.wait_for_sync(conn, mysync) @@ -1832,6 +1831,40 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase): loopingcall.FixedIntervalLoopingCall.reset_mock() loopingcall.FixedIntervalLoopingCall = loopingcall_orig + def test_wait_for_sync_extra_specs(self): + mysync = 'fakesync' + conn = self.fake_ecom_connection() + self.create_fake_config_file_no_fast_with_add_ons() + extraSpecs = {'volume_backend_name': 'ISCSINoFAST'} + extraSpecs = ( + self.driver.common._get_job_extra_specs(self.config_file_path, + extraSpecs)) + + self.driver.utils._is_sync_complete = mock.Mock( + return_value=True) + rc = self.driver.utils.wait_for_sync(conn, mysync, extraSpecs) + self.assertIsNone(rc) + self.driver.utils._is_sync_complete.assert_called_once_with( + conn, mysync) + self.assertEqual( + True, + self.driver.utils._is_sync_complete.return_value) + self.assertEqual(40, + self.driver.utils._get_max_job_retries(extraSpecs)) + self.assertEqual(5, + self.driver.utils._get_interval_in_secs(extraSpecs)) + self.driver.utils._is_sync_complete.reset_mock() + + # Save the original state and restore it after this test + loopingcall_orig = loopingcall.FixedIntervalLoopingCall + loopingcall.FixedIntervalLoopingCall = mock.Mock() + rc = self.driver.utils.wait_for_sync(conn, mysync) + self.assertIsNone(rc) + loopingcall.FixedIntervalLoopingCall.assert_called_once_with( + mock.ANY) + loopingcall.FixedIntervalLoopingCall.reset_mock() + loopingcall.FixedIntervalLoopingCall = loopingcall_orig + # Bug 1395830: _find_lun throws exception when lun is not found. def test_find_lun(self): keybindings = {'CreationClassName': u'Symm_StorageVolume', @@ -1891,6 +1924,10 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase): # Bug 1403160 - make sure the masking view is cleanly deleted def test_last_volume_delete_masking_view(self): + extraSpecs = {'volume_backend_name': 'ISCSINoFAST'} + extraSpecs = ( + self.driver.common._get_job_extra_specs(self.config_file_path, + extraSpecs)) conn = self.fake_ecom_connection() controllerConfigService = ( self.driver.utils.find_controller_configuration_service( @@ -1908,14 +1945,14 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase): exception.VolumeBackendAPIException, self.driver.common.masking._last_volume_delete_masking_view, conn, controllerConfigService, maskingViewInstanceName, - maskingViewName) + maskingViewName, extraSpecs) # Deleting Masking view successful self.driver.common.masking.utils.get_existing_instance = mock.Mock( return_value=None) self.driver.common.masking._last_volume_delete_masking_view( conn, controllerConfigService, maskingViewInstanceName, - maskingViewName) + maskingViewName, extraSpecs) # Bug 1403160 - make sure the storage group is cleanly deleted def test_remove_last_vol_and_delete_sg(self): diff --git a/cinder/volume/drivers/emc/emc_vmax_common.py b/cinder/volume/drivers/emc/emc_vmax_common.py index aadf3184b..223de5bda 100644 --- a/cinder/volume/drivers/emc/emc_vmax_common.py +++ b/cinder/volume/drivers/emc/emc_vmax_common.py @@ -234,7 +234,7 @@ class EMCVMAXCommon(object): storageSystem = snapshotInstance['SystemName'] syncName = self.utils.find_sync_sv_by_target( - self.conn, storageSystem, snapshotInstance, True) + self.conn, storageSystem, snapshotInstance, extraSpecs, True) if syncName is not None: repservice = self.utils.find_replication_service(self.conn, storageSystem) @@ -1336,12 +1336,13 @@ class EMCVMAXCommon(object): return foundVolumeinstance - def _find_storage_sync_sv_sv(self, snapshot, volume, + def _find_storage_sync_sv_sv(self, snapshot, volume, extraSpecs, waitforsync=True): """Find the storage synchronized name. :param snapshot: snapshot object :param volume: volume object + :param extraSpecs: extra specifications :param waitforsync: boolean -- Wait for Solutions Enabler sync. :returns: string -- foundsyncname :returns: string -- storage_system @@ -1372,7 +1373,8 @@ class EMCVMAXCommon(object): 'sync': foundsyncname}) # Wait for SE_StorageSynchronized_SV_SV to be fully synced. if waitforsync: - self.utils.wait_for_sync(self.conn, foundsyncname) + self.utils.wait_for_sync(self.conn, foundsyncname, + extraSpecs) return foundsyncname, storage_system @@ -2276,7 +2278,8 @@ class EMCVMAXCommon(object): # Wait for it to fully sync in case there is an ongoing # create volume from snapshot request. syncName = self.utils.find_sync_sv_by_target( - self.conn, storageSystem, snapshotInstance, True) + self.conn, storageSystem, snapshotInstance, extraSpecs, + True) if syncName is None: LOG.info(_LI( @@ -2547,7 +2550,8 @@ class EMCVMAXCommon(object): targetCgInstanceName, relationName, extraSpecs) # Break the replica group relationship. rgSyncInstanceName = self.utils.find_group_sync_rg_by_target( - self.conn, storageSystem, targetCgInstanceName, True) + self.conn, storageSystem, targetCgInstanceName, extraSpecs, + True) if rgSyncInstanceName is not None: repservice = self.utils.find_replication_service( self.conn, storageSystem) @@ -3789,7 +3793,8 @@ class EMCVMAXCommon(object): cloneVolume['provider_location'] = six.text_type(cloneDict) syncInstanceName, _storageSystem = ( - self._find_storage_sync_sv_sv(cloneVolume, sourceVolume, True)) + self._find_storage_sync_sv_sv(cloneVolume, sourceVolume, + extraSpecs, True)) # Detach/dissolve the clone/snap relationship. # 8 - Detach operation. diff --git a/cinder/volume/drivers/emc/emc_vmax_masking.py b/cinder/volume/drivers/emc/emc_vmax_masking.py index 2d0d2b07d..2a0d0a368 100644 --- a/cinder/volume/drivers/emc/emc_vmax_masking.py +++ b/cinder/volume/drivers/emc/emc_vmax_masking.py @@ -130,7 +130,8 @@ class EMCVMAXMasking(object): try: maskingViewInstanceName, storageGroupInstanceName, errorMessage = ( self._validate_masking_view(conn, maskingViewDict, - defaultStorageGroupInstanceName)) + defaultStorageGroupInstanceName, + extraSpecs)) LOG.debug( "The masking view in the attach operation is " "%(maskingViewInstanceName)s. The storage group " @@ -191,12 +192,14 @@ class EMCVMAXMasking(object): return rollbackDict def _validate_masking_view(self, conn, maskingViewDict, - defaultStorageGroupInstanceName): + defaultStorageGroupInstanceName, + extraSpecs): """Validate all the individual pieces of the masking view. :param conn: the ecom connection :param maskingViewDict: the masking view dictionary :param defaultStorageGroupInstanceName: the default SG + :param extraSpecs: extra specifications :returns: maskingViewInstanceName :returns: storageGroupInstanceName, :returns: string -- errorMessage @@ -209,22 +212,26 @@ class EMCVMAXMasking(object): if maskingViewInstanceName is None: maskingViewInstanceName, storageGroupInstanceName, errorMessage = ( self._validate_new_masking_view( - conn, maskingViewDict, defaultStorageGroupInstanceName)) + conn, maskingViewDict, defaultStorageGroupInstanceName, + extraSpecs)) else: storageGroupInstanceName, errorMessage = ( self._validate_existing_masking_view( - conn, maskingViewDict, maskingViewInstanceName)) + conn, maskingViewDict, maskingViewInstanceName, + extraSpecs)) return maskingViewInstanceName, storageGroupInstanceName, errorMessage def _validate_new_masking_view(self, conn, maskingViewDict, - defaultStorageGroupInstanceName): + defaultStorageGroupInstanceName, + extraSpecs): """Validate the creation of a new masking view. :param conn: the ecom connection :param maskingViewDict: the masking view dictionary :param defaultStorageGroupInstanceName: the default SG + :param extraSpecs: extra specifications :returns: maskingViewInstanceName :returns: storageGroupInstanceName, :returns: string -- errorMessage @@ -251,7 +258,7 @@ class EMCVMAXMasking(object): initiatorGroupInstanceName, errorMessage = ( self._check_initiator_group(conn, controllerConfigService, igGroupName, connector, - storageSystemName)) + storageSystemName, extraSpecs)) if errorMessage: return None, storageGroupInstanceName, errorMessage @@ -268,18 +275,20 @@ class EMCVMAXMasking(object): self._check_masking_view( conn, controllerConfigService, maskingViewName, storageGroupInstanceName, - portGroupInstanceName, initiatorGroupInstanceName)) + portGroupInstanceName, initiatorGroupInstanceName, + extraSpecs)) return maskingViewInstanceName, storageGroupInstanceName, errorMessage def _validate_existing_masking_view(self, conn, maskingViewDict, - maskingViewInstanceName): + maskingViewInstanceName, extraSpecs): """Validate the components of an existing masking view. :param conn: the ecom connection :param maskingViewDict: the masking view dictionary :param maskingViewInstanceName: the masking view instance name + :param extraSpecs: extra specification :returns: storageGroupInstanceName :returns: string -- errorMessage """ @@ -294,7 +303,7 @@ class EMCVMAXMasking(object): # First verify that the initiator group matches the initiators. errorMessage = self._check_existing_initiator_group( conn, controllerConfigService, maskingViewName, - connector, storageSystemName, igGroupName) + connector, storageSystemName, igGroupName, extraSpecs) if errorMessage: return storageGroupInstanceName, errorMessage @@ -382,7 +391,7 @@ class EMCVMAXMasking(object): def _check_initiator_group( self, conn, controllerConfigService, igGroupName, - connector, storageSystemName): + connector, storageSystemName, extraSpecs): """Check that initiator group can be either retrieved or created. :param conn: the ecom connection @@ -390,6 +399,7 @@ class EMCVMAXMasking(object): :param igGroupName: the initiator group Name :param connector: the connector object :param storageSystemName: the storage system name + :param extraSpecs: extra specifications :returns: initiatorGroupInstanceName :returns: string -- the error message """ @@ -397,7 +407,7 @@ class EMCVMAXMasking(object): initiatorGroupInstanceName = ( self._get_initiator_group_instance_name( conn, controllerConfigService, igGroupName, connector, - storageSystemName)) + storageSystemName, extraSpecs)) if initiatorGroupInstanceName is None: # This may be used in exception hence _ instead of _LE. msg = (_( @@ -410,7 +420,7 @@ class EMCVMAXMasking(object): def _check_existing_initiator_group( self, conn, controllerConfigService, maskingViewName, - connector, storageSystemName, igGroupName): + connector, storageSystemName, igGroupName, extraSpecs): """Check that existing initiator group in the masking view. Check if the initiators in the initiator group match those in the @@ -422,12 +432,14 @@ class EMCVMAXMasking(object): :param connector: the connector object :param storageSystemName: the storage system name :param igGroupName: the initiator group name + :param extraSpecs: extra specification :returns: string -- msg, the error message """ msg = None if not self._verify_initiator_group_from_masking_view( conn, controllerConfigService, maskingViewName, - connector, storageSystemName, igGroupName): + connector, storageSystemName, igGroupName, + extraSpecs): # This may be used in exception hence _ instead of _LE. msg = (_( "Unable to verify initiator group: %(igGroupName)s " @@ -440,7 +452,7 @@ class EMCVMAXMasking(object): def _check_masking_view( self, conn, controllerConfigService, maskingViewName, storageGroupInstanceName, - portGroupInstanceName, initiatorGroupInstanceName): + portGroupInstanceName, initiatorGroupInstanceName, extraSpecs): """Check that masking view can be either got or created. :param conn: the ecom connection @@ -449,6 +461,7 @@ class EMCVMAXMasking(object): :param storageGroupInstanceName: storage group instance name :param portGroupInstanceName: port group instance name :param initiatorGroupInstanceName: the initiator group instance name + :param extraSpecs: extra specifications :returns: maskingViewInstanceName :returns: string -- msg, the error message """ @@ -457,7 +470,7 @@ class EMCVMAXMasking(object): self._get_masking_view_instance_name( conn, controllerConfigService, maskingViewName, storageGroupInstanceName, portGroupInstanceName, - initiatorGroupInstanceName)) + initiatorGroupInstanceName, extraSpecs)) if maskingViewInstanceName is None: # This may be used in exception hence _ instead of _LE. msg = (_( @@ -771,7 +784,7 @@ class EMCVMAXMasking(object): def _create_or_get_initiator_group( self, conn, controllerConfigService, igGroupName, - connector, storageSystemName): + connector, storageSystemName, extraSpecs): """Attempt to create a initiatorGroup. If one already exists with the same Initiator/wwns then get it. @@ -786,6 +799,7 @@ class EMCVMAXMasking(object): :param igGroupName: the proposed name of the initiator group :param connector: the connector information to the host :param storageSystemName: the storage system name (String) + :param extraSpecs: extra specifications :returns: foundInitiatorGroupInstanceName """ initiatorNames = self._find_initiator_names(conn, connector) @@ -821,7 +835,7 @@ class EMCVMAXMasking(object): foundInitiatorGroupInstanceName = self._create_initiator_Group( conn, controllerConfigService, igGroupName, - storageHardwareIDInstanceNames) + storageHardwareIDInstanceNames, extraSpecs) LOG.info(_LI( "Created new initiator group name: %(igGroupName)s."), @@ -982,7 +996,7 @@ class EMCVMAXMasking(object): def _create_masking_view( self, conn, configService, maskingViewName, deviceMaskingGroup, - targetMaskingGroup, initiatorMaskingGroup): + targetMaskingGroup, initiatorMaskingGroup, extraSpecs): """After creating an new initiator group find it and return it. :param conn: the connection to the ecom server @@ -991,6 +1005,7 @@ class EMCVMAXMasking(object): :param deviceMaskingGroup: device(storage) masking group (instanceName) :param targetMaskingGroup: target(port) masking group (instanceName) :param initiatorMaskingGroup: initiator masking group (instanceName) + :param extraSpecs: extra specifications :returns: int -- return code :returns: dict -- job :raises: VolumeBackendAPIException @@ -1002,7 +1017,8 @@ class EMCVMAXMasking(object): TargetMaskingGroup=targetMaskingGroup) if rc != 0L: - rc, errordesc = self.utils.wait_for_job_complete(conn, job) + rc, errordesc = self.utils.wait_for_job_complete(conn, job, + extraSpecs) if rc != 0L: exceptionMessage = (_( "Error Create Masking View: %(groupName)s. " @@ -1148,7 +1164,7 @@ class EMCVMAXMasking(object): def _get_initiator_group_instance_name( self, conn, controllerConfigService, igGroupName, connector, - storageSystemName): + storageSystemName, extraSpecs): """Gets the initiator group instance name. :param conn: the connection to the ecom server @@ -1156,11 +1172,12 @@ class EMCVMAXMasking(object): :param igGroupName: the port group name :param connector: the connector object :param storageSystemName: the storage system name + :param extraSpecs: extra specifications :returns: foundInitiatorGroupInstanceName """ foundInitiatorGroupInstanceName = (self._create_or_get_initiator_group( conn, controllerConfigService, igGroupName, connector, - storageSystemName)) + storageSystemName, extraSpecs)) if foundInitiatorGroupInstanceName is None: LOG.error(_LE( "Cannot create or find an initiator group with " @@ -1171,7 +1188,7 @@ class EMCVMAXMasking(object): def _get_masking_view_instance_name( self, conn, controllerConfigService, maskingViewName, storageGroupInstanceName, portGroupInstanceName, - initiatorGroupInstanceName): + initiatorGroupInstanceName, extraSpecs): """Gets the masking view instance name. :param conn: the connection to the ecom server @@ -1180,13 +1197,14 @@ class EMCVMAXMasking(object): :param storageGroupInstanceName: the storage group instance name :param portGroupInstanceName: the port group instance name :param initiatorGroupInstanceName: the initiator group instance name + :param extraSpecs: extra specifications :returns: instance name foundMaskingViewInstanceName """ _rc, job = ( self._create_masking_view( conn, controllerConfigService, maskingViewName, storageGroupInstanceName, portGroupInstanceName, - initiatorGroupInstanceName)) + initiatorGroupInstanceName, extraSpecs)) foundMaskingViewInstanceName = self.find_new_masking_view(conn, job) if foundMaskingViewInstanceName is None: LOG.error(_LE( @@ -1333,7 +1351,7 @@ class EMCVMAXMasking(object): def _verify_initiator_group_from_masking_view( self, conn, controllerConfigService, maskingViewName, connector, - storageSystemName, igGroupName): + storageSystemName, igGroupName, extraSpecs): """Check that the initiator group contains the correct initiators. If using an existing masking view check that the initiator group @@ -1349,6 +1367,7 @@ class EMCVMAXMasking(object): :param connector: the connector dict :param storageSystemName: the storage System Name (string) :param igGroupName: the initiator group name (String) + :param extraSpecs: extra specifications :returns: boolean """ initiatorNames = self._find_initiator_names(conn, connector) @@ -1387,7 +1406,7 @@ class EMCVMAXMasking(object): foundInitiatorGroupFromConnector = ( self._create_initiator_Group( conn, controllerConfigService, igGroupName, - storageHardwareIDInstanceNames)) + storageHardwareIDInstanceNames, extraSpecs)) storageGroupInstanceName = ( self._get_storage_group_from_masking_view( conn, maskingViewName, storageSystemName)) @@ -1398,12 +1417,12 @@ class EMCVMAXMasking(object): portGroupInstanceName is not None): self._delete_masking_view( conn, controllerConfigService, maskingViewName, - maskingViewInstanceName) + maskingViewInstanceName, extraSpecs) newMaskingViewInstanceName = ( self._get_masking_view_instance_name( conn, controllerConfigService, maskingViewName, storageGroupInstanceName, portGroupInstanceName, - foundInitiatorGroupFromConnector)) + foundInitiatorGroupFromConnector, extraSpecs)) if newMaskingViewInstanceName is not None: LOG.debug( "The old masking view has been replaced: " @@ -1421,7 +1440,7 @@ class EMCVMAXMasking(object): def _create_initiator_Group( self, conn, controllerConfigService, igGroupName, - hardwareIdinstanceNames): + hardwareIdinstanceNames, extraSpecs): """Create a new initiator group. Given a list of hardwareId Instance name create a new @@ -1431,6 +1450,7 @@ class EMCVMAXMasking(object): :param controllerConfigService: the controller configuration service :param igGroupName: the initiator group name (String) :param hardwareIdinstanceNames: one or more hardware id instance names + :param extraSpecs: extra specifications :returns: foundInitiatorGroupInstanceName :raises: VolumeBackendAPIException """ @@ -1440,7 +1460,8 @@ class EMCVMAXMasking(object): Members=[hardwareIdinstanceNames[0]]) if rc != 0L: - rc, errordesc = self.utils.wait_for_job_complete(conn, job) + rc, errordesc = self.utils.wait_for_job_complete(conn, job, + extraSpecs) if rc != 0L: exceptionMessage = (_( "Error Create Group: %(groupName)s. " @@ -1463,7 +1484,9 @@ class EMCVMAXMasking(object): Members=[hardwareIdinstanceNames[j]]) if rc != 0L: - rc, errordesc = self.utils.wait_for_job_complete(conn, job) + rc, errordesc = ( + self.utils.wait_for_job_complete(conn, job, + extraSpecs)) if rc != 0L: exceptionMessage = (_( "Error adding initiator to group : %(groupName)s. " @@ -1507,13 +1530,14 @@ class EMCVMAXMasking(object): def _delete_masking_view( self, conn, controllerConfigService, maskingViewName, - maskingViewInstanceName): + maskingViewInstanceName, extraSpecs): """Delete a masking view. :param conn: connection the ecom server :param controllerConfigService: the controller configuration service :param maskingViewName: maskingview name (String) :param maskingViewInstanceName: the masking view instance name + :param extraSpecs: extra specifications :raises: VolumeBackendAPIException """ rc, job = conn.InvokeMethod('DeleteMaskingView', @@ -1521,7 +1545,8 @@ class EMCVMAXMasking(object): ProtocolController=maskingViewInstanceName) if rc != 0L: - rc, errordesc = self.utils.wait_for_job_complete(conn, job) + rc, errordesc = self.utils.wait_for_job_complete(conn, job, + extraSpecs) if rc != 0L: exceptionMessage = (_( "Error Modifying masking view : %(groupName)s. " @@ -1843,7 +1868,7 @@ class EMCVMAXMasking(object): self._last_volume_delete_masking_view( conn, controllerConfigService, mvInstanceName, - maskingViewName) + maskingViewName, extraSpecs) if not isV3: isTieringPolicySupported, tierPolicyServiceInstanceName = ( self._get_tiering_info(conn, storageSystemInstanceName, @@ -1920,7 +1945,7 @@ class EMCVMAXMasking(object): def _last_volume_delete_masking_view( self, conn, controllerConfigService, mvInstanceName, - maskingViewName): + maskingViewName, extraSpecs): """Delete the masking view. Delete the masking view if the volume is the last one in the @@ -1930,6 +1955,7 @@ class EMCVMAXMasking(object): :param controllerConfigService: controller config service :param mvInstanceName: masking view instance name :param maskingViewName: masking view name + :param extraSpecs: extra specifications """ LOG.debug( "Last volume in the storage group, deleting masking view " @@ -1937,7 +1963,7 @@ class EMCVMAXMasking(object): {'maskingViewName': maskingViewName}) self._delete_masking_view( conn, controllerConfigService, maskingViewName, - mvInstanceName) + mvInstanceName, extraSpecs) mvInstance = self.utils.get_existing_instance( conn, mvInstanceName) @@ -2240,7 +2266,7 @@ class EMCVMAXMasking(object): # Delete storage group. self._delete_storage_group(conn, controllerConfigService, storageGroupInstanceName, - storageGroupName) + storageGroupName, extraSpecs) storageGroupInstance = self.utils.get_existing_instance( conn, storageGroupInstanceName) if storageGroupInstance: @@ -2258,13 +2284,15 @@ class EMCVMAXMasking(object): {'storageGroupName': storageGroupName}) def _delete_storage_group(self, conn, controllerConfigService, - storageGroupInstanceName, storageGroupName): + storageGroupInstanceName, storageGroupName, + extraSpecs): """Delete empty storage group :param conn: the ecom connection :param controllerConfigService: controller config service :param storageGroupInstanceName: storage group instance name :param storageGroupName: storage group name + :param extraSpecs: extra specifications """ rc, job = conn.InvokeMethod( 'DeleteGroup', @@ -2273,7 +2301,8 @@ class EMCVMAXMasking(object): Force=True) if rc != 0L: - rc, errordesc = self.utils.wait_for_job_complete(conn, job) + rc, errordesc = self.utils.wait_for_job_complete(conn, job, + extraSpecs) if rc != 0L: exceptionMessage = (_( "Error Deleting Group: %(storageGroupName)s. " diff --git a/cinder/volume/drivers/emc/emc_vmax_utils.py b/cinder/volume/drivers/emc/emc_vmax_utils.py index e63638ac9..1e40fd7e0 100644 --- a/cinder/volume/drivers/emc/emc_vmax_utils.py +++ b/cinder/volume/drivers/emc/emc_vmax_utils.py @@ -386,11 +386,12 @@ class EMCVMAXUtils(object): else: return True - def wait_for_sync(self, conn, syncName): + def wait_for_sync(self, conn, syncName, extraSpecs=None): """Given the sync name wait for it to fully synchronize. :param conn: connection to the ecom server :param syncName: the syncName + :param extraSpecs: extra specifications :raises: loopingcall.LoopingCallDone :raises: VolumeBackendAPIException """ @@ -402,10 +403,11 @@ class EMCVMAXUtils(object): :raises: VolumeBackendAPIException """ retries = kwargs['retries'] + maxJobRetries = self._get_max_job_retries(extraSpecs) wait_for_sync_called = kwargs['wait_for_sync_called'] if self._is_sync_complete(conn, syncName): raise loopingcall.LoopingCallDone() - if retries > JOB_RETRIES: + if retries > maxJobRetries: LOG.error(_LE("_wait_for_sync failed after %(retries)d " "tries."), {'retries': retries}) @@ -423,8 +425,9 @@ class EMCVMAXUtils(object): kwargs = {'retries': 0, 'wait_for_sync_called': False} + intervalInSecs = self._get_interval_in_secs(extraSpecs) timer = loopingcall.FixedIntervalLoopingCall(_wait_for_sync) - timer.start(interval=INTERVAL_10_SEC).wait() + timer.start(interval=intervalInSecs).wait() def _is_sync_complete(self, conn, syncName): """Check if the job is finished. @@ -1419,12 +1422,14 @@ class EMCVMAXUtils(object): return six.text_type(datetime.timedelta(seconds=int(delta))) def find_sync_sv_by_target( - self, conn, storageSystem, target, waitforsync=True): + self, conn, storageSystem, target, extraSpecs, + waitforsync=True): """Find the storage synchronized name by target device ID. :param conn: connection to the ecom server :param storageSystem: the storage system name :param target: target volume object + :param extraSpecs: the extraSpecs dict :param waitforsync: wait for the synchronization to complete if True :returns: foundSyncInstanceName """ @@ -1455,17 +1460,19 @@ class EMCVMAXUtils(object): else: # Wait for SE_StorageSynchronized_SV_SV to be fully synced. if waitforsync: - self.wait_for_sync(conn, foundSyncInstanceName) + self.wait_for_sync(conn, foundSyncInstanceName, extraSpecs) return foundSyncInstanceName def find_group_sync_rg_by_target( - self, conn, storageSystem, targetRgInstanceName, waitforsync=True): + self, conn, storageSystem, targetRgInstanceName, extraSpecs, + waitforsync=True): """Find the SE_GroupSynchronized_RG_RG instance name by target group. :param conn: connection to the ecom server :param storageSystem: the storage system name :param targetRgInstanceName: target group instance name + :param extraSpecs: the extraSpecs dict :param waitforsync: wait for synchronization to complete :returns: foundSyncInstanceName """ @@ -1495,7 +1502,7 @@ class EMCVMAXUtils(object): else: # Wait for SE_StorageSynchronized_SV_SV to be fully synced. if waitforsync: - self.wait_for_sync(conn, foundSyncInstanceName) + self.wait_for_sync(conn, foundSyncInstanceName, extraSpecs) return foundSyncInstanceName -- 2.45.2