Merge "[Pure Storage] Fix issue with LACP ports not being identified" into stable/2025.1
This commit is contained in:
commit
3df9d33c89
@ -590,7 +590,34 @@ NON_ISCSI_PORT = {
|
||||
"portal": None,
|
||||
"wwn": "5001500150015081",
|
||||
}
|
||||
NVME_PORTS_WITH = NVME_PORTS + [NON_ISCSI_PORT]
|
||||
ISCSI_LACP_PORTS = [
|
||||
{
|
||||
"name": "lacp2",
|
||||
"iqn": TARGET_IQN,
|
||||
"nqn": None,
|
||||
"portal": None,
|
||||
"wwn": None,
|
||||
},
|
||||
]
|
||||
NVME_LACP_PORTS = [
|
||||
{
|
||||
"name": "lacp0",
|
||||
"iqn": None,
|
||||
"nqn": TARGET_NQN,
|
||||
"portal": None,
|
||||
"wwn": None,
|
||||
},
|
||||
{
|
||||
"name": "lacp1",
|
||||
"iqn": None,
|
||||
"nqn": TARGET_NQN,
|
||||
"portal": None,
|
||||
"wwn": None,
|
||||
},
|
||||
]
|
||||
NVME_PORTS_WITH = NVME_PORTS + [NON_ISCSI_PORT] + NVME_LACP_PORTS
|
||||
ISCSI_PORTS_WITH = ISCSI_PORTS + ISCSI_LACP_PORTS
|
||||
PORTS_WITH = ISCSI_PORTS + [NON_ISCSI_PORT] + ISCSI_LACP_PORTS
|
||||
PORTS_WITH = ISCSI_PORTS + [NON_ISCSI_PORT]
|
||||
PORTS_WITHOUT = [NON_ISCSI_PORT]
|
||||
TOTAL_CAPACITY = 50.0
|
||||
@ -1186,6 +1213,56 @@ VGROUP = 'puretest-vgroup'
|
||||
ARRAY_RESPONSE = {
|
||||
'status_code': 200
|
||||
}
|
||||
INTERFACES = [
|
||||
{
|
||||
'name': 'ct0.eth4',
|
||||
'services': ['nvme-tcp'],
|
||||
'eth': {'address': '1.1.1.1',
|
||||
'subtype': 'physical'},
|
||||
},
|
||||
{
|
||||
'name': 'ct0.eth5',
|
||||
'services': ['iscsi'],
|
||||
'eth': {'address': '2.2.2.2',
|
||||
'subtype': 'physical'},
|
||||
},
|
||||
{
|
||||
'name': 'ct0.eth20',
|
||||
'services': ['nvme-roce'],
|
||||
'eth': {'address': '3.3.3.3',
|
||||
'subtype': 'physical'}
|
||||
},
|
||||
{
|
||||
'name': 'ct0.fc4',
|
||||
'services': ['nvme-fc'],
|
||||
'eth': {'address': None,
|
||||
'subtype': 'physical'},
|
||||
},
|
||||
{
|
||||
'name': 'lacp0',
|
||||
'services': ['nvme-roce'],
|
||||
'eth': {'address': '4.4.4.4',
|
||||
'subtype': 'lacp_bond'},
|
||||
},
|
||||
{
|
||||
'name': 'lacp1',
|
||||
'services': ['nvme-tcp'],
|
||||
'eth': {'address': '5.5.5.5',
|
||||
'subtype': 'lacp_bond'},
|
||||
},
|
||||
{
|
||||
'name': 'lacp2',
|
||||
'services': ['iscsi'],
|
||||
'eth': {'address': '6.6.6.6',
|
||||
'subtype': 'lacp_bond'},
|
||||
},
|
||||
{
|
||||
'name': 'ct0.fc1',
|
||||
'services': ['scsi-fc'],
|
||||
'eth': {'address': None,
|
||||
'subtype': 'physical'},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class PureDriverTestCase(test.TestCase):
|
||||
@ -4746,21 +4823,27 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
def test_get_target_iscsi_ports(self):
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
self.array.get_ports.return_value = VALID_ISCSI_PORTS
|
||||
self.array.get_network_interfaces.return_value = ValidResponse(
|
||||
200, None, 1, [DotNotation(INTERFACES[1])], {})
|
||||
ret = self.driver._get_target_iscsi_ports(self.array)
|
||||
self.assertEqual(ISCSI_PORTS[0:4], ret)
|
||||
self.assertEqual(ISCSI_PORTS[0:4], ret[0:4])
|
||||
|
||||
def test_get_target_iscsi_ports_with_iscsi_and_fc(self):
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
PORTS_DATA = [DotNotation(i) for i in PORTS_WITH]
|
||||
PORTS_DATA = [DotNotation(i) for i in ISCSI_PORTS_WITH]
|
||||
ifc_ports = ValidResponse(200, None, 1, PORTS_DATA, {})
|
||||
self.array.get_ports.return_value = ifc_ports
|
||||
self.array.get_network_interfaces.return_value = ValidResponse(
|
||||
200, None, 1, [DotNotation(INTERFACES[0])], {})
|
||||
ret = self.driver._get_target_iscsi_ports(self.array)
|
||||
self.assertEqual(ISCSI_PORTS, ret)
|
||||
self.assertEqual(ISCSI_PORTS_WITH[0:9], ret[0:9])
|
||||
|
||||
def test_get_target_iscsi_ports_with_no_ports(self):
|
||||
# Should raise an exception if there are no ports
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
no_ports = ValidResponse(200, None, 1, [], {})
|
||||
self.array.get_network_interfaces.return_value = ValidResponse(
|
||||
200, None, 1, [], {})
|
||||
self.array.get_ports.return_value = no_ports
|
||||
self.assertRaises(pure.PureDriverException,
|
||||
self.driver._get_target_iscsi_ports,
|
||||
@ -4770,6 +4853,8 @@ class PureISCSIDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
# Should raise an exception of there are no iscsi ports
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
PORTS_NOISCSI = [DotNotation(i) for i in PORTS_WITHOUT]
|
||||
self.array.get_network_interfaces.return_value = ValidResponse(
|
||||
200, None, 1, [DotNotation(INTERFACES[3])], {})
|
||||
self.array.get_ports.\
|
||||
return_value = ValidResponse(200, None, 1, PORTS_NOISCSI, {})
|
||||
self.assertRaises(pure.PureDriverException,
|
||||
@ -5922,18 +6007,20 @@ class PureNVMEDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
{'name': 'CT0.FC4',
|
||||
'wwn': TARGET_WWN,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN},
|
||||
{'name': 'LACP0',
|
||||
'wwn': None,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN},
|
||||
{'name': 'LACP1',
|
||||
'wwn': None,
|
||||
'iqn': None,
|
||||
'nqn': TARGET_NQN}]
|
||||
interfaces = [
|
||||
{'name': 'ct0.eth4', 'services': ['nvme-tcp']},
|
||||
{'name': 'ct0.eth5', 'services': ['iscsi']},
|
||||
{'name': 'ct0.eth20', 'services': ['nvme-roce']},
|
||||
{'name': 'ct0.fc4', 'services': ['nvme-fc']}
|
||||
]
|
||||
# Test for the nvme-tcp port
|
||||
self.driver.configuration.pure_nvme_transport = "tcp"
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
nvme_interfaces = ValidResponse(200, None, 4,
|
||||
[DotNotation(interfaces[x])
|
||||
[DotNotation(INTERFACES[x])
|
||||
for x in range(4)], {})
|
||||
self.array.get_network_interfaces.return_value = nvme_interfaces
|
||||
nvme_ports = ValidResponse(200, None, 4,
|
||||
@ -5956,17 +6043,37 @@ class PureNVMEDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
# Test for the nvme-roce port
|
||||
self.driver.configuration.pure_nvme_transport = "roce"
|
||||
nvme_roce_interface = ValidResponse(200, None, 1,
|
||||
[DotNotation(interfaces[2])], {})
|
||||
[DotNotation(INTERFACES[2])], {})
|
||||
self.array.get_network_interfaces.return_value = nvme_roce_interface
|
||||
nvme_roce_ports = ValidResponse(200, None, 1,
|
||||
[DotNotation(ports[2])], {})
|
||||
self.array.get_ports.return_value = nvme_roce_ports
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual([ports[2]], ret)
|
||||
self.assertEqual([ports[2]], [ret[0]])
|
||||
# Test for the nvme-roce LACP port
|
||||
self.driver.configuration.pure_nvme_transport = "roce"
|
||||
nvme_roce_interface = ValidResponse(200, None, 1,
|
||||
[DotNotation(INTERFACES[4])], {})
|
||||
self.array.get_network_interfaces.return_value = nvme_roce_interface
|
||||
nvme_roce_ports = ValidResponse(200, None, 1,
|
||||
[DotNotation(ports[4])], {})
|
||||
self.array.get_ports.return_value = nvme_roce_ports
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual([ports[4]], [ret[0]])
|
||||
# Test for the nvme-tcp LACP port
|
||||
self.driver.configuration.pure_nvme_transport = "tcp"
|
||||
nvme_roce_interface = ValidResponse(200, None, 1,
|
||||
[DotNotation(INTERFACES[5])], {})
|
||||
self.array.get_network_interfaces.return_value = nvme_roce_interface
|
||||
nvme_roce_ports = ValidResponse(200, None, 1,
|
||||
[DotNotation(ports[5])], {})
|
||||
self.array.get_ports.return_value = nvme_roce_ports
|
||||
ret = self.driver._get_target_nvme_ports(self.array)
|
||||
self.assertEqual([ports[5]], [ret[0]])
|
||||
# Test for empty dict if only nvme-fc port
|
||||
self.driver.configuration.pure_nvme_transport = "roce"
|
||||
nvme_fc_interface = ValidResponse(200, None, 1,
|
||||
[DotNotation(interfaces[3])], {})
|
||||
[DotNotation(INTERFACES[3])], {})
|
||||
self.array.get_network_interfaces.return_value = nvme_fc_interface
|
||||
nvme_fc_ports = ValidResponse(200, None, 1,
|
||||
[DotNotation(ports[3])], {})
|
||||
@ -5978,7 +6085,9 @@ class PureNVMEDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
# Should raise an exception if there are no ports
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
nvme_no_ports = ValidResponse(200, None, 1, [], {})
|
||||
nvme_no_interfaces = ValidResponse(200, None, 1, [], {})
|
||||
self.array.get_ports.return_value = nvme_no_ports
|
||||
self.array.get_network_interfaces.return_value = nvme_no_interfaces
|
||||
self.assertRaises(
|
||||
pure.PureDriverException,
|
||||
self.driver._get_target_nvme_ports,
|
||||
@ -5988,8 +6097,12 @@ class PureNVMEDriverTestCase(PureBaseSharedDriverTestCase):
|
||||
def test_get_target_nvme_ports_with_only_fc_ports(self):
|
||||
# Should raise an exception of there are no nvme ports
|
||||
self.array.get_controllers.return_value = CTRL_OBJ
|
||||
nvme_noports = ValidResponse(200, None, 1, [PORTS_WITHOUT], {})
|
||||
PORTS_NONVME = [DotNotation(i) for i in PORTS_WITHOUT]
|
||||
nvme_noports = ValidResponse(200, None, 1, PORTS_NONVME, {})
|
||||
nvme_nointerfaces = ValidResponse(200, None, 1,
|
||||
[DotNotation(INTERFACES[3])], {})
|
||||
self.array.get_ports.return_value = nvme_noports
|
||||
self.array.get_network_interfaces.return_value = nvme_nointerfaces
|
||||
self.assertRaises(
|
||||
pure.PureDriverException,
|
||||
self.driver._get_target_nvme_ports,
|
||||
|
@ -3554,6 +3554,18 @@ class PureBaseVolumeDriver(san.SanDriver):
|
||||
ports += list(
|
||||
array.get_ports(filter="name='" + controller + ".*'").items
|
||||
)
|
||||
lacps = list(
|
||||
array.get_network_interfaces(
|
||||
filter="eth.subtype='lacp_bond'"
|
||||
).items
|
||||
)
|
||||
if lacps:
|
||||
for lacp in range(0, len(lacps)):
|
||||
ports += list(
|
||||
array.get_ports(
|
||||
names=[lacps[lacp].name.upper()]
|
||||
).items
|
||||
)
|
||||
return ports
|
||||
|
||||
|
||||
@ -4202,13 +4214,13 @@ class PureNVMEDriver(PureBaseVolumeDriver, driver.BaseVD):
|
||||
valid_nvme_ports = []
|
||||
nvme_ports = [port for port in ports if getattr(port, "nqn", None)]
|
||||
for port in range(0, len(nvme_ports)):
|
||||
if "ETH" in nvme_ports[port].name:
|
||||
port_detail = list(array.get_network_interfaces(
|
||||
names=[nvme_ports[port].name]
|
||||
).items)[0]
|
||||
if port_detail.services[0] == "nvme-" + \
|
||||
self.configuration.pure_nvme_transport:
|
||||
valid_nvme_ports.append(nvme_ports[port])
|
||||
port_detail = list(array.get_network_interfaces(
|
||||
names=[nvme_ports[port].name.lower()]
|
||||
).items)[0]
|
||||
if hasattr(port_detail.eth, "address") and (
|
||||
port_detail.services[0] == "nvme-" +
|
||||
self.configuration.pure_nvme_transport):
|
||||
valid_nvme_ports.append(nvme_ports[port])
|
||||
if not nvme_ports:
|
||||
raise PureDriverException(
|
||||
reason=_("No %(type)s enabled ports on target array.") %
|
||||
|
7
releasenotes/notes/pure_lacp_iscsi-34678bdb98fa6bab.yaml
Normal file
7
releasenotes/notes/pure_lacp_iscsi-34678bdb98fa6bab.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Pure Storage `bug #2101859
|
||||
<https://bugs.launchpad.net/cinder/+bug/2101859>`_: Fixed issue where
|
||||
LACP bonds were not been correctly identified as iSCSI and NVMe
|
||||
targets.
|
Loading…
x
Reference in New Issue
Block a user