Merge "HPE 3PAR: use vlan iscsi ips"

This commit is contained in:
Zuul 2023-08-17 08:56:35 +00:00 committed by Gerrit Code Review
commit 3b9cc13a94
3 changed files with 184 additions and 28 deletions

View File

@ -9003,6 +9003,75 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
self.assertDictEqual(self.multipath_properties, result)
def test_initialize_connection_multipath_vlan_ip(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
mock_client = self.setup_driver()
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}]
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,
'lun': self.TARGET_LUN, 'type': 0,
'portPos': {'node': 8, 'slot': 1, 'cardPort': 1}}]]
location = ("%(volume_name)s,%(lun_id)s,%(host)s,%(nsp)s" %
{'volume_name': self.VOLUME_3PAR_NAME,
'lun_id': self.TARGET_LUN,
'host': self.FAKE_HOST,
'nsp': 'something'})
mock_client.createVLUN.return_value = location
mock_client.getiSCSIPorts.return_value = [{
'IPAddr': '1.1.1.2',
'iSCSIName': self.TARGET_IQN,
'iSCSIVlans': [{'IPAddr': '192.168.100.1',
'iSCSIName': self.TARGET_IQN}]
}]
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
mock_create_client.return_value = mock_client
volume = copy.deepcopy(self.volume)
volume.replication_status = 'disabled'
result = self.driver.initialize_connection(
volume,
self.connector_multipath_enabled)
expected = [
mock.call.getVolume(self.VOLUME_3PAR_NAME),
mock.call.getCPG(HPE3PAR_CPG),
mock.call.getHost(self.FAKE_HOST),
mock.call.queryHost(iqns=['iqn.1993-08.org.debian:01:222']),
mock.call.getHost(self.FAKE_HOST),
mock.call.getiSCSIPorts(
state=self.mock_client_conf['PORT_STATE_READY']),
mock.call.getHostVLUNs(self.FAKE_HOST),
mock.call.createVLUN(
self.VOLUME_3PAR_NAME,
auto=True,
hostname=self.FAKE_HOST,
portPos=self.FAKE_ISCSI_PORT['portPos'],
lun=None),
mock.call.getHostVLUNs(self.FAKE_HOST)]
mock_client.assert_has_calls(
self.standard_login +
expected +
self.standard_logout)
self.assertDictEqual(self.multipath_properties, result)
def test_terminate_connection_for_clear_chap_creds_not_found(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
@ -10537,6 +10606,24 @@ class TestHPE3PARISCSIDriver(HPE3PARBaseDriver):
self.driver.initialize_iscsi_ports,
common)
def test_initialize_iscsi_ports_with_vlan_ip(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
conf = self.setup_configuration()
conf.hpe3par_iscsi_ips = ["192.168.100.1:1234"]
mock_client = self.setup_driver(config=conf)
mock_client.getPorts.return_value = PORTS_VLAN_RET
expected = [mock.call.getPorts()]
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
mock_create_client.return_value = mock_client
common = self.driver._login()
self.driver.initialize_iscsi_ports(common)
mock_client.assert_has_calls(expected)
def test_ensure_export(self):
# setup_mock_client drive with default configuration
# and return the mock HTTP 3PAR client
@ -10889,6 +10976,19 @@ PORTS_RET = ({'members':
'HWAddr': '2C27D75375D6',
'type': 8}]})
PORTS_VLAN_RET = ({'members':
[{'portPos': {'node': 1, 'slot': 8, 'cardPort': 2},
'protocol': 2,
'IPAddr': '10.10.220.252',
'linkState': 4,
'device': [],
'iSCSIName': 'iqn.2000-05.com.3pardata:21820002ac00383d',
'mode': 2,
'HWAddr': '2C27D75375D2',
'type': 8,
'iSCSIVlans': [{'IPAddr': '192.168.100.1'}],
}]})
VLUNS1_RET = ({'members':
[{'portPos': {'node': 1, 'slot': 8, 'cardPort': 2},
'hostname': 'foo', 'active': True},

View File

@ -129,10 +129,11 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
4.0.4 - Added Peer Persistence feature
4.0.5 - Added Primera array check. bug #1849525
4.0.6 - Allow iSCSI support for Primera 4.2 onwards
4.0.7 - Use vlan iscsi ips. Bug #2015034
"""
VERSION = "4.0.6"
VERSION = "4.0.7"
# The name of the CI wiki page.
CI_WIKI_NAME = "HPE_Storage_CI"
@ -164,6 +165,13 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
finally:
self._logout(common)
def _update_dicts(self, temp_iscsi_ip, iscsi_ip_list, ip, port):
ip_port = temp_iscsi_ip[ip]['ip_port']
iscsi_ip_list[ip] = {'ip_port': ip_port,
'nsp': port['nsp'],
'iqn': port['iSCSIName']}
del temp_iscsi_ip[ip]
def initialize_iscsi_ports(self, common,
remote_target=None, remote_client=None):
# map iscsi_ip-> ip_port
@ -202,15 +210,20 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
# when found, add the valid iSCSI ip, ip port, iqn and nsp
# to the iSCSI IP dictionary
iscsi_ports = common.get_active_iscsi_target_ports(remote_client)
LOG.debug("iscsi_ports: %(iscsi_ports)s", {'iscsi_ports': iscsi_ports})
for port in iscsi_ports:
ip = port['IPAddr']
if ip in temp_iscsi_ip:
ip_port = temp_iscsi_ip[ip]['ip_port']
iscsi_ip_list[ip] = {'ip_port': ip_port,
'nsp': port['nsp'],
'iqn': port['iSCSIName']}
del temp_iscsi_ip[ip]
self._update_dicts(temp_iscsi_ip, iscsi_ip_list, ip, port)
if 'iSCSIVlans' in port:
for vip in port['iSCSIVlans']:
ip = vip['IPAddr']
if ip in temp_iscsi_ip:
LOG.debug("vlan ip: %(ip)s", {'ip': ip})
self._update_dicts(temp_iscsi_ip, iscsi_ip_list,
ip, port)
# if the single value iscsi_ip_address option is still in the
# temp dictionary it's because it defaults to $my_ip which doesn't
@ -237,6 +250,44 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
self.iscsi_ips[common._client_conf['hpe3par_api_url']] = (
iscsi_ip_list)
def _vlun_create_or_use_existing(self, volume, common, host, iscsi_ips,
target_portals, target_iqns,
target_luns, remote_client,
target_portal_ips,
existing_vluns, iscsi_ip,
lun_id, port):
vlun = None
# check for an already existing VLUN matching the
# nsp for this iSCSI IP. If one is found, use it
# instead of creating a new VLUN.
for v in existing_vluns:
portPos = common.build_portPos(
iscsi_ips[iscsi_ip]['nsp'])
if v['portPos'] == portPos:
vlun = v
break
else:
vlun = common.create_vlun(
volume, host, iscsi_ips[iscsi_ip]['nsp'],
lun_id=lun_id, remote_client=remote_client)
# This function is called multiple times (from a for loop).
# We want to use the same LUN ID for every port.
# For first port, lun_id is received as None.
# - assign lun_id = vlun['lun'] and return it.
# Thus for subsequent ports, that same lun_id is used
# in create_vlun() above.
if lun_id is None:
lun_id = vlun['lun']
iscsi_ip_port = "%s:%s" % (
iscsi_ip, iscsi_ips[iscsi_ip]['ip_port'])
target_portals.append(iscsi_ip_port)
target_iqns.append(port['iSCSIName'])
target_luns.append(vlun['lun'])
return lun_id
def _initialize_connection_common(self, volume, connector, common,
host, iscsi_ips, ready_ports,
target_portals, target_iqns, target_luns,
@ -255,30 +306,30 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
for port in ready_ports:
iscsi_ip = port['IPAddr']
if iscsi_ip in target_portal_ips:
vlun = None
# check for an already existing VLUN matching the
# nsp for this iSCSI IP. If one is found, use it
# instead of creating a new VLUN.
for v in existing_vluns:
portPos = common.build_portPos(
iscsi_ips[iscsi_ip]['nsp'])
if v['portPos'] == portPos:
vlun = v
break
else:
vlun = common.create_vlun(
volume, host, iscsi_ips[iscsi_ip]['nsp'],
lun_id=lun_id, remote_client=remote_client)
lun_id = (
self._vlun_create_or_use_existing(
volume, common, host, iscsi_ips,
target_portals, target_iqns,
target_luns, remote_client,
target_portal_ips,
existing_vluns, iscsi_ip,
lun_id, port))
# We want to use the same LUN ID for every port
if lun_id is None:
lun_id = vlun['lun']
if 'iSCSIVlans' in port:
for vip in port['iSCSIVlans']:
iscsi_ip = vip['IPAddr']
if iscsi_ip in target_portal_ips:
LOG.debug("vlan ip: %(ip)s", {'ip': iscsi_ip})
lun_id = (
self._vlun_create_or_use_existing(
volume, common, host, iscsi_ips,
target_portals, target_iqns,
target_luns, remote_client,
target_portal_ips,
existing_vluns, iscsi_ip,
lun_id, port))
iscsi_ip_port = "%s:%s" % (
iscsi_ip, iscsi_ips[iscsi_ip]['ip_port'])
target_portals.append(iscsi_ip_port)
target_iqns.append(port['iSCSIName'])
target_luns.append(vlun['lun'])
else:
LOG.warning("iSCSI IP: '%s' was not found in "
"hpe3par_iscsi_ips list defined in "

View File

@ -0,0 +1,5 @@
fixes:
- |
HPE 3PAR driver `Bug #2015034 <https://bugs.launchpad.net/cinder/+bug/2015034>`_:
Added handling for VLAN iscsi IPs in the 3PAR iSCSI driver.