]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Fix issues with extra specs in VMAX driver
authorXing Yang <xing.yang@emc.com>
Thu, 2 Apr 2015 05:03:08 +0000 (01:03 -0400)
committerXing Yang <xing.yang@emc.com>
Tue, 26 May 2015 03:34:07 +0000 (23:34 -0400)
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
cinder/volume/drivers/emc/emc_vmax_common.py
cinder/volume/drivers/emc/emc_vmax_masking.py
cinder/volume/drivers/emc/emc_vmax_utils.py

index f141a010c80424cdb58d95c9eb89108cdfc0e35f..bbf097d85bc5fcf10d85b0fc702efec9ae9a981f 100644 (file)
@@ -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):
index aadf3184b6b2b12b4803415170cc5f0ed9202bd3..223de5bda4eec7532cfda71ea790e18cee7ec578 100644 (file)
@@ -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.
index 2d0d2b07d4459e906d7a4dfd9066781d704dab7b..2a0d0a36890b30332ba84cf0a43b03faa2794218 100644 (file)
@@ -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. "
index e63638ac9df187e683636d7d2f3c0dfe1fbdcfdf..1e40fd7e006c9759089f21a4b6c4195a8691dc6b 100644 (file)
@@ -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