diff --git a/coriolis/osmorphing/base.py b/coriolis/osmorphing/base.py index 4b55915c..6e9ea0f5 100644 --- a/coriolis/osmorphing/base.py +++ b/coriolis/osmorphing/base.py @@ -1149,6 +1149,14 @@ def _setup_network_preservation(self, nics_info) -> None: break if ip_addresses and nic_ips: if set(ip_addresses) & set(nic_ips): + # A ':' in the name marks an address label on the parent + # device. udev can only rename the parent. + if ":" in iface: + LOG.info( + "Skipping IP alias interface '%s' for the udev rule.", + iface, + ) + continue LOG.info( "Found matching interface for NIC '%s' " "with new MAC '%s', identified by IP.", diff --git a/coriolis/tests/osmorphing/test_base.py b/coriolis/tests/osmorphing/test_base.py index 7d5b2d9f..f49de881 100644 --- a/coriolis/tests/osmorphing/test_base.py +++ b/coriolis/tests/osmorphing/test_base.py @@ -2085,6 +2085,50 @@ def test__add_net_udev_rules(self, mock_write_file_sudo, mock_test_path): "eth0": "ff:aa:11:22:33:44", }, ), + # An ifcfg IP alias is listed before the parent and its address is on + # the source NIC. The alias name must be ignored; the parent is used. + ( + [ + { + "name": "Network adapter 1", + "mac_address": "00:50:56:8e:74:51", + "ip_addresses": ["10.203.180.156", "10.203.181.192"], + }, + ], + { + "ens192:SAB": { + "mac_address": None, + "ip_addresses": ["10.203.181.192"], + }, + "ens192": { + "mac_address": "00:50:56:8e:74:51", + "ip_addresses": ["10.203.180.156"], + }, + }, + {"ens192": "00:50:56:8e:74:51"}, + ), + # Same layout when the guest ifcfg files have no HWADDR. The IP match + # must still select the name without ':'. + ( + [ + { + "name": "Network adapter 1", + "mac_address": "00:50:56:8e:74:51", + "ip_addresses": ["10.203.180.156", "10.203.181.192"], + }, + ], + { + "ens192:SAB": { + "mac_address": None, + "ip_addresses": ["10.203.181.192"], + }, + "ens192": { + "mac_address": None, + "ip_addresses": ["10.203.180.156"], + }, + }, + {"ens192": "00:50:56:8e:74:51"}, + ), ) @ddt.unpack def test__setup_network_preservation(