Merge "EMC VMAX - locking SG for concurrent threads"
This commit is contained in:
commit
a0a96a8e55
|
@ -241,6 +241,10 @@ class EMCVMAXCommonData(object):
|
|||
default_storage_group = (
|
||||
u'//10.10.10.10/root/emc: SE_DeviceMaskingGroup.InstanceID='
|
||||
'"SYMMETRIX+000198700440+OS_default_GOLD1_SG"')
|
||||
default_sg_instance_name = {
|
||||
'CreationClassName': 'CIM_DeviceMaskingGroup',
|
||||
'ElementName': 'OS_default_GOLD1_SG',
|
||||
'SystemName': 'SYMMETRIX+000195900551'}
|
||||
storage_system = 'SYMMETRIX+000195900551'
|
||||
storage_system_v3 = 'SYMMETRIX-+-000197200056'
|
||||
port_group = 'OS-portgroup-PG'
|
||||
|
@ -3139,7 +3143,7 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
|
|||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'find_storage_masking_group',
|
||||
return_value='value')
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
emc_vmax_masking.EMCVMAXMasking,
|
||||
'_wrap_get_storage_group_from_volume',
|
||||
|
@ -3167,7 +3171,7 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
|
|||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'find_storage_masking_group',
|
||||
return_value='value')
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
emc_vmax_common.EMCVMAXCommon,
|
||||
'find_device_number',
|
||||
|
@ -3242,7 +3246,7 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
|
|||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'find_storage_masking_group',
|
||||
return_value=EMCVMAXCommonData.storagegroupname)
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
volume_types,
|
||||
'get_volume_type_extra_specs',
|
||||
|
@ -4141,7 +4145,7 @@ class EMCVMAXISCSIDriverFastTestCase(test.TestCase):
|
|||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'find_storage_masking_group',
|
||||
return_value=EMCVMAXCommonData.storagegroupname)
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
volume_types,
|
||||
'get_volume_type_extra_specs',
|
||||
|
@ -5920,6 +5924,8 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
self.data.test_volume_v3['host'] = self.data.fake_host_v3
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
self.driver.create_volume(self.data.test_volume_v3)
|
||||
|
||||
@mock.patch.object(
|
||||
|
@ -5949,6 +5955,8 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
'portgroupname': 'OS-portgroup-PG'}
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
return_value=extraSpecs)
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
|
||||
self.driver.create_volume(v3_vol)
|
||||
|
||||
|
@ -5988,6 +5996,8 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
self, _mock_volume_type, mock_storage_system):
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
self.driver.create_volume(self.data.test_volume_CG_v3)
|
||||
|
||||
@mock.patch.object(
|
||||
|
@ -6014,7 +6024,10 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
def test_create_snapshot_v3_success(
|
||||
self, mock_volume_db, mock_type, moke_pool):
|
||||
self.data.test_volume_v3['volume_name'] = "vmax-1234567"
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
common = self.driver.common
|
||||
common.provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock(
|
||||
return_value=(None, None, self.data.default_sg_instance_name))
|
||||
common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
self.driver.create_snapshot(self.data.test_volume_v3)
|
||||
|
||||
|
@ -6059,8 +6072,13 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
cloneVol['NumberOfBlocks'] = 100
|
||||
cloneVol['BlockSize'] = self.data.block_size
|
||||
cloneVol['host'] = self.data.fake_host_v3
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
common = self.driver.common
|
||||
common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
common.provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock(
|
||||
return_value=(None, None, self.data.default_sg_instance_name))
|
||||
self.driver.create_cloned_volume(cloneVol, self.data.test_volume_v3)
|
||||
|
||||
@mock.patch.object(
|
||||
|
@ -6124,7 +6142,7 @@ class EMCV3DriverTestCase(test.TestCase):
|
|||
@mock.patch.object(
|
||||
emc_vmax_provision_v3.EMCVMAXProvisionV3,
|
||||
'_find_new_storage_group',
|
||||
return_value='Any')
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'wrap_get_storage_group_from_volume',
|
||||
|
@ -6954,6 +6972,8 @@ class EMCV3MultiSloDriverTestCase(test.TestCase):
|
|||
self.vol_v3['provider_location'] = None
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
self.driver.create_volume(self.vol_v3)
|
||||
|
||||
@mock.patch.object(
|
||||
|
@ -6983,12 +7003,14 @@ class EMCV3MultiSloDriverTestCase(test.TestCase):
|
|||
self.data.test_volume_CG_v3['provider_location'] = None
|
||||
self.driver.common._initial_setup = mock.Mock(
|
||||
return_value=self.default_extraspec())
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
self.driver.create_volume(self.data.test_volume_CG_v3)
|
||||
|
||||
@mock.patch.object(
|
||||
emc_vmax_provision_v3.EMCVMAXProvisionV3,
|
||||
'_find_new_storage_group',
|
||||
return_value='Any')
|
||||
return_value=EMCVMAXCommonData.default_sg_instance_name)
|
||||
@mock.patch.object(
|
||||
emc_vmax_utils.EMCVMAXUtils,
|
||||
'wrap_get_storage_group_from_volume',
|
||||
|
@ -7468,6 +7490,65 @@ class EMCVMAXProvisionV3Test(test.TestCase):
|
|||
theVolumeInstanceName, inVolumeInstanceName, volumeSize,
|
||||
extraSpecs)
|
||||
|
||||
def test_create_volume_from_sg(self):
|
||||
provisionv3 = self.driver.common.provisionv3
|
||||
conn = FakeEcomConnection()
|
||||
storageConfigService = {
|
||||
'CreationClassName': 'EMC_StorageConfigurationService',
|
||||
'SystemName': 'SYMMETRIX+000195900551'}
|
||||
extraSpecs = {'volume_backend_name': 'GOLD_BE',
|
||||
'isV3': True}
|
||||
volumeName = 'v3_vol'
|
||||
volumeSize = 3
|
||||
volumeDict, rc = (
|
||||
provisionv3.create_volume_from_sg(
|
||||
conn, storageConfigService, volumeName,
|
||||
self.data.default_sg_instance_name, volumeSize, extraSpecs))
|
||||
keybindings = volumeDict['keybindings']
|
||||
self.assertEqual('1', keybindings['DeviceID'])
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_create_storage_group_v3(self):
|
||||
provisionv3 = self.driver.common.provisionv3
|
||||
conn = FakeEcomConnection()
|
||||
controllerConfigService = {
|
||||
'CreationClassName': 'EMC_ControllerConfigurationService',
|
||||
'SystemName': 'SYMMETRIX+000195900551'}
|
||||
extraSpecs = {'volume_backend_name': 'GOLD_BE',
|
||||
'isV3': True}
|
||||
groupName = self.data.storagegroupname
|
||||
srp = 'SRP_1'
|
||||
slo = 'Bronze'
|
||||
workload = 'DSS'
|
||||
provisionv3._find_new_storage_group = mock.Mock(
|
||||
return_value=self.data.default_sg_instance_name)
|
||||
newstoragegroup = provisionv3.create_storage_group_v3(
|
||||
conn, controllerConfigService, groupName, srp, slo, workload,
|
||||
extraSpecs)
|
||||
self.assertEqual(self.data.default_sg_instance_name, newstoragegroup)
|
||||
|
||||
def test_create_element_replica(self):
|
||||
provisionv3 = self.driver.common.provisionv3
|
||||
conn = FakeEcomConnection()
|
||||
repServiceInstanceName = {
|
||||
'CreationClassName': 'repServiceInstanceName',
|
||||
'SystemName': 'SYMMETRIX+000195900551'}
|
||||
extraSpecs = {'volume_backend_name': 'GOLD_BE',
|
||||
'isV3': True,
|
||||
'storagetype:pool': 'SRP_1',
|
||||
'storagetype:slo': 'SRP_1',
|
||||
'storagetype:workload': 'SRP_1'}
|
||||
sourceInstance = (
|
||||
conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
|
||||
syncType = 7
|
||||
cloneName = 'new_ss'
|
||||
provisionv3.utils.get_v3_default_sg_instance_name = mock.Mock(
|
||||
return_value=(None, None, self.data.default_sg_instance_name))
|
||||
rc, job = provisionv3.create_element_replica(
|
||||
conn, repServiceInstanceName, cloneName, syncType, sourceInstance,
|
||||
extraSpecs)
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class EMCVMAXMaskingTest(test.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -7838,6 +7919,8 @@ class EMCVMAXCommonTest(test.TestCase):
|
|||
targetInstance = common.conn.GetInstance(volumeInstanceName)
|
||||
common.utils.find_volume_instance = mock.Mock(
|
||||
return_value=targetInstance)
|
||||
self.driver.common._get_or_create_storage_group_v3 = mock.Mock(
|
||||
return_value = self.data.default_sg_instance_name)
|
||||
duplicateVolumeInstance = self.driver.common._create_duplicate_volume(
|
||||
sourceInstance, cloneName, extraSpecs)
|
||||
self.assertIsNotNone(duplicateVolumeInstance)
|
||||
|
@ -7861,3 +7944,76 @@ class EMCVMAXCommonTest(test.TestCase):
|
|||
|
||||
self.driver.common._cleanup_target(
|
||||
repServiceInstanceName, targetInstance, extraSpecs)
|
||||
|
||||
|
||||
class EMCVMAXProvisionTest(test.TestCase):
|
||||
def setUp(self):
|
||||
self.data = EMCVMAXCommonData()
|
||||
|
||||
super(EMCVMAXProvisionTest, self).setUp()
|
||||
|
||||
configuration = mock.Mock()
|
||||
configuration.safe_get.return_value = 'ProvisionTests'
|
||||
configuration.config_group = 'ProvisionTests'
|
||||
emc_vmax_common.EMCVMAXCommon._gather_info = mock.Mock()
|
||||
driver = emc_vmax_iscsi.EMCVMAXISCSIDriver(
|
||||
configuration=configuration)
|
||||
driver.db = FakeDB()
|
||||
self.driver = driver
|
||||
self.driver.utils = emc_vmax_utils.EMCVMAXUtils(object)
|
||||
|
||||
def test_remove_device_from_storage_group(self):
|
||||
conn = FakeEcomConnection()
|
||||
controllerConfigService = (
|
||||
self.driver.utils.find_controller_configuration_service(
|
||||
conn, self.data.storage_system))
|
||||
volumeInstanceName = (
|
||||
conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
|
||||
volumeName = 'vol1'
|
||||
extraSpecs = {'volume_backend_name': 'V3_BE',
|
||||
'isV3': True,
|
||||
'storagetype:pool': 'SRP_1',
|
||||
'storagetype:workload': 'DSS',
|
||||
'storagetype:slo': 'Bronze'}
|
||||
masking = self.driver.common.masking
|
||||
masking.provision.remove_device_from_storage_group = mock.Mock()
|
||||
masking = self.driver.common.masking
|
||||
volumeInstance = conn.GetInstance(volumeInstanceName)
|
||||
storageGroupName = self.data.storagegroupname
|
||||
storageGroupInstanceName = (
|
||||
self.driver.common.utils.find_storage_masking_group(
|
||||
conn, controllerConfigService, storageGroupName))
|
||||
numVolsInSG = 2
|
||||
masking._multiple_vols_in_SG(
|
||||
conn, controllerConfigService, storageGroupInstanceName,
|
||||
volumeInstance, volumeName, numVolsInSG, extraSpecs)
|
||||
masking.provision.remove_device_from_storage_group.assert_called_with(
|
||||
conn, controllerConfigService, storageGroupInstanceName,
|
||||
volumeInstanceName, volumeName, extraSpecs)
|
||||
|
||||
def test_add_members_to_masking_group(self):
|
||||
conn = FakeEcomConnection()
|
||||
controllerConfigService = (
|
||||
self.driver.utils.find_controller_configuration_service(
|
||||
conn, self.data.storage_system))
|
||||
volumeInstanceName = (
|
||||
conn.EnumerateInstanceNames("EMC_StorageVolume")[0])
|
||||
volumeName = 'vol1'
|
||||
extraSpecs = {'volume_backend_name': 'V3_BE',
|
||||
'isV3': True,
|
||||
'storagetype:pool': 'SRP_1',
|
||||
'storagetype:workload': 'DSS',
|
||||
'storagetype:slo': 'Bronze'}
|
||||
volumeInstance = conn.GetInstance(volumeInstanceName)
|
||||
storageGroupName = self.data.storagegroupname
|
||||
storageGroupInstanceName = (
|
||||
self.driver.common.utils.find_storage_masking_group(
|
||||
conn, controllerConfigService, storageGroupName))
|
||||
masking = self.driver.common.masking
|
||||
masking.provision.add_members_to_masking_group = mock.Mock()
|
||||
masking.add_volume_to_storage_group(
|
||||
conn, controllerConfigService, storageGroupInstanceName,
|
||||
volumeInstance, volumeName, storageGroupName, extraSpecs)
|
||||
masking.provision.add_members_to_masking_group.assert_called_with(
|
||||
conn, controllerConfigService, storageGroupInstanceName,
|
||||
volumeInstanceName, volumeName, extraSpecs)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
import time
|
||||
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
|
@ -159,33 +160,38 @@ class EMCVMAXProvision(object):
|
|||
"""
|
||||
startTime = time.time()
|
||||
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateGroup', controllerConfigService, GroupName=storageGroupName,
|
||||
Type=self.utils.get_num(STORAGEGROUPTYPE, '16'),
|
||||
Members=[volumeInstanceName])
|
||||
@lockutils.synchronized(storageGroupName,
|
||||
"emc-sg-", True)
|
||||
def do_create_storage_group():
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateGroup', controllerConfigService,
|
||||
GroupName=storageGroupName,
|
||||
Type=self.utils.get_num(STORAGEGROUPTYPE, '16'),
|
||||
Members=[volumeInstanceName])
|
||||
|
||||
if rc != 0:
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Group: %(groupName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'groupName': storageGroupName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Group: %(groupName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'groupName': storageGroupName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
LOG.debug("InvokeMethod CreateGroup "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
foundStorageGroupInstanceName = self._find_new_storage_group(
|
||||
conn, job, storageGroupName)
|
||||
LOG.debug("InvokeMethod CreateGroup "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
foundStorageGroupInstanceName = self._find_new_storage_group(
|
||||
conn, job, storageGroupName)
|
||||
|
||||
return foundStorageGroupInstanceName
|
||||
return foundStorageGroupInstanceName
|
||||
return do_create_storage_group()
|
||||
|
||||
def create_storage_group_no_members(
|
||||
self, conn, controllerConfigService, groupName, extraSpecs):
|
||||
|
@ -267,42 +273,57 @@ class EMCVMAXProvision(object):
|
|||
return volumeDict
|
||||
|
||||
def remove_device_from_storage_group(
|
||||
self, conn, controllerConfigService, storageGroupInstanceName,
|
||||
self, conn, controllerConfigService, sgInstanceName,
|
||||
volumeInstanceName, volumeName, extraSpecs):
|
||||
"""Remove a volume from a storage group.
|
||||
|
||||
:param conn: the connection to the ecom server
|
||||
:param controllerConfigService: the controller configuration service
|
||||
:param storageGroupInstanceName: the instance name of the storage group
|
||||
:param sgInstanceName: the instance name of the storage group
|
||||
:param volumeInstanceName: the instance name of the volume
|
||||
:param volumeName: the volume name (String)
|
||||
:param extraSpecs: additional info
|
||||
:returns: int -- the return code of the job
|
||||
:raises: VolumeBackendAPIException
|
||||
"""
|
||||
startTime = time.time()
|
||||
|
||||
rc, jobDict = conn.InvokeMethod('RemoveMembers',
|
||||
controllerConfigService,
|
||||
MaskingGroup=storageGroupInstanceName,
|
||||
Members=[volumeInstanceName])
|
||||
if rc != 0:
|
||||
rc, errorDesc = self.utils.wait_for_job_complete(conn, jobDict,
|
||||
extraSpecs)
|
||||
try:
|
||||
storageGroupInstance = conn.GetInstance(sgInstanceName)
|
||||
except Exception:
|
||||
exceptionMessage = (_(
|
||||
"Unable to get the name of the storage group."))
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
@lockutils.synchronized(storageGroupInstance['ElementName'],
|
||||
"emc-sg-", True)
|
||||
def do_remove_volume_from_sg():
|
||||
startTime = time.time()
|
||||
rc, jobDict = conn.InvokeMethod('RemoveMembers',
|
||||
controllerConfigService,
|
||||
MaskingGroup=sgInstanceName,
|
||||
Members=[volumeInstanceName])
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error removing volume %(vol)s. %(error)s.")
|
||||
% {'vol': volumeName, 'error': errorDesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
rc, errorDesc = self.utils.wait_for_job_complete(conn, jobDict,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error removing volume %(vol)s from %(sg). %(error)s.")
|
||||
% {'vol': volumeName,
|
||||
'sg': storageGroupInstance['ElementName'],
|
||||
'error': errorDesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
LOG.debug("InvokeMethod RemoveMembers "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
LOG.debug("InvokeMethod RemoveMembers "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
|
||||
return rc
|
||||
return rc
|
||||
return do_remove_volume_from_sg()
|
||||
|
||||
def add_members_to_masking_group(
|
||||
self, conn, controllerConfigService, storageGroupInstanceName,
|
||||
|
@ -317,28 +338,43 @@ class EMCVMAXProvision(object):
|
|||
:param extraSpecs: additional info
|
||||
:raises: VolumeBackendAPIException
|
||||
"""
|
||||
startTime = time.time()
|
||||
try:
|
||||
storageGroupInstance = conn.GetInstance(storageGroupInstanceName)
|
||||
except Exception:
|
||||
exceptionMessage = (_(
|
||||
"Unable to get the name of the storage group."))
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
rc, job = conn.InvokeMethod(
|
||||
'AddMembers', controllerConfigService,
|
||||
MaskingGroup=storageGroupInstanceName,
|
||||
Members=[volumeInstanceName])
|
||||
@lockutils.synchronized(storageGroupInstance['ElementName'],
|
||||
"emc-sg-", True)
|
||||
def do_add_volume_to_sg():
|
||||
startTime = time.time()
|
||||
rc, job = conn.InvokeMethod(
|
||||
'AddMembers', controllerConfigService,
|
||||
MaskingGroup=storageGroupInstanceName,
|
||||
Members=[volumeInstanceName])
|
||||
|
||||
if rc != 0:
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error mapping volume %(vol)s. %(error)s.")
|
||||
% {'vol': volumeName, 'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error adding volume %(vol)s to %(sg). %(error)s.")
|
||||
% {'vol': volumeName,
|
||||
'sg': storageGroupInstance['ElementName'],
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
LOG.debug("InvokeMethod AddMembers "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
LOG.debug("InvokeMethod AddMembers "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
return rc
|
||||
return do_add_volume_to_sg()
|
||||
|
||||
def unbind_volume_from_storage_pool(
|
||||
self, conn, storageConfigService,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import time
|
||||
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
|
@ -111,41 +112,55 @@ class EMCVMAXProvisionV3(object):
|
|||
:returns: int -- return code
|
||||
:raises: VolumeBackendAPIException
|
||||
"""
|
||||
startTime = time.time()
|
||||
try:
|
||||
storageGroupInstance = conn.GetInstance(sgInstanceName)
|
||||
except Exception:
|
||||
exceptionMessage = (_(
|
||||
"Unable to get the name of the storage group"))
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateOrModifyElementFromStoragePool',
|
||||
storageConfigService, ElementName=volumeName,
|
||||
EMCCollections=[sgInstanceName],
|
||||
ElementType=self.utils.get_num(THINPROVISIONING, '16'),
|
||||
Size=self.utils.get_num(volumeSize, '64'))
|
||||
@lockutils.synchronized(storageGroupInstance['ElementName'],
|
||||
"emc-sg-", True)
|
||||
def do_create_volume_from_sg():
|
||||
startTime = time.time()
|
||||
|
||||
LOG.debug("Create Volume: %(volumename)s. Return code: %(rc)lu.",
|
||||
{'volumename': volumeName,
|
||||
'rc': rc})
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateOrModifyElementFromStoragePool',
|
||||
storageConfigService, ElementName=volumeName,
|
||||
EMCCollections=[sgInstanceName],
|
||||
ElementType=self.utils.get_num(THINPROVISIONING, '16'),
|
||||
Size=self.utils.get_num(volumeSize, '64'))
|
||||
|
||||
LOG.debug("Create Volume: %(volumename)s. Return code: %(rc)lu.",
|
||||
{'volumename': volumeName,
|
||||
'rc': rc})
|
||||
|
||||
if rc != 0:
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Volume: %(volumeName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'volumeName': volumeName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Volume: %(volumeName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'volumeName': volumeName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
LOG.debug("InvokeMethod CreateOrModifyElementFromStoragePool "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
LOG.debug("InvokeMethod CreateOrModifyElementFromStoragePool "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
|
||||
# Find the newly created volume.
|
||||
volumeDict = self.get_volume_dict_from_job(conn, job['Job'])
|
||||
return volumeDict, rc
|
||||
# Find the newly created volume.
|
||||
volumeDict = self.get_volume_dict_from_job(conn, job['Job'])
|
||||
return volumeDict, rc
|
||||
|
||||
return do_create_volume_from_sg()
|
||||
|
||||
def _find_new_storage_group(
|
||||
self, conn, maskingGroupDict, storageGroupName):
|
||||
|
@ -246,38 +261,51 @@ class EMCVMAXProvisionV3(object):
|
|||
conn, extraSpecs[self.utils.POOL],
|
||||
extraSpecs[self.utils.SLO],
|
||||
extraSpecs[self.utils.WORKLOAD], storageSystemName))
|
||||
if targetInstance is None and rsdInstance is None:
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateElementReplica', repServiceInstanceName,
|
||||
ElementName=cloneName,
|
||||
SyncType=self.utils.get_num(syncType, '16'),
|
||||
SourceElement=sourceInstance.path,
|
||||
Collections=[sgInstanceName])
|
||||
else:
|
||||
rc, job = self._create_element_replica_extra_params(
|
||||
conn, repServiceInstanceName, cloneName, syncType,
|
||||
sourceInstance, targetInstance, rsdInstance,
|
||||
sgInstanceName)
|
||||
try:
|
||||
storageGroupInstance = conn.GetInstance(sgInstanceName)
|
||||
except Exception:
|
||||
exceptionMessage = (_(
|
||||
"Unable to get the name of the storage group"))
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
@lockutils.synchronized(storageGroupInstance['ElementName'],
|
||||
"emc-sg-", True)
|
||||
def do_create_element_replica():
|
||||
if targetInstance is None and rsdInstance is None:
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateElementReplica', repServiceInstanceName,
|
||||
ElementName=cloneName,
|
||||
SyncType=self.utils.get_num(syncType, '16'),
|
||||
SourceElement=sourceInstance.path,
|
||||
Collections=[sgInstanceName])
|
||||
else:
|
||||
rc, job = self._create_element_replica_extra_params(
|
||||
conn, repServiceInstanceName, cloneName, syncType,
|
||||
sourceInstance, targetInstance, rsdInstance,
|
||||
sgInstanceName)
|
||||
|
||||
if rc != 0:
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Cloned Volume: %(cloneName)s "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'cloneName': cloneName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
rc, errordesc = self.utils.wait_for_job_complete(conn, job,
|
||||
extraSpecs)
|
||||
if rc != 0:
|
||||
exceptionMessage = (_(
|
||||
"Error Create Cloned Volume: %(cloneName)s "
|
||||
"Return code: %(rc)lu. Error: %(error)s.")
|
||||
% {'cloneName': cloneName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
LOG.error(exceptionMessage)
|
||||
raise exception.VolumeBackendAPIException(
|
||||
data=exceptionMessage)
|
||||
|
||||
LOG.debug("InvokeMethod CreateElementReplica "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
return rc, job
|
||||
LOG.debug("InvokeMethod CreateElementReplica "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
return rc, job
|
||||
return do_create_element_replica()
|
||||
|
||||
def _create_element_replica_extra_params(
|
||||
self, conn, repServiceInstanceName, cloneName, syncType,
|
||||
|
@ -363,36 +391,46 @@ class EMCVMAXProvisionV3(object):
|
|||
"""
|
||||
startTime = time.time()
|
||||
|
||||
rc, job = conn.InvokeMethod(
|
||||
'CreateGroup',
|
||||
controllerConfigService,
|
||||
GroupName=groupName,
|
||||
Type=self.utils.get_num(4, '16'),
|
||||
EMCSRP=srp,
|
||||
EMCSLO=slo,
|
||||
EMCWorkload=workload)
|
||||
@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)
|
||||
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)
|
||||
if rc != 0:
|
||||
LOG.error(_LE(
|
||||
"Error Create Group: %(groupName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s."),
|
||||
{'groupName': groupName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
raise
|
||||
rc, errordesc = self.utils.wait_for_job_complete(
|
||||
conn, job, extraSpecs)
|
||||
if rc != 0:
|
||||
LOG.error(_LE(
|
||||
"Error Create Group: %(groupName)s. "
|
||||
"Return code: %(rc)lu. Error: %(error)s."),
|
||||
{'groupName': groupName,
|
||||
'rc': rc,
|
||||
'error': errordesc})
|
||||
raise
|
||||
|
||||
LOG.debug("InvokeMethod CreateGroup "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
LOG.debug("InvokeMethod CreateGroup "
|
||||
"took: %(delta)s H:MM:SS.",
|
||||
{'delta': self.utils.get_time_delta(startTime,
|
||||
time.time())})
|
||||
|
||||
foundStorageGroupInstanceName = self._find_new_storage_group(
|
||||
conn, job, groupName)
|
||||
foundStorageGroupInstanceName = self._find_new_storage_group(
|
||||
conn, job, groupName)
|
||||
|
||||
return foundStorageGroupInstanceName
|
||||
return foundStorageGroupInstanceName
|
||||
return do_create_storage_group_v3()
|
||||
|
||||
def get_storage_pool_capability(self, conn, poolInstanceName):
|
||||
"""Get the pool capability.
|
||||
|
|
Loading…
Reference in New Issue