maskingviewdict,
controllerConfigService, maskingviewdict['volumeName']))
self.assertIsNone(result)
+
+
+class EMCVMAXFCTest(test.TestCase):
+ def setUp(self):
+ self.data = EMCVMAXCommonData()
+
+ super(EMCVMAXFCTest, self).setUp()
+
+ configuration = mock.Mock()
+ configuration.safe_get.return_value = 'FCTests'
+ configuration.config_group = 'FCTests'
+ emc_vmax_common.EMCVMAXCommon._gather_info = mock.Mock()
+ driver = emc_vmax_fc.EMCVMAXFCDriver(configuration=configuration)
+ driver.db = FakeDB()
+ self.driver = driver
+
+ def test_terminate_connection(self):
+ common = self.driver.common
+ common.conn = FakeEcomConnection()
+ common._unmap_lun = mock.Mock()
+ common.get_masking_view_by_volume = mock.Mock(
+ return_value='testMV')
+ common.get_masking_views_by_port_group = mock.Mock(
+ return_value=[])
+ common.get_target_wwns = mock.Mock(
+ return_value=EMCVMAXCommonData.target_wwns)
+ data = self.driver.terminate_connection(self.data.test_volume_v3,
+ self.data.connector)
+ common.get_target_wwns.assert_called_once_with(
+ EMCVMAXCommonData.storage_system, EMCVMAXCommonData.connector)
+ numTargetWwns = len(EMCVMAXCommonData.target_wwns)
+ self.assertEqual(numTargetWwns, len(data['data']))
+
+ def test_get_common_masking_views_two_exist(self):
+ common = self.driver.common
+ common.conn = FakeEcomConnection()
+ maskingviews = [{'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV1'},
+ {'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV2'}]
+
+ portGroupInstanceName = (
+ self.driver.common.masking._get_port_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+
+ initiatorGroupInstanceName = (
+ self.driver.common.masking._get_initiator_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+ common.get_masking_views_by_port_group = mock.Mock(
+ return_value=maskingviews)
+ common.get_masking_views_by_initiator_group = mock.Mock(
+ return_value=maskingviews)
+
+ mvInstances = self.driver._get_common_masking_views(
+ portGroupInstanceName, initiatorGroupInstanceName)
+ self.assertTrue(len(mvInstances) == 2)
+
+ def test_get_common_masking_views_one_overlap(self):
+ common = self.driver.common
+ common.conn = FakeEcomConnection()
+ maskingviewsPG = [{'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV1'},
+ {'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV2'}]
+
+ maskingviewsIG = [{'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV1'}]
+
+ portGroupInstanceName = (
+ self.driver.common.masking._get_port_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+
+ initiatorGroupInstanceName = (
+ self.driver.common.masking._get_initiator_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+ common.get_masking_views_by_port_group = mock.Mock(
+ return_value=maskingviewsPG)
+ common.get_masking_views_by_initiator_group = mock.Mock(
+ return_value=maskingviewsIG)
+
+ mvInstances = self.driver._get_common_masking_views(
+ portGroupInstanceName, initiatorGroupInstanceName)
+ self.assertTrue(len(mvInstances) == 1)
+
+ def test_get_common_masking_views_no_overlap(self):
+ common = self.driver.common
+ common.conn = FakeEcomConnection()
+ maskingviewsPG = [{'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV2'}]
+
+ maskingviewsIG = [{'CreationClassName': 'Symm_LunMaskingView',
+ 'ElementName': 'MV1'}]
+
+ portGroupInstanceName = (
+ self.driver.common.masking._get_port_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+
+ initiatorGroupInstanceName = (
+ self.driver.common.masking._get_initiator_group_from_masking_view(
+ common.conn, self.data.lunmaskctrl_name,
+ self.data.storage_system))
+ common.get_masking_views_by_port_group = mock.Mock(
+ return_value=maskingviewsPG)
+ common.get_masking_views_by_initiator_group = mock.Mock(
+ return_value=maskingviewsIG)
+
+ mvInstances = self.driver._get_common_masking_views(
+ portGroupInstanceName, initiatorGroupInstanceName)
+ self.assertTrue(len(mvInstances) == 0)
return self.masking.get_port_group_from_masking_view(
self.conn, maskingViewInstanceName)
+ def get_initiator_group_from_masking_view(self, maskingViewInstanceName):
+ """Get the initiator group in a masking view.
+
+ :param maskingViewInstanceName: masking view instance name
+ :returns: initiatorGroupInstanceName
+ """
+ return self.masking.get_initiator_group_from_masking_view(
+ self.conn, maskingViewInstanceName)
+
def get_masking_view_by_volume(self, volume, connector):
"""Given volume, retrieve the masking view instance name.
return self.masking.get_masking_views_by_port_group(
self.conn, portGroupInstanceName)
+ def get_masking_views_by_initiator_group(
+ self, initiatorGroupInstanceName):
+ """Given initiator group, retrieve the masking view instance name.
+
+ :param initiatorGroupInstanceName: initiator group instance name
+ :returns: list -- maskingViewInstanceNames
+ """
+ LOG.debug("Finding Masking Views for initiator group %(ig)s.",
+ {'ig': initiatorGroupInstanceName})
+ return self.masking.get_masking_views_by_initiator_group(
+ self.conn, initiatorGroupInstanceName)
+
def _create_replica_v3(
self, repServiceInstanceName, cloneVolume,
sourceVolume, sourceInstance, isSnapshot, extraSpecs):
- Extend Volume for VMAX3, SE8.1.0.3
https://blueprints.launchpad.net/cinder/+spec/vmax3-extend-volume
- Incorrect SG selected on an attach (#1515176)
+ - Cleanup Zoning (bug #1501938) NOTE: FC only
"""
VERSION = "2.3.0"
portGroupInstanceName = (
self.common.get_port_group_from_masking_view(
mvInstanceName))
+ initiatorGroupInstanceName = (
+ self.common.get_initiator_group_from_masking_view(
+ mvInstanceName))
LOG.debug("Found port group: %(portGroup)s "
"in masking view %(maskingView)s.",
{'portGroup': portGroupInstanceName,
'maskingView': mvInstanceName})
+ # Map must be populated before the terminate_connection
+ target_wwns, init_targ_map = self._build_initiator_target_map(
+ storage_system, volume, connector)
self.common.terminate_connection(volume, connector)
LOG.debug("Looking for masking views still associated with "
"Port Group %s.", portGroupInstanceName)
- mvInstances = self.common.get_masking_views_by_port_group(
- portGroupInstanceName)
+ mvInstances = self._get_common_masking_views(
+ portGroupInstanceName, initiatorGroupInstanceName)
if len(mvInstances) > 0:
LOG.debug("Found %(numViews)lu MaskingViews.",
{'numViews': len(mvInstances)})
else: # No views found.
- target_wwns, init_targ_map = self._build_initiator_target_map(
- storage_system, volume, connector)
LOG.debug("No MaskingViews were found. Deleting zone.")
data = {'driver_volume_type': 'fibre_channel',
'data': {'target_wwn': target_wwns,
{'volume': volume['name']})
return data
+ def _get_common_masking_views(
+ self, portGroupInstanceName, initiatorGroupInstanceName):
+ """Check to see the existence of mv in list"""
+ mvInstances = []
+ mvInstancesByPG = self.common.get_masking_views_by_port_group(
+ portGroupInstanceName)
+
+ mvInstancesByIG = self.common.get_masking_views_by_initiator_group(
+ initiatorGroupInstanceName)
+
+ for mvInstanceByPG in mvInstancesByPG:
+ if mvInstanceByPG in mvInstancesByIG:
+ mvInstances.append(mvInstanceByPG)
+ return mvInstances
+
def _build_initiator_target_map(self, storage_system, volume, connector):
"""Build the target_wwns and the initiator target map."""
target_wwns = []