enable_vlan_interfaces: support identifying interfaces by MAC

The enable_vlan_interfaces config option supports a comma-separated list
of <interface>.<vlan> pairs. However, using this relies on knowledge of
the interface name. When used via the ipa-enable-vlan-interfaces kernel
command-line parameter, an interface name may be hard to predict.

As an alternative to identifying interfaces by name, support identifying
them by MAC.

Change-Id: Ice822a8e7b8d82352b3b39f87d930bef3eb7b461
Signed-off-by: Jonathan Davies <jonathan.davies@nutanix.com>
This commit is contained in:
Jonathan Davies
2025-07-17 18:05:34 +01:00
parent c2c72eef97
commit f596fe4701
4 changed files with 68 additions and 6 deletions

View File

@@ -318,7 +318,9 @@ cli_opts = [
cfg.StrOpt('enable_vlan_interfaces',
default=APARAMS.get('ipa-enable-vlan-interfaces', ''),
help='Comma-separated list of VLAN interfaces to enable, '
'in the format "interface.vlan". If only an '
'in the format "interface.vlan". The "interface" can be '
'an interface name or a MAC address (EUI-48 format, '
'case-insensitive). If only an '
'interface is provided, then IPA should attempt to '
'bring up all VLANs on that interface detected '
'via lldp. If "all" is set then IPA should attempt '

View File

@@ -420,11 +420,14 @@ def bring_up_vlan_interfaces(interfaces_list):
if '.' in vlan_int:
# interface and vlan are provided
interface, vlan = vlan_int.split('.', 1)
if any(x.name == interface for x in interfaces_list):
name = _add_vlan_interface(interface, vlan,
interfaces_list)
if name:
interfaces.append(name)
for x in interfaces_list:
if (x.name == interface
or x.mac_address.lower() == interface.lower()):
name = _add_vlan_interface(x.name, vlan,
interfaces_list)
if name:
interfaces.append(name)
break
else:
LOG.warning('Provided VLAN interface %s does not exist',
interface)

View File

@@ -6901,6 +6901,58 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
self.assertEqual('00:0c:29:8c:11:b1', interfaces[1].mac_address)
self.assertIsNone(interfaces[1].lldp)
def test_list_network_vlan_interfaces_mac(self,
mock_has_carrier,
mocked_execute,
mocked_open,
mocked_exists,
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('enable_vlan_interfaces', '00:0c:29:8c:11:b1.100')
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
mocked_open.return_value.__enter__ = lambda s: s
mocked_open.return_value.__exit__ = mock.Mock()
read_mock = mocked_open.return_value.read
read_mock.side_effect = ['1']
mocked_net_if_addrs.return_value = {
'lo': [
FakeAddr(socket.AF_INET, '127.0.0.1'),
FakeAddr(socket.AF_INET6, '::1'),
FakeAddr(socket.AF_PACKET, '00:00:00:00:00:00')
],
'eth0': [
FakeAddr(socket.AF_INET, '192.168.1.2'),
FakeAddr(socket.AF_INET6, 'fd00::101'),
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
],
'eth0.100': [
FakeAddr(socket.AF_INET, '192.168.2.2'),
FakeAddr(socket.AF_INET6, 'fd00::1000::101'),
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
'eth0.100': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
self.assertEqual(2, len(interfaces))
self.assertEqual('eth0', interfaces[0].name)
self.assertEqual('00:0c:29:8c:11:b1', interfaces[0].mac_address)
self.assertEqual('192.168.1.2', interfaces[0].ipv4_address)
self.assertEqual('fd00::101', interfaces[0].ipv6_address)
self.assertIsNone(interfaces[0].lldp)
self.assertEqual('eth0.100', interfaces[1].name)
self.assertEqual('00:0c:29:8c:11:b1', interfaces[1].mac_address)
self.assertIsNone(interfaces[1].lldp)
@mock.patch.object(netutils, 'get_lldp_info', autospec=True)
def test_list_network_vlan_interfaces_using_lldp(self,
mocked_lldp_info,

View File

@@ -0,0 +1,5 @@
---
features:
- |
Extend ``ipa-enable-vlan-interfaces`` kernel params field to support
identifying an interface by its MAC address as an alternative to its name.