Merge "HPE3PAR: Modify host & clear zone after detach"

This commit is contained in:
Zuul 2017-11-11 22:44:35 +00:00 committed by Gerrit Code Review
commit d783dd7617
3 changed files with 86 additions and 17 deletions

View File

@ -364,6 +364,7 @@ class HPE3PARBaseDriver(test.TestCase):
'TASK_DONE': TASK_DONE,
'TASK_ACTIVE': TASK_ACTIVE,
'HOST_EDIT_ADD': 1,
'HOST_EDIT_REMOVE': 2,
'CHAP_INITIATOR': 1,
'CHAP_TARGET': 2,
'getPorts.return_value': {
@ -5966,6 +5967,11 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
'lun': None, 'type': 0},
{'active': True,
'volumeName': 'there-is-another-volume',
'remoteName': '123456789012ABC',
'lun': None, 'type': 0},
{'active': True,
'volumeName': 'there-is-another-volume',
'remoteName': '123456789012ABC',
'lun': None, 'type': 0},
]
@ -5983,7 +5989,18 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
None,
hostname=self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST)]
mock.call.modifyHost(
'fakehost',
{'FCWWNs': ['123456789012345', '123456789054321'],
'pathOperation': self.mock_client_conf['HOST_EDIT_REMOVE']}),
mock.call.getHostVLUNs(self.FAKE_HOST), mock.call.getPorts()]
expect_conn = {
'driver_volume_type': 'fibre_channel',
'data': {'initiator_target_map':
{'123456789012345': ['0987654321234', '123456789000987'],
'123456789054321': ['0987654321234', '123456789000987']},
'target_wwn': ['0987654321234', '123456789000987']}}
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
@ -5994,7 +6011,7 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
self.standard_login +
expect_less +
self.standard_logout)
self.assertNotIn('initiator_target_map', conn_info['data'])
self.assertEqual(expect_conn, conn_info)
def test_get_3par_host_from_wwn_iqn(self):
mock_client = self.setup_driver()
@ -6996,7 +7013,10 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
None,
hostname=self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.modifyHost(
'fakehost',
{'pathOperation': 2,
'iSCSINames': ['iqn.1993-08.org.debian:01:222']}),
mock.call.removeVolumeMetaData(
self.VOLUME_3PAR_NAME, CHAP_USER_KEY),
mock.call.removeVolumeMetaData(
@ -7048,7 +7068,10 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
None,
hostname=self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.modifyHost(
'fakehost',
{'pathOperation': 2,
'iSCSINames': ['iqn.1993-08.org.debian:01:222']}),
mock.call.removeVolumeMetaData(
self.VOLUME_3PAR_NAME, CHAP_USER_KEY)]
@ -7099,7 +7122,10 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
None,
hostname=self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.modifyHost(
'fakehost',
{'pathOperation': 2,
'iSCSINames': ['iqn.1993-08.org.debian:01:222']}),
mock.call.removeVolumeMetaData(
self.VOLUME_3PAR_NAME, CHAP_USER_KEY),
mock.call.removeVolumeMetaData(
@ -8590,7 +8616,10 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
None,
hostname=self.FAKE_HOST),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.deleteHost(self.FAKE_HOST),
mock.call.modifyHost(
'fakehost',
{'pathOperation': 2,
'iSCSINames': ['iqn.1993-08.org.debian:01:222']}),
mock.call.removeVolumeMetaData(
self.VOLUME_3PAR_NAME, CHAP_USER_KEY),
mock.call.removeVolumeMetaData(

View File

@ -266,11 +266,12 @@ class HPE3PARCommon(object):
of QOS. bug #1717875
3.0.39 - Add support for revert to snapshot.
4.0.0 - Code refactor.
4.0.1 - Added check to modify host after volume detach. bug #1730720
"""
VERSION = "4.0.0"
VERSION = "4.0.1"
stats = {}
@ -1497,7 +1498,7 @@ class HPE3PARCommon(object):
vlun_info['lun_id'],
nsp)
def delete_vlun(self, volume, hostname):
def delete_vlun(self, volume, hostname, wwn=None, iqn=None):
volume_name = self._get_3par_vol_name(volume['id'])
vluns = self.client.getHostVLUNs(hostname)
@ -1505,6 +1506,7 @@ class HPE3PARCommon(object):
# and any active VLUNs will be automatically removed. The template
# VLUN are marked as active: False
modify_host = True
volume_vluns = []
for vlun in vluns:
@ -1538,11 +1540,21 @@ class HPE3PARCommon(object):
LOG.debug("All VLUNs removed from host %s", hostname)
pass
if wwn is not None and not isinstance(wwn, list):
wwn = [wwn]
if iqn is not None and not isinstance(iqn, list):
iqn = [iqn]
for vlun in vluns:
if volume_name not in vlun['volumeName']:
# Found another volume
break
else:
if vlun.get('active'):
if (wwn is not None and vlun.get('remoteName').lower() in wwn)\
or (iqn is not None and vlun.get('remoteName').lower() in
iqn):
# vlun with wwn/iqn exists so do not modify host.
modify_host = False
break
if len(vluns) == 0:
# We deleted the last vlun, so try to delete the host too.
# This check avoids the old unnecessary try/fail when vluns exist
# but adds a minor race condition if a vlun is manually deleted
@ -1566,6 +1578,21 @@ class HPE3PARCommon(object):
"because: %(reason)s",
{'name': volume_name, 'host': hostname,
'reason': ex.get_description()})
elif modify_host:
if wwn is not None:
mod_request = {'pathOperation': self.client.HOST_EDIT_REMOVE,
'FCWWNs': wwn}
else:
mod_request = {'pathOperation': self.client.HOST_EDIT_REMOVE,
'iSCSINames': iqn}
try:
self.client.modifyHost(hostname, mod_request)
except Exception as ex:
LOG.info("3PAR vlun for volume '%(name)s' was deleted, "
"but the host '%(host)s' was not Modified "
"because: %(reason)s",
{'name': volume_name, 'host': hostname,
'reason': ex.get_description()})
def _get_volume_type(self, type_id):
ctxt = context.get_admin_context()
@ -2717,7 +2744,7 @@ class HPE3PARCommon(object):
hostname = hosts['members'][0]['name']
try:
self.delete_vlun(volume, hostname)
self.delete_vlun(volume, hostname, wwn=wwn, iqn=iqn)
return
except hpeexceptions.HTTPNotFound as e:
if 'host does not exist' in e.get_description():
@ -2747,7 +2774,7 @@ class HPE3PARCommon(object):
raise
# try again with name retrieved from 3par
self.delete_vlun(volume, hostname)
self.delete_vlun(volume, hostname, wwn=wwn, iqn=iqn)
def build_nsp(self, portPos):
return '%s:%s:%s' % (portPos['node'],

View File

@ -107,10 +107,11 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
3.0.11 - Handle manage and unmanage hosts present. bug #1648067
3.0.12 - Adds consistency group capability in generic volume groups.
4.0.0 - Adds base class.
4.0.1 - Added check to remove FC zones. bug #1730720
"""
VERSION = "4.0.0"
VERSION = "4.0.1"
# The name of the CI wiki page.
CI_WIKI_NAME = "HPE_Storage_CI"
@ -256,18 +257,30 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
info = {'driver_volume_type': 'fibre_channel',
'data': {}}
zone_remove = True
try:
common.client.getHostVLUNs(hostname)
vluns = common.client.getHostVLUNs(hostname)
except hpeexceptions.HTTPNotFound:
# No more exports for this host.
pass
else:
# Vlun exists, so check for wwpn entry.
for wwpn in connector.get('wwpns'):
for vlun in vluns:
if vlun.get('active') and \
vlun.get('remoteName') == wwpn.upper():
zone_remove = False
break
if zone_remove:
LOG.info("Need to remove FC Zone, building initiator "
"target map")
target_wwns, init_targ_map, _numPaths = \
self._build_initiator_target_map(common, connector)
info['data'] = {'target_wwn': target_wwns,
'initiator_target_map': init_targ_map}
return info
finally: