storage_system_v3 = 'SYMMETRIX-+-000197200056'
port_group = 'OS-portgroup-PG'
lunmaskctrl_id = (
- 'SYMMETRIX+000195900551+OS-fakehost-gold-MV')
- lunmaskctrl_name = 'OS-fakehost-gold-MV'
+ 'SYMMETRIX+000195900551+OS-fakehost-gold-I-MV')
+ lunmaskctrl_name = (
+ 'OS-fakehost-gold-I-MV')
initiatorgroup_id = (
'SYMMETRIX+000195900551+OS-fakehost-IG')
antecedent = SYMM_LunMasking()
antecedent['CreationClassName'] = self.data.lunmask_creationclass2
antecedent['SystemName'] = self.data.storage_system
+ antecedent['ElementName'] = mvname
classcimproperty = Fake_CIMProperty()
elementName = (
def _getinstance_ipprotocolendpoint(self, objectpath):
return self._enum_ipprotocolendpoint()[0]
+ def _getinstance_lunmaskingview(self, objectpath):
+ return self._enum_maskingView()[0]
+
def _default_getinstance(self, objectpath):
return objectpath
def _enum_maskingView(self):
maskingViews = []
- maskingView = {}
+ maskingView = SYMM_LunMasking()
maskingView['CreationClassName'] = 'Symm_LunMaskingView'
- maskingView['ElementName'] = 'myMaskingView'
+ maskingView['ElementName'] = self.data.lunmaskctrl_name
+
+ cimproperty = Fake_CIMProperty()
+ cimproperty.value = self.data.lunmaskctrl_name
+ properties = {u'ElementName': cimproperty}
+ maskingView.properties = properties
+
maskingViews.append(maskingView)
return maskingViews
issynched = self.driver.common.utils._is_sync_complete(conn, syncname)
self.assertFalse(issynched)
+ def test_get_correct_port_group(self):
+ self.driver.common.conn = self.fake_ecom_connection()
+ maskingViewInstanceName = {'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'OS-fakehost-gold-I-MV',
+ 'SystemName': 'SYMMETRIX+000195900551'}
+ deviceinfodict = {'controller': maskingViewInstanceName}
+ portgroupname = self.driver.common._get_correct_port_group(
+ deviceinfodict, self.data.storage_system)
+ self.assertEqual('OS-portgroup-PG', portgroupname)
+
def test_generate_unique_trunc_pool(self):
pool_under_16_chars = 'pool_under_16'
pool1 = self.driver.utils.generate_unique_trunc_pool(
self.assertEqual('10.10.10.10', foundIpAddresses[0])
def test_find_device_number(self):
- host = 'myhost'
+ host = 'fakehost'
data = (
self.driver.common.find_device_number(self.data.test_volume_v2,
host))
- self.assertEqual('OS-myhost-MV', data['maskingview'])
+ self.assertEqual('OS-fakehost-MV', data['maskingview'])
host = 'bogushost'
data = (
self.driver.common.find_device_number(self.data.test_volume_v2,
self.data.storage_system, self.data.connector))
# The controller has been found.
self.assertEqual(
- 'OS-fakehost-gold-MV',
+ 'OS-fakehost-gold-I-MV',
self.driver.common.conn.GetInstance(
foundControllerInstanceName)['ElementName'])
def test_already_mapped_no_fast_success(
self, _mock_volume_type, mock_wrap_group, mock_wrap_device,
mock_is_same_host):
+ self.driver.common._get_correct_port_group = mock.Mock(
+ return_value=self.data.port_group)
self.driver.initialize_connection(self.data.test_volume,
self.data.connector)
def test_map_new_masking_view_no_fast_success(
self, _mock_volume_type, mock_wrap_group,
mock_storage_group, mock_add_volume):
+ self.driver.common._wrap_find_device_number = mock.Mock(
+ return_value={})
self.driver.initialize_connection(self.data.test_volume,
self.data.connector)
def test_already_mapped_fast_success(
self, _mock_volume_type, mock_wrap_group, mock_wrap_device,
mock_is_same_host):
+ self.driver.common._get_correct_port_group = mock.Mock(
+ return_value=self.data.port_group)
self.driver.initialize_connection(self.data.test_volume,
self.data.connector)
common = self.driver.common
common.get_target_wwns_from_masking_view = mock.Mock(
return_value=EMCVMAXCommonData.target_wwns)
+ common._get_correct_port_group = mock.Mock(
+ return_value=self.data.port_group)
lookup_service = self.driver.zonemanager_lookup_service
lookup_service.get_device_mapping_from_network = mock.Mock(
return_value=EMCVMAXCommonData.device_map)
common = self.driver.common
common.get_target_wwns = mock.Mock(
return_value=EMCVMAXCommonData.target_wwns)
+ self.driver.common._get_correct_port_group = mock.Mock(
+ return_value=self.data.port_group)
data = self.driver.initialize_connection(
self.data.test_volume, self.data.connector)
# Test the no lookup service, pre-zoned case.
return_value=EMCVMAXCommonData.target_wwns)
self.driver.common._initial_setup = mock.Mock(
return_value=self.default_extraspec())
+ self.driver.common._get_correct_port_group = mock.Mock(
+ return_value=self.data.port_group)
data = self.driver.initialize_connection(
self.data.test_volume_v3, self.data.connector)
# Test the no lookup service, pre-zoned case.
{'volume': volumename})
device_info = self.find_device_number(volume, connector['host'])
- device_number = device_info['hostlunid']
- if device_number is None:
+ if 'hostlunid' not in device_info:
LOG.info(_LI("Volume %s is not mapped. No volume to unmap."),
volumename)
return
:returns: dict -- deviceInfoDict - device information dict
:raises: VolumeBackendAPIException
"""
+ portGroupName = None
extraSpecs = self._initial_setup(volume)
volumeName = volume['name']
LOG.info(_LI("Initialize connection: %(volume)s."),
{'volume': volumeName})
self.conn = self._get_ecom_connection()
- deviceInfoDict = self.find_device_number(volume, connector['host'])
+ deviceInfoDict = self._wrap_find_device_number(
+ volume, connector['host'])
maskingViewDict = self._populate_masking_dict(
volume, connector, extraSpecs)
"The device number is %(deviceNumber)s."),
{'volume': volumeName,
'deviceNumber': deviceNumber})
+ # Special case, we still need to get the iscsi ip address.
+ portGroupName = (
+ self._get_correct_port_group(
+ deviceInfoDict, maskingViewDict['storageSystemName']))
+
else:
- deviceInfoDict = self._attach_volume(
+ deviceInfoDict, portGroupName = self._attach_volume(
volume, connector, extraSpecs, maskingViewDict, True)
else:
- deviceInfoDict = self._attach_volume(
- volume, connector, extraSpecs, maskingViewDict)
+ deviceInfoDict, portGroupName = (
+ self._attach_volume(
+ volume, connector, extraSpecs, maskingViewDict))
if self.protocol.lower() == 'iscsi':
return self._find_ip_protocol_endpoints(
self.conn, deviceInfoDict['storagesystem'],
- maskingViewDict['pgGroupName'])
+ portGroupName)
else:
return deviceInfoDict
:param maskingViewDict: masking view information
:param isLiveMigration: boolean, can be None
:returns: dict -- deviceInfoDict
+ String -- port group name
:raises: VolumeBackendAPIException
"""
volumeName = volume['name']
raise exception.VolumeBackendAPIException(
data=exception_message)
- return deviceInfoDict
+ return deviceInfoDict, rollbackDict['pgGroupName']
def _is_same_host(self, connector, deviceInfoDict):
"""Check if the host is the same.
return True
return False
+ def _get_correct_port_group(self, deviceInfoDict, storageSystemName):
+ """Get the portgroup name from the existing masking view.
+
+ :params deviceInfoDict: the device info dictionary
+ :params storageSystemName: storage system name
+ :returns: String port group name
+ """
+ if ('controller' in deviceInfoDict and
+ deviceInfoDict['controller'] is not None):
+ maskingViewInstanceName = deviceInfoDict['controller']
+ try:
+ maskingViewInstance = (
+ self.conn.GetInstance(maskingViewInstanceName))
+ except Exception:
+ exception_message = (_("Unable to get the name of "
+ "the masking view."))
+ raise exception.VolumeBackendAPIException(
+ data=exception_message)
+
+ # Get the portgroup from masking view
+ portGroupInstanceName = (
+ self.masking._get_port_group_from_masking_view(
+ self.conn,
+ maskingViewInstance['ElementName'],
+ storageSystemName))
+ try:
+ portGroupInstance = (
+ self.conn.GetInstance(portGroupInstanceName))
+ portGroupName = (
+ portGroupInstance['ElementName'])
+ except Exception:
+ exception_message = (_("Unable to get the name of "
+ "the portgroup."))
+ raise exception.VolumeBackendAPIException(
+ data=exception_message)
+ else:
+ exception_message = (_("Cannot get the portgroup from "
+ "the masking view."))
+ raise exception.VolumeBackendAPIException(
+ data=exception_message)
+ return portGroupName
+
def terminate_connection(self, volume, connector):
"""Disallow connection from connector.
'initiator': foundinitiatornames})
return foundinitiatornames
+ def _wrap_find_device_number(self, volume, host):
+ return self.find_device_number(volume, host)
+
def find_device_number(self, volume, host):
"""Given the volume dict find a device number.
"""
maskedvols = []
data = {}
+ foundController = None
foundNumDeviceNumber = None
foundMaskingViewName = None
volumeName = volume['name']
if index > -1:
unitinstance = self.conn.GetInstance(unitname,
LocalOnly=False)
- numDeviceNumber = int(unitinstance['DeviceNumber'],
- 16)
+ numDeviceNumber = int(unitinstance['DeviceNumber'], 16)
foundNumDeviceNumber = numDeviceNumber
+ foundController = controller
controllerInstance = self.conn.GetInstance(controller,
LocalOnly=False)
propertiesList = controllerInstance.properties.items()
devicedict = {'hostlunid': foundNumDeviceNumber,
'storagesystem': storageSystemName,
- 'maskingview': foundMaskingViewName}
+ 'maskingview': foundMaskingViewName,
+ 'controller': foundController}
maskedvols.append(devicedict)
if not maskedvols:
def _find_ip_protocol_endpoints(self, conn, storageSystemName,
portgroupname):
- """Find the IP protocol endpoint for ISCSI
+ """Find the IP protocol endpoint for ISCSI.
:param storageSystemName: the system name
:param portgroupname: the portgroup name
:returns: foundIpAddresses
"""
+ LOG.debug("The portgroup name for iscsiadm is %(pg)s",
+ {'pg': portgroupname})
foundipaddresses = []
configservice = (
self.utils.find_controller_configuration_service(
for VMAX3 (bug #1520549)
- necessary updates for CG changes (#1534616)
- Changing PercentSynced to CopyState (bug #1517103)
+ - Getting iscsi ip from port in existing masking view
"""
VERSION = "2.3.0"
for VMAX3 (bug #1520549)
- necessary updates for CG changes (#1534616)
- Changing PercentSynced to CopyState (bug #1517103)
+ - Getting iscsi ip from port in existing masking view
"""
VERSION = "2.3.0"
defaultStorageGroupInstanceName = None
fastPolicyName = None
assocStorageGroupName = None
+ storageGroupInstanceName = None
if isLiveMigration is False:
if isV3:
defaultStorageGroupInstanceName = (
{'maskingViewName': maskingViewDict['maskingViewName']})
errorMessage = e
+ rollbackDict['pgGroupName'], errorMessage = (
+ self._get_port_group_name_from_mv(
+ conn, maskingViewDict['maskingViewName'],
+ maskingViewDict['storageSystemName']))
+
if not errorMessage:
# Only after the masking view has been validated, add the
# volume to the storage group and recheck that it has been
foundHardwareIDsInstanceNames.append(hardwareIdInstanceName)
return foundHardwareIDsInstanceNames
+
+ def _get_port_group_name_from_mv(self, conn, maskingViewName,
+ storageSystemName):
+ """Get the port group name from the masking view.
+
+ :param conn: the connection to the ecom server
+ :param maskingViewName: the masking view name
+ :param storageSystemName: the storage system name
+ :returns: String - port group name
+ String - error message
+ """
+ errorMessage = None
+ portGroupName = None
+ portGroupInstanceName = (
+ self._get_port_group_from_masking_view(
+ conn, maskingViewName, storageSystemName))
+ if portGroupInstanceName is None:
+ LOG.error(_LE(
+ "Cannot get port group from masking view: "
+ "%(maskingViewName)s. "),
+ {'maskingViewName': maskingViewName})
+ else:
+ try:
+ portGroupInstance = (
+ conn.GetInstance(portGroupInstanceName))
+ portGroupName = (
+ portGroupInstance['ElementName'])
+ except Exception:
+ LOG.error(_LE(
+ "Cannot get port group name."))
+ return portGroupName, errorMessage