Revert "3PAR: Provide new option to specify NSP for single path attachments"
Several issues pointed out in https://review.opendev.org/#/c/676728/ that were
not flagged here that should be fixed before we backport.
This reverts commit b7c81a7b42
.
Change-Id: Ic1c79c0f1c92d34085e09beab1f5112c466c1c16
This commit is contained in:
parent
b7c81a7b42
commit
2b6ef61294
@ -6940,8 +6940,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
# setup_mock_client drive with default configuration
|
# setup_mock_client drive with default configuration
|
||||||
# and return the mock HTTP 3PAR client
|
# and return the mock HTTP 3PAR client
|
||||||
mock_client = self.setup_driver()
|
mock_client = self.setup_driver()
|
||||||
mock_client.getStorageSystemInfo.return_value = (
|
|
||||||
{'id': self.CLIENT_ID})
|
|
||||||
mock_client.getVolume.return_value = {'userCPG': HPE3PAR_CPG}
|
mock_client.getVolume.return_value = {'userCPG': HPE3PAR_CPG}
|
||||||
mock_client.getCPG.return_value = {}
|
mock_client.getCPG.return_value = {}
|
||||||
mock_client.getHost.side_effect = [
|
mock_client.getHost.side_effect = [
|
||||||
@ -6997,7 +6995,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
mock.call.queryHost(wwns=['123456789012345']),
|
mock.call.queryHost(wwns=['123456789012345']),
|
||||||
mock.call.getHost(self.FAKE_HOST),
|
mock.call.getHost(self.FAKE_HOST),
|
||||||
mock.call.getPorts(),
|
mock.call.getPorts(),
|
||||||
mock.call.getPorts(),
|
|
||||||
mock.call.getHostVLUNs(self.FAKE_HOST),
|
mock.call.getHostVLUNs(self.FAKE_HOST),
|
||||||
mock.call.createVLUN(
|
mock.call.createVLUN(
|
||||||
self.VOLUME_3PAR_NAME,
|
self.VOLUME_3PAR_NAME,
|
||||||
@ -7007,8 +7004,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
mock.call.getHostVLUNs(self.FAKE_HOST)]
|
mock.call.getHostVLUNs(self.FAKE_HOST)]
|
||||||
|
|
||||||
mock_client.assert_has_calls(
|
mock_client.assert_has_calls(
|
||||||
self.get_id_login +
|
|
||||||
self.standard_logout +
|
|
||||||
self.standard_login +
|
self.standard_login +
|
||||||
expected +
|
expected +
|
||||||
self.standard_logout)
|
self.standard_logout)
|
||||||
@ -7030,8 +7025,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
return fake_map
|
return fake_map
|
||||||
mock_lookup.return_value = fake_lookup_object()
|
mock_lookup.return_value = fake_lookup_object()
|
||||||
mock_client = self.setup_driver()
|
mock_client = self.setup_driver()
|
||||||
mock_client.getStorageSystemInfo.return_value = (
|
|
||||||
{'id': self.CLIENT_ID})
|
|
||||||
mock_client.getVolume.return_value = {'userCPG': HPE3PAR_CPG}
|
mock_client.getVolume.return_value = {'userCPG': HPE3PAR_CPG}
|
||||||
mock_client.getCPG.return_value = {}
|
mock_client.getCPG.return_value = {}
|
||||||
mock_client.getHost.side_effect = [
|
mock_client.getHost.side_effect = [
|
||||||
@ -7094,7 +7087,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.call.getHost(self.FAKE_HOST),
|
mock.call.getHost(self.FAKE_HOST),
|
||||||
mock.call.getPorts(),
|
mock.call.getPorts(),
|
||||||
mock.call.getPorts(),
|
|
||||||
mock.call.getHostVLUNs(self.FAKE_HOST),
|
mock.call.getHostVLUNs(self.FAKE_HOST),
|
||||||
mock.call.getPorts(),
|
mock.call.getPorts(),
|
||||||
mock.call.createVLUN(
|
mock.call.createVLUN(
|
||||||
@ -7106,89 +7098,6 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver):
|
|||||||
mock.call.getHostVLUNs(self.FAKE_HOST)]
|
mock.call.getHostVLUNs(self.FAKE_HOST)]
|
||||||
|
|
||||||
mock_client.assert_has_calls(
|
mock_client.assert_has_calls(
|
||||||
self.get_id_login +
|
|
||||||
self.standard_logout +
|
|
||||||
self.standard_login +
|
|
||||||
expected +
|
|
||||||
self.standard_logout)
|
|
||||||
|
|
||||||
self.assertDictEqual(expected_properties, result)
|
|
||||||
|
|
||||||
def test_initialize_connection_single_path_target_nsp(self):
|
|
||||||
# setup_mock_client drive with default configuration
|
|
||||||
# and return the mock HTTP 3PAR client
|
|
||||||
mock_client = self.setup_driver()
|
|
||||||
self.driver.configuration.hpe3par_target_nsp = '2:1:2'
|
|
||||||
mock_client.getStorageSystemInfo.return_value = (
|
|
||||||
{'id': self.CLIENT_ID})
|
|
||||||
mock_client.getVolume.return_value = {'userCPG': HPE3PAR_CPG}
|
|
||||||
mock_client.getCPG.return_value = {}
|
|
||||||
mock_client.getHost.side_effect = [
|
|
||||||
hpeexceptions.HTTPNotFound('fake'),
|
|
||||||
{'name': self.FAKE_HOST,
|
|
||||||
'FCPaths': [{'driverVersion': None,
|
|
||||||
'firmwareVersion': None,
|
|
||||||
'hostSpeed': 0,
|
|
||||||
'model': None,
|
|
||||||
'vendor': None,
|
|
||||||
'wwn': self.wwn[0]}]}]
|
|
||||||
mock_client.queryHost.return_value = {
|
|
||||||
'members': [{
|
|
||||||
'name': self.FAKE_HOST
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
mock_client.getHostVLUNs.side_effect = [
|
|
||||||
hpeexceptions.HTTPNotFound('fake'),
|
|
||||||
[{'active': True,
|
|
||||||
'volumeName': self.VOLUME_3PAR_NAME,
|
|
||||||
'portPos': {'node': 7, 'slot': 1, 'cardPort': 1},
|
|
||||||
'remoteName': self.wwn[0],
|
|
||||||
'lun': 90, 'type': 0}]]
|
|
||||||
|
|
||||||
location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" %
|
|
||||||
{'volume_name': self.VOLUME_3PAR_NAME,
|
|
||||||
'lun_id': 90,
|
|
||||||
'host': self.FAKE_HOST,
|
|
||||||
'nsp': 'something'})
|
|
||||||
mock_client.createVLUN.return_value = location
|
|
||||||
user_target_wwn = '0987654321234'
|
|
||||||
expected_properties = {
|
|
||||||
'driver_volume_type': 'fibre_channel',
|
|
||||||
'data': {
|
|
||||||
'encrypted': False,
|
|
||||||
'target_lun': 90,
|
|
||||||
'target_wwn': [user_target_wwn],
|
|
||||||
'target_discovered': True,
|
|
||||||
'initiator_target_map':
|
|
||||||
{'123456789012345': [user_target_wwn]}}}
|
|
||||||
|
|
||||||
with mock.patch.object(hpecommon.HPE3PARCommon,
|
|
||||||
'_create_client') as mock_create_client:
|
|
||||||
mock_create_client.return_value = mock_client
|
|
||||||
result = self.driver.initialize_connection(
|
|
||||||
self.volume,
|
|
||||||
self.connector.copy())
|
|
||||||
|
|
||||||
expected = [
|
|
||||||
mock.call.getVolume(self.VOLUME_3PAR_NAME),
|
|
||||||
mock.call.getCPG(HPE3PAR_CPG),
|
|
||||||
mock.call.getHost(self.FAKE_HOST),
|
|
||||||
mock.call.queryHost(wwns=['123456789012345']),
|
|
||||||
mock.call.getHost(self.FAKE_HOST),
|
|
||||||
mock.call.getPorts(),
|
|
||||||
mock.call.getPorts(),
|
|
||||||
mock.call.getHostVLUNs(self.FAKE_HOST),
|
|
||||||
mock.call.createVLUN(
|
|
||||||
self.VOLUME_3PAR_NAME,
|
|
||||||
auto=True,
|
|
||||||
hostname=self.FAKE_HOST,
|
|
||||||
lun=None),
|
|
||||||
mock.call.getHostVLUNs(self.FAKE_HOST)]
|
|
||||||
|
|
||||||
mock_client.assert_has_calls(
|
|
||||||
self.get_id_login +
|
|
||||||
self.standard_logout +
|
|
||||||
self.standard_login +
|
self.standard_login +
|
||||||
expected +
|
expected +
|
||||||
self.standard_logout)
|
self.standard_logout)
|
||||||
|
@ -118,15 +118,6 @@ hpe3par_opts = [
|
|||||||
cfg.BoolOpt('hpe3par_iscsi_chap_enabled',
|
cfg.BoolOpt('hpe3par_iscsi_chap_enabled',
|
||||||
default=False,
|
default=False,
|
||||||
help="Enable CHAP authentication for iSCSI connections."),
|
help="Enable CHAP authentication for iSCSI connections."),
|
||||||
cfg.StrOpt('hpe3par_target_nsp',
|
|
||||||
default="",
|
|
||||||
help="The nsp of 3PAR backend to be used when: "
|
|
||||||
"(1) multipath is not enabled in cinder.conf. "
|
|
||||||
"(2) Fiber Channel Zone Manager is not used. "
|
|
||||||
"(3) the 3PAR backend is prezoned with this "
|
|
||||||
" specific nsp only. "
|
|
||||||
"For example if nsp is 2 1 2, the format of the "
|
|
||||||
"option's value is 2:1:2"),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,22 +173,10 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
|
|||||||
host = self._create_host(common, volume, connector)
|
host = self._create_host(common, volume, connector)
|
||||||
target_wwns, init_targ_map, numPaths = \
|
target_wwns, init_targ_map, numPaths = \
|
||||||
self._build_initiator_target_map(common, connector)
|
self._build_initiator_target_map(common, connector)
|
||||||
|
if not connector.get('multipath'):
|
||||||
multipath = connector.get('multipath')
|
target_wwns = target_wwns[:1]
|
||||||
LOG.debug("multipath: %(multipath)s",
|
|
||||||
{'multipath': multipath})
|
|
||||||
user_target = None
|
|
||||||
if not multipath:
|
|
||||||
user_target = self._get_user_target(common)
|
|
||||||
initiator = connector.get('wwpns')[0]
|
initiator = connector.get('wwpns')[0]
|
||||||
if user_target is None:
|
init_targ_map[initiator] = init_targ_map[initiator][:1]
|
||||||
target_wwns = target_wwns[:1]
|
|
||||||
init_targ_map[initiator] = \
|
|
||||||
init_targ_map[initiator][:1]
|
|
||||||
else:
|
|
||||||
target_wwns = [user_target]
|
|
||||||
init_targ_map[initiator] = [user_target]
|
|
||||||
|
|
||||||
# check if a VLUN already exists for this host
|
# check if a VLUN already exists for this host
|
||||||
existing_vlun = common.find_existing_vlun(volume, host)
|
existing_vlun = common.find_existing_vlun(volume, host)
|
||||||
|
|
||||||
@ -423,26 +411,3 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
|
|||||||
self._modify_3par_fibrechan_host(common, host['name'], new_wwns)
|
self._modify_3par_fibrechan_host(common, host['name'], new_wwns)
|
||||||
host = common._get_3par_host(host['name'])
|
host = common._get_3par_host(host['name'])
|
||||||
return host
|
return host
|
||||||
|
|
||||||
def _get_user_target(self, common):
|
|
||||||
target_nsp = common.config.hpe3par_target_nsp
|
|
||||||
|
|
||||||
if not target_nsp:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
# Get target wwn from target nsp
|
|
||||||
fc_ports = common.get_active_fc_target_ports()
|
|
||||||
|
|
||||||
target_wwn = ''
|
|
||||||
for port in fc_ports:
|
|
||||||
nsp = port['nsp']
|
|
||||||
if target_nsp == nsp:
|
|
||||||
target_wwn = port['portWWN']
|
|
||||||
break
|
|
||||||
|
|
||||||
if not target_wwn:
|
|
||||||
LOG.warning("Did not get wwn for target nsp: "
|
|
||||||
"%(nsp)s", {'nsp': target_nsp})
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return target_wwn
|
|
||||||
|
@ -413,51 +413,3 @@ the HPE 3PAR Fibre Channel and iSCSI drivers.
|
|||||||
:config-target: 3PAR
|
:config-target: 3PAR
|
||||||
|
|
||||||
cinder.volume.drivers.hpe.hpe_3par_common
|
cinder.volume.drivers.hpe.hpe_3par_common
|
||||||
|
|
||||||
|
|
||||||
Specify NSP for FC Bootable Volume
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Given a system connected to HPE 3PAR via FC and multipath setting is
|
|
||||||
NOT used in cinder.conf. When the user tries to create a bootable
|
|
||||||
volume, it fails intermittently with the following error:
|
|
||||||
Fibre Channel volume device not found
|
|
||||||
|
|
||||||
This happens when a zone is created using second or later target from
|
|
||||||
3PAR backend. In this case, HPE 3PAR client code picks up first target
|
|
||||||
to form initiator target map. This can be illustrated with below
|
|
||||||
example.
|
|
||||||
|
|
||||||
Sample output of showport command:
|
|
||||||
|
|
||||||
``$ showport -sortcol 6``
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
N:S:P Mode State ----Node_WWN---- -Port_WWN/HW_Addr- Type Protocol Partner FailoverState
|
|
||||||
0:1:1 target ready 2FF70002AC002DB6 20110002AC002DB6 host FC - -
|
|
||||||
0:1:2 target ready 2FF70002AC002DB6 20120002AC002DB6 host FC 1:1:2 none
|
|
||||||
1:1:1 initiator ready 2FF70002AC002DB6 21110002AC002DB6 rcfc FC - -
|
|
||||||
1:1:2 target ready 2FF70002AC002DB6 21120002AC002DB6 host FC 0:1:2 none
|
|
||||||
2:1:1 initiator ready 2FF70002AC002DB6 22110002AC002DB6 rcfc FC - -
|
|
||||||
2:1:2 target ready 2FF70002AC002DB6 22120002AC002DB6 host FC 3:1:2 none
|
|
||||||
3:1:1 target ready 2FF70002AC002DB6 23110002AC002DB6 host FC - -
|
|
||||||
3:1:2 target ready 2FF70002AC002DB6 23120002AC002DB6 host FC 2:1:2 none
|
|
||||||
|
|
||||||
Suppose zone is created using targets "2:1:2" and "3:1:2" from above
|
|
||||||
output. Then initiator target map is created using target "0:1:1" only.
|
|
||||||
In such a case, the path is not found, and bootable volume creation fails.
|
|
||||||
|
|
||||||
To avoid above mentioned failure, the user can specify the target in 3PAR
|
|
||||||
backend section of cinder.conf as follows:
|
|
||||||
|
|
||||||
``hpe3par_target_nsp = 3:1:2``
|
|
||||||
|
|
||||||
Using above mentioned nsp, respective wwn information is fetched.
|
|
||||||
Later initiator target map is created using wwn information and
|
|
||||||
bootable volume is created successfully.
|
|
||||||
|
|
||||||
Note: If above mentioned option (nsp) is not specified in cinder.conf,
|
|
||||||
then the original flow is executed i.e first target is picked and
|
|
||||||
bootable volume creation may fail.
|
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
fixes:
|
|
||||||
- |
|
|
||||||
This change fixes bug 1809249 - 3PAR driver picks wrong port when
|
|
||||||
not in multipath mode. Now the user can specify target NSP (Node-
|
|
||||||
Slot-Port) in cinder.conf. This information is used to create
|
|
||||||
initiator target map accordingly. And then bootable volume is
|
|
||||||
created successfully.
|
|
Loading…
Reference in New Issue
Block a user