Merge "[SVF]:Fix multiple lshost calls during attach."
This commit is contained in:
commit
f3d12a1385
@ -178,6 +178,9 @@ class StorwizeSVCManagementSimulator(object):
|
||||
'CMMVC8783E': ('', 'CMMVC8783E The volume copy was not deleted '
|
||||
'because the volume is part of a consistency '
|
||||
'group.'),
|
||||
'CMMVC6578E': ('', 'CMMVC6578E The command has failed because '
|
||||
'the iSCSI name is already assigned or is '
|
||||
'not valid.'),
|
||||
}
|
||||
self._fc_transitions = {'begin': {'make': 'idle_or_copied'},
|
||||
'idle_or_copied': {'prepare': 'preparing',
|
||||
@ -1209,7 +1212,10 @@ port_speed!N/A
|
||||
continue
|
||||
for port in v[added_key]:
|
||||
if port == added_val:
|
||||
return self._errors['CMMVC6581E']
|
||||
error = 'CMMVC6035E'
|
||||
if 'iscsiname' in kwargs:
|
||||
error = 'CMMVC6578E'
|
||||
return self._errors[error]
|
||||
return ('', '')
|
||||
|
||||
# Make a host
|
||||
@ -3264,7 +3270,10 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
||||
snapshot,
|
||||
connector)
|
||||
|
||||
def test_storwize_initialize_iscsi_connection_with_host_site(self):
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'initialize_host_info')
|
||||
def test_storwize_initialize_iscsi_connection_with_host_site(self,
|
||||
init_host):
|
||||
connector = {'host': 'storwize-svc-host',
|
||||
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||
'wwpns': ['ff00000000000000', 'ff00000000000001'],
|
||||
@ -3279,6 +3288,8 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
||||
volume_iSCSI_2 = self._create_volume()
|
||||
volume_iSCSI_2['volume_type_id'] = vol_type_iSCSI['id']
|
||||
self.iscsi_driver.initialize_connection(volume_iSCSI, connector)
|
||||
init_host.assert_called()
|
||||
self.assertEqual(1, init_host.call_count)
|
||||
host_name = self.iscsi_driver._helpers.get_host_from_connector(
|
||||
connector, iscsi=True)
|
||||
host_info = self.iscsi_driver._helpers.ssh.lshost(host=host_name)
|
||||
@ -3337,7 +3348,10 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
||||
volume_iSCSI, connector)
|
||||
term_conn.assert_called_once_with(volume_iSCSI, connector)
|
||||
|
||||
def test_storwize_terminate_iscsi_connection_multi_attach(self):
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'initialize_host_info')
|
||||
def test_storwize_terminate_iscsi_connection_multi_attach(self,
|
||||
init_host_info):
|
||||
# create an iSCSI volume
|
||||
volume_iSCSI = self._create_volume()
|
||||
extra_spec = {'capabilities:storage_protocol': '<in> iSCSI'}
|
||||
@ -3355,6 +3369,7 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
||||
|
||||
# map and unmap the volume to two hosts normal case
|
||||
self.iscsi_driver.initialize_connection(volume_iSCSI, connector)
|
||||
init_host_info.assert_called()
|
||||
self.iscsi_driver.initialize_connection(volume_iSCSI, connector2)
|
||||
for conn in [connector, connector2]:
|
||||
host = self.iscsi_driver._helpers.get_host_from_connector(
|
||||
@ -3382,6 +3397,7 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
||||
rmmap.side_effect = Exception('boom')
|
||||
self.iscsi_driver.terminate_connection(volume_iSCSI,
|
||||
connector2)
|
||||
init_host_info.assert_called()
|
||||
host_name = self.iscsi_driver._helpers.get_host_from_connector(
|
||||
connector2, iscsi=True)
|
||||
self.assertIsNone(host_name)
|
||||
@ -4401,12 +4417,6 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
|
||||
|
||||
# Check bad output from lsfabric for the 2nd volume
|
||||
if protocol == 'FC' and self.USESIM:
|
||||
for error in ['remove_field', 'header_mismatch']:
|
||||
self.sim.error_injection('lsfabric', error)
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.fc_driver.initialize_connection,
|
||||
volume2, self._connector)
|
||||
|
||||
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_conn_fc_wwpns') as conn_fc_wwpns:
|
||||
conn_fc_wwpns.return_value = []
|
||||
@ -9823,17 +9833,17 @@ class StorwizeHelpersTestCase(test.TestCase):
|
||||
access=access)
|
||||
startrcrelationship.assert_called_once_with(opts['RC_name'], None)
|
||||
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsfabric')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_host_from_host_info')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lshost')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsvdiskhostmap')
|
||||
def test_get_host_from_connector_with_vol(self,
|
||||
lsvdishosmap,
|
||||
lshost,
|
||||
lsfabric):
|
||||
get_host_from_host_info):
|
||||
vol = 'testvol'
|
||||
connector = {"wwpns": ["10000090fa3870d7", "C050760825191B00"]}
|
||||
lsfabric.return_value = [{"remote_wwpn": "10000090fa3870d7",
|
||||
"name": "test_host"}]
|
||||
get_host_from_host_info.return_value = "test_host", []
|
||||
raw = "id!name!host_id!host_name!vdisk_UID\n2594!testvol!315!"\
|
||||
"test_host!60050768028110A4700000000001168E"
|
||||
ssh_cmd = ['svcinfo', 'lsvdiskhostmap', '-delim', '!', '"%s"' % vol]
|
||||
@ -9844,23 +9854,23 @@ class StorwizeHelpersTestCase(test.TestCase):
|
||||
host = self.storwize_svc_common.get_host_from_connector(connector,
|
||||
vol)
|
||||
self.assertEqual(host, "test_host")
|
||||
lsfabric.assert_called_with(wwpn='10000090fa3870d7')
|
||||
self.assertEqual(1, lsfabric.call_count)
|
||||
get_host_from_host_info.assert_called_with(connector, False)
|
||||
self.assertEqual(1, get_host_from_host_info.call_count)
|
||||
lsvdishosmap.assert_called_with(vol)
|
||||
self.assertEqual(1, lsvdishosmap.call_count)
|
||||
lshost.assert_not_called()
|
||||
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsfabric')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_host_from_host_info')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lshost')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsvdiskhostmap')
|
||||
def test_get_host_from_connector_wo_vol(self,
|
||||
lsvdishosmap,
|
||||
lshost,
|
||||
lsfabric):
|
||||
get_host_from_host_info):
|
||||
vol = 'testvol'
|
||||
connector = {"wwpns": ["10000090fa3870d7", "C050760825191B00"]}
|
||||
lsfabric.return_value = [{"remote_wwpn": "10000090fa3870d7",
|
||||
"name": "test_host"}]
|
||||
get_host_from_host_info.return_value = "test_host", []
|
||||
raw = "id!name!host_id!host_name!vdisk_UID\n2594!testvol!315!"\
|
||||
"test_host!60050768028110A4700000000001168E"
|
||||
ssh_cmd = ['svcinfo', 'lsvdiskhostmap', '-delim', '!', '"%s"' % vol]
|
||||
@ -9870,8 +9880,8 @@ class StorwizeHelpersTestCase(test.TestCase):
|
||||
True)
|
||||
host = self.storwize_svc_common.get_host_from_connector(connector)
|
||||
self.assertEqual(host, "test_host")
|
||||
lsfabric.assert_called_with(wwpn='10000090fa3870d7')
|
||||
self.assertEqual(1, lsfabric.call_count)
|
||||
get_host_from_host_info.assert_called_with(connector, False)
|
||||
self.assertEqual(1, get_host_from_host_info.call_count)
|
||||
lsvdishosmap.assert_not_called()
|
||||
self.assertEqual(0, lsvdishosmap.call_count)
|
||||
lshost.assert_not_called()
|
||||
@ -12896,11 +12906,14 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
self.driver._sync_with_aux_grp(self.ctxt, rccg_name)
|
||||
startrccg.assert_called_with(rccg_name, 'aux')
|
||||
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'initialize_host_info')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'get_host_from_connector')
|
||||
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||
'check_vol_mapped_to_host')
|
||||
def test_get_map_info_from_connector(self, is_mapped, get_host_from_conn):
|
||||
def test_get_map_info_from_connector(self, is_mapped, get_host_from_conn,
|
||||
initialize_host_info):
|
||||
self.driver.configuration.set_override('replication_device',
|
||||
[self.rep_target])
|
||||
self.driver.do_setup(self.ctxt)
|
||||
@ -12927,6 +12940,8 @@ class StorwizeSVCReplicationTestCase(test.TestCase):
|
||||
backend_helper)
|
||||
self.assertEqual(self.driver._master_state,
|
||||
node_state)
|
||||
initialize_host_info.assert_called()
|
||||
self.assertEqual(1, initialize_host_info.call_count)
|
||||
|
||||
connector = {'host': 'storwize-svc-host',
|
||||
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||
|
@ -796,6 +796,7 @@ class StorwizeHelpers(object):
|
||||
self.check_fcmapping_interval = 3
|
||||
self.code_level = None
|
||||
self.stats = {}
|
||||
self.Host_connector_info = {"FC": {}, "ISCSI": {}}
|
||||
|
||||
@staticmethod
|
||||
def handle_keyerror(cmd, out):
|
||||
@ -1131,28 +1132,48 @@ class StorwizeHelpers(object):
|
||||
wwpns.add(wwpn)
|
||||
return list(wwpns)
|
||||
|
||||
def initialize_host_info(self):
|
||||
"""Get the host,wwpn,iscsi and store in Host_connector_info."""
|
||||
if (not self.Host_connector_info['FC'] and
|
||||
not self.Host_connector_info['ISCSI']):
|
||||
hosts_info = self.ssh.lshost()
|
||||
host_list = list(hosts_info.select('name'))
|
||||
for eachhost in host_list:
|
||||
resp = self.ssh.lshost(host=eachhost)
|
||||
if list(resp.select("WWPN")) != [None]:
|
||||
for wwpn in resp.select('WWPN'):
|
||||
if wwpn not in self.Host_connector_info['FC'].keys():
|
||||
self.Host_connector_info['FC'][wwpn] = eachhost
|
||||
elif list(resp.select('iscsi_name')) != [None]:
|
||||
for iscsi_name in resp.select('iscsi_name'):
|
||||
if (iscsi_name not in
|
||||
self.Host_connector_info['ISCSI'].keys()):
|
||||
self.Host_connector_info['ISCSI'][iscsi_name] = (
|
||||
eachhost)
|
||||
|
||||
def get_host_from_host_info(self, connector, iscsi=False):
|
||||
host_name = None
|
||||
new_wwpn = []
|
||||
if iscsi and 'initiator' in connector:
|
||||
if connector['initiator'] in self.Host_connector_info['ISCSI']:
|
||||
iqn = connector['initiator']
|
||||
host_name = self.Host_connector_info['ISCSI'][iqn]
|
||||
elif 'wwpns' in connector:
|
||||
for wwpn in connector['wwpns']:
|
||||
if wwpn.upper() in self.Host_connector_info['FC']:
|
||||
host_name = self.Host_connector_info['FC'][wwpn.upper()]
|
||||
else:
|
||||
new_wwpn.append(['wwpn', '%s' % wwpn])
|
||||
|
||||
return host_name, new_wwpn
|
||||
|
||||
def get_host_from_connector(self, connector, volume_name=None,
|
||||
iscsi=False):
|
||||
"""Return the Storwize host described by the connector."""
|
||||
LOG.debug('Enter: get_host_from_connector: %s.', connector)
|
||||
|
||||
# If we have FC information, we have a faster lookup option
|
||||
host_name = None
|
||||
if 'wwpns' in connector and not iscsi:
|
||||
for wwpn in connector['wwpns']:
|
||||
resp = self.ssh.lsfabric(wwpn=wwpn)
|
||||
for wwpn_info in resp:
|
||||
try:
|
||||
if (wwpn_info['remote_wwpn'] and
|
||||
wwpn_info['name'] and
|
||||
wwpn_info['remote_wwpn'].lower() ==
|
||||
wwpn.lower()):
|
||||
host_name = wwpn_info['name']
|
||||
break
|
||||
except KeyError:
|
||||
self.handle_keyerror('lsfabric', wwpn_info)
|
||||
if host_name:
|
||||
break
|
||||
host_name, new_wwpn = self.get_host_from_host_info(connector, iscsi)
|
||||
|
||||
if host_name and volume_name:
|
||||
hosts_map_info = self.ssh.lsvdiskhostmap(volume_name)
|
||||
@ -1168,6 +1189,11 @@ class StorwizeHelpers(object):
|
||||
host_name = None
|
||||
|
||||
if host_name:
|
||||
for port in new_wwpn:
|
||||
LOG.debug('update wwpn %(wwpn)s to host %(host)s.',
|
||||
{'wwpn': port, 'host': host_name})
|
||||
self.ssh.addhostport(host_name, port[0], port[1])
|
||||
|
||||
LOG.debug('Leave: get_host_from_connector: host %s.', host_name)
|
||||
return host_name
|
||||
|
||||
@ -1298,6 +1324,13 @@ class StorwizeHelpers(object):
|
||||
for port in ports:
|
||||
self.ssh.addhostport(host_name, port[0], port[1])
|
||||
|
||||
if iscsi and 'initiator' in connector:
|
||||
iqn = connector['initiator']
|
||||
self.Host_connector_info['ISCSI'][iqn] = host_name
|
||||
elif 'wwpns' in connector:
|
||||
for wwpn in connector['wwpns']:
|
||||
self.Host_connector_info['FC'][wwpn.upper()] = host_name
|
||||
|
||||
LOG.debug('Leave: create_host: host %(host)s - %(host_name)s.',
|
||||
{'host': connector['host'], 'host_name': host_name})
|
||||
return host_name
|
||||
@ -1308,6 +1341,23 @@ class StorwizeHelpers(object):
|
||||
def delete_host(self, host_name):
|
||||
self.ssh.rmhost(host_name)
|
||||
|
||||
if host_name in self.Host_connector_info['ISCSI'].values():
|
||||
host_iqn = None
|
||||
for iqn, host in self.Host_connector_info['ISCSI'].items():
|
||||
if host == host_name:
|
||||
host_iqn = iqn
|
||||
break
|
||||
if host_iqn:
|
||||
self.Host_connector_info['ISCSI'].pop(host_iqn)
|
||||
elif host_name in self.Host_connector_info['FC'].values():
|
||||
host_wwpn = []
|
||||
for wwpn, host in self.Host_connector_info['FC'].items():
|
||||
if host == host_name:
|
||||
host_wwpn.append(wwpn)
|
||||
|
||||
for wwpn in host_wwpn:
|
||||
self.Host_connector_info['FC'].pop(wwpn)
|
||||
|
||||
def _get_unused_lun_id(self, host_name):
|
||||
luns_used = []
|
||||
result_lun = '-1'
|
||||
@ -4863,6 +4913,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||
vol_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||
volume)
|
||||
|
||||
backend_helper.initialize_host_info()
|
||||
|
||||
info = {}
|
||||
if 'host' in connector:
|
||||
# get host according to FC protocol
|
||||
|
@ -172,6 +172,8 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
volume)
|
||||
|
||||
host_site = None
|
||||
backend_helper.initialize_host_info()
|
||||
|
||||
is_hyper_volume = self.is_volume_hyperswap(volume)
|
||||
if is_hyper_volume:
|
||||
host_site = self._get_volume_host_site_from_conf(volume,
|
||||
@ -183,12 +185,24 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeDriverException(message=msg)
|
||||
|
||||
# Check if a host object is defined for this host name
|
||||
host_name = backend_helper.get_host_from_connector(connector)
|
||||
if host_name is None:
|
||||
# Host does not exist - add a new host to Storwize/SVC
|
||||
# Try creating the host, if host creation is successfull continue
|
||||
# with intialization flow, else search for host object defined for
|
||||
# this connector info.
|
||||
host_name = None
|
||||
try:
|
||||
host_name = backend_helper.create_host(connector, site=host_site)
|
||||
elif is_hyper_volume:
|
||||
except exception.VolumeBackendAPIException as excp:
|
||||
if "CMMVC6035E" in excp.msg:
|
||||
msg = (_('Host already exists for connector '
|
||||
'%(conn)s'), {'conn': connector})
|
||||
LOG.info(msg)
|
||||
host_name = backend_helper.get_host_from_connector(connector)
|
||||
else:
|
||||
msg = (_('Error creating host %(ex)s'), {'ex': excp.msg})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeDriverException(message=msg)
|
||||
|
||||
if is_hyper_volume:
|
||||
self._update_host_site_for_hyperswap_volume(host_name, host_site)
|
||||
|
||||
volume_attributes = backend_helper.get_vdisk_attributes(volume_name)
|
||||
|
@ -166,6 +166,8 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||
volume)
|
||||
|
||||
backend_helper.initialize_host_info()
|
||||
|
||||
host_site = self._get_volume_host_site_from_conf(volume,
|
||||
connector,
|
||||
iscsi=True)
|
||||
@ -176,14 +178,26 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeDriverException(message=msg)
|
||||
|
||||
# Check if a host object is defined for this host name
|
||||
host_name = backend_helper.get_host_from_connector(connector,
|
||||
iscsi=True)
|
||||
if host_name is None:
|
||||
# Host does not exist - add a new host to Storwize/SVC
|
||||
# Try creating the host, if host creation is successfull continue
|
||||
# with intialization flow, else search for host object defined for
|
||||
# this connector info.
|
||||
host_name = None
|
||||
try:
|
||||
host_name = backend_helper.create_host(connector, iscsi=True,
|
||||
site=host_site)
|
||||
elif is_hyper_volume:
|
||||
except exception.VolumeBackendAPIException as excp:
|
||||
if "CMMVC6578E" in excp.msg:
|
||||
msg = (_('Host already exists for connector '
|
||||
'%(conn)s'), {'conn': connector})
|
||||
LOG.info(msg)
|
||||
host_name = backend_helper.get_host_from_connector(connector,
|
||||
iscsi=True)
|
||||
else:
|
||||
msg = (_('Error creating host %(ex)s'), {'ex': excp.msg})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeDriverException(message=msg)
|
||||
|
||||
if is_hyper_volume:
|
||||
self._update_host_site_for_hyperswap_volume(host_name, host_site)
|
||||
|
||||
chap_secret = backend_helper.get_chap_secret_for_host(host_name)
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
IBM Spectrum Virtualize Family driver `Bug #1913363
|
||||
<https://bugs.launchpad.net/cinder/+bug/1913363>`_: Fixed
|
||||
issue in get_host_from_connector by caching the host
|
||||
information during attach or detach operations and using
|
||||
host details from cached information.
|
Loading…
x
Reference in New Issue
Block a user