Merge "HPE3PAR: Modify host & clear zone after detach"
This commit is contained in:
commit
d783dd7617
@ -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(
|
||||
|
@ -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'],
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user