Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions coriolis/osmorphing/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,9 @@ def _setup_network_preservation(self, nics_info) -> None:

for nic in nics_info:
nic_mac = nic.get('mac_address')
new_nic_mac = nic.get('new_mac_address') or nic_mac
if new_nic_mac != nic_mac:
LOG.info("MAC address changed: %s -> %s", nic_mac, new_nic_mac)
nic_ips = nic.get('ip_addresses')
if not nic_mac:
LOG.warning(
Expand All @@ -1020,22 +1023,37 @@ def _setup_network_preservation(self, nics_info) -> None:
mac_address = info.get('mac_address')
ip_addresses = info.get('ip_addresses', [])
if mac_address and mac_address == nic_mac:
if new_nic_mac != nic_mac:
raise exception.CoriolisException(
"The NIC '%s' configuration explicitly targets "
"MAC '%s', however its MAC changed to '%s'. "
"Coriolis defines udev rules for preserving the "
"interface name, mapping it to the new MAC "
"address but DOES NOT modify Linux network "
"configuration files. Depending on the target "
"platform capabilities, consider using DHCP, "
"enabling MAC address preservation or removing "
"the explicit MAC filter from the NIC "
"configuration."
% (nic.get('name'), nic_mac, new_nic_mac))
LOG.info(
"Found matching interface for NIC '%s' with MAC '%s'",
"Found matching interface for NIC '%s' with MAC '%s'.",
nic.get('name'), nic_mac)
matching_ifaces[iface] = nic_mac
break
if ip_addresses and nic_ips:
if set(ip_addresses) & set(nic_ips):
LOG.info(
"Found matching interface for NIC '%s' with MAC "
"'%s'", nic.get('name'), nic_mac)
matching_ifaces[iface] = nic_mac
"Found matching interface for NIC '%s' "
"with new MAC '%s', identified by IP.",
nic.get('name'), new_nic_mac)
matching_ifaces[iface] = new_nic_mac
break
if not matching_ifaces:
LOG.warning(
"Could not find a matching guest interface for NIC '%s' "
"with MAC address '%s'", nic, nic_mac)
"with MAC address '%s' (old MAC address: %s)",
nic, new_nic_mac, nic_mac)
net_ifaces_info.update(matching_ifaces)

self._add_net_udev_rules(net_ifaces_info)
Expand Down
12 changes: 12 additions & 0 deletions coriolis/osmorphing/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,20 @@ def _get_static_nics_info(self, nics_info, ips_info):
def _write_static_ip_script(self, base_dir, nics_info, ips_info):
scripts_dir = self._get_cbslinit_scripts_dir(base_dir)
script_path = "%s\\01-static-ip-config.ps1" % scripts_dir

nics_info = copy.deepcopy(nics_info)
for nic in nics_info:
# The static ip configuration script only requires the new
# MAC address.
if nic.get("new_mac_address"):
LOG.info(
"Updated mac address: %s -> %s",
nic["mac_address"], nic["new_mac_address"])
nic["mac_address"] = nic["new_mac_address"]

nics_info_dump = json.dumps(nics_info)
ips_info_dump = json.dumps(ips_info)

contents = STATIC_IP_SCRIPT_TEMPLATE % {
'nics_info': base64.b64encode(nics_info_dump.encode()).decode(),
'ips_info': base64.b64encode(ips_info_dump.encode()).decode()}
Expand Down
57 changes: 49 additions & 8 deletions coriolis/tests/osmorphing/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,38 @@ def test__add_net_udev_rules(self, mock_write_file_sudo, mock_test_path):
"eth2": "FF:FF:FF:FF:FF:FF",
}
),
# MAC changed but the network config contains an explicit MAC
# assignment. An exception is expected since Coriolis cannot
# modify Linux network config files at the moment.
(
[
{"mac_address": "00:11:22:33:44:55",
"new_mac_address": "ff:aa:11:22:33:44",
"ip_addresses": ["192.168.1.10"]},
],
{
"eth0": {"mac_address": "00:11:22:33:44:55",
"ip_addresses": []},
},
exception.CoriolisException,
),
# The MAC address changed but the network config files did not
# contain explicit MAC assignments, we can rely on the udev rules
# that preserve the interface names. The new MAC will be returned.
(
[
{"mac_address": "00:11:22:33:44:55",
"new_mac_address": "ff:aa:11:22:33:44",
"ip_addresses": ["192.168.1.10"]},
],
{
"eth0": {"mac_address": None,
"ip_addresses": ["192.168.1.10"]},
},
{
"eth0": "ff:aa:11:22:33:44",
}
),
)
@ddt.unpack
def test__setup_network_preservation(
Expand All @@ -1912,13 +1944,22 @@ def parse_network(self):

self.os_morphing_tools._add_net_udev_rules = mock.MagicMock()

with self.assertLogs(
'coriolis.osmorphing.base', level=logging.INFO):
self.os_morphing_tools._setup_network_preservation(nics_info)
if isinstance(expected_net_ifaces, type) and issubclass(
expected_net_ifaces, Exception):
self.assertRaises(
expected_net_ifaces,
self.os_morphing_tools._setup_network_preservation,
nics_info,
)
else:
with self.assertLogs(
'coriolis.osmorphing.base', level=logging.INFO):
self.os_morphing_tools._setup_network_preservation(
nics_info)

result_net_ifaces = dict(
self.os_morphing_tools._add_net_udev_rules.call_args[0][0])
result_net_ifaces = dict(
self.os_morphing_tools._add_net_udev_rules.call_args[0][0])

mock_get_np.assert_called_once_with(self.os_morphing_tools)
self.os_morphing_tools._add_net_udev_rules.assert_called_once()
self.assertEqual(expected_net_ifaces, result_net_ifaces)
mock_get_np.assert_called_once_with(self.os_morphing_tools)
self.os_morphing_tools._add_net_udev_rules.assert_called_once()
self.assertEqual(expected_net_ifaces, result_net_ifaces)
Loading