diff --git a/coriolis/osmorphing/windows.py b/coriolis/osmorphing/windows.py index 8c8f707b..f687d54d 100644 --- a/coriolis/osmorphing/windows.py +++ b/coriolis/osmorphing/windows.py @@ -17,7 +17,6 @@ from coriolis.osmorphing.osdetect import windows as windows_osdetect from coriolis import utils - LOG = logging.getLogger(__name__) WINDOWS_CLIENT_IDENTIFIER = windows_osdetect.WINDOWS_CLIENT_IDENTIFIER @@ -562,23 +561,39 @@ def _compile_static_ip_conf_from_registry(self, key_name): return ips_info - def _check_ips_info(self, nics_info, ips_info): - source_ip_addresses = set() + def _get_static_nics_info(self, nics_info, ips_info): + static_nics_info = [] reg_ip_addresses = set() - for nic in nics_info: - source_ip_addresses.update(nic.get('ip_addresses', [])) for ip_info in ips_info: if ip_info.get('ip_address'): reg_ip_addresses.add(ip_info['ip_address']) - diff = source_ip_addresses - reg_ip_addresses - if diff: - raise exception.OSMorphingException( - "The following IP(s): %s found on the source VM's NICs were " - "not found in the registry. Please check whether the static " - "IP configurations on the source machine are properly set up " - "and retry the migration." % diff) + for nic in nics_info: + static_nic = copy.deepcopy(nic) + nic_ips = nic.get('ip_addresses', []) + if not nic_ips: + LOG.warning( + f"Skipping NIC ('{nic.get('mac_address')}'). It has no " + f"detected IP addresses") + continue + diff = set(nic_ips) - reg_ip_addresses + if diff: + LOG.warning( + f"The IP addresses {list(diff)} found on the source " + f"VM's NIC were not found in the registry. These IPs will " + f"be skipped in the static IP configuration process") + ip_matches = list(reg_ip_addresses.intersection(set(nic_ips))) + if not ip_matches: + LOG.warning( + f"Couldn't find any static IP configuration that " + f"matches the addresses {list(nic_ips)} of the source " + f"NIC ({nic.get('mac_address')}). Skipping") + continue + static_nic['ip_addresses'] = ip_matches + static_nics_info.append(static_nic) + + return static_nics_info def _write_static_ip_script(self, base_dir, nics_info, ips_info): scripts_dir = self._get_cbslinit_scripts_dir(base_dir) @@ -601,9 +616,16 @@ def set_net_config(self, nics_info, dhcp): try: cbslinit_base_dir = self._get_cbslinit_base_dir() ips_info = self._compile_static_ip_conf_from_registry(key_name) - self._check_ips_info(nics_info, ips_info) - self._write_static_ip_script( - cbslinit_base_dir, nics_info, ips_info) + LOG.debug(f"Registry static IP configuration: {ips_info}") + static_nics_info = self._get_static_nics_info(nics_info, ips_info) + LOG.debug(f"Detected static NICS info: {static_nics_info}") + if static_nics_info: + self._write_static_ip_script( + cbslinit_base_dir, static_nics_info, ips_info) + else: + LOG.warning( + "No static IP configuration found on the source VM. " + "Static IP configuration will be skipped.") finally: self._unload_registry_hive("HKLM\\%s" % key_name) diff --git a/coriolis/tests/osmorphing/test_windows.py b/coriolis/tests/osmorphing/test_windows.py index a83cc7af..fa6da5fe 100644 --- a/coriolis/tests/osmorphing/test_windows.py +++ b/coriolis/tests/osmorphing/test_windows.py @@ -735,27 +735,32 @@ def test_compile_static_ip_conf_from_registry_no_static_ip(self): interfaces_reg_path), ]) - def test_check_ips_info(self): + def test__get_static_nics_info(self): + # detected static IPs + ips_info = [{"ip_address": "10.0.0.16"}, + {"ip_address": "fe80::728a:688:1a92:baec"}] nics_info = [ - {'ip_addresses': [mock.sentinel.ip_address]} - ] - ips_info = [ - {'ip_address': mock.sentinel.ip_address} - ] - self.morphing_tools._check_ips_info(nics_info, ips_info) - - def test_check_ips_info_different_ips(self): - nics_info = [ - {'ip_addresses': [ - mock.sentinel.ip_address, mock.sentinel.ip_address2]} - ] - ips_info = [ - {'ip_address': mock.sentinel.ip_address} - ] + # no IP addresses on NIC + {"ip_addresses": [], "mac_address": "00:50:56:92:91:42"}, + # dynamic ipv6 IP + {"ip_addresses": ["10.0.0.16", "fe81::728a:688:1a92:baec"], + "mac_address": "00:50:56:92:91:43"}, + # both IPs dynamic + {"ip_addresses": ["10.0.1.16", "fe81::728a:688:1a92:baec"], + "mac_address": "00:50:56:92:91:44"}, + # dynamic ipv4 IP + {"ip_addresses": ["10.0.1.17", "fe80::728a:688:1a92:baec"], + "mac_address": "00:50:56:92:91:45"}] + + expected_result = [ + {"mac_address": "00:50:56:92:91:43", + "ip_addresses": ["10.0.0.16"]}, + {"mac_address": "00:50:56:92:91:45", + "ip_addresses": ["fe80::728a:688:1a92:baec"]}] - self.assertRaises(exception.OSMorphingException, - self.morphing_tools._check_ips_info, - nics_info, ips_info) + self.assertEqual( + self.morphing_tools._get_static_nics_info(nics_info, ips_info), + expected_result) @mock.patch.object(windows.utils, 'write_winrm_file') def test__write_static_ip_script(self, mock_write_winrm_file): @@ -786,6 +791,8 @@ def test__write_static_ip_script(self, mock_write_winrm_file): @mock.patch.object( windows.BaseWindowsMorphingTools, '_write_static_ip_script' ) + @mock.patch.object( + windows.BaseWindowsMorphingTools, '_get_static_nics_info') @mock.patch.object( windows.BaseWindowsMorphingTools, '_unload_registry_hive' ) @@ -795,6 +802,7 @@ def test__write_static_ip_script(self, mock_write_winrm_file): @mock.patch.object(windows.uuid, 'uuid4') def test_set_net_config(self, mock_uuid4, mock_load_registry_hive, mock_unload_registry_hive, + mock_get_static_nics_info, mock_write_static_ip_script, mock_compile_static_ip_conf_from_registry): dhcp = False @@ -813,13 +821,57 @@ def test_set_net_config(self, mock_uuid4, mock_load_registry_hive, "%sWindows\\System32\\config\\SYSTEM" % self.os_root_dir) mock_compile_static_ip_conf_from_registry.assert_called_once_with( str(mock_uuid4.return_value)) + mock_get_static_nics_info.assert_called_once_with(nics_info, ips_info) mock_write_static_ip_script.assert_called_once_with( "C:\\Cloudbase-Init", - nics_info, + mock_get_static_nics_info.return_value, mock_compile_static_ip_conf_from_registry.return_value) mock_unload_registry_hive.assert_called_once_with( "HKLM\\%s" % mock_uuid4.return_value) + @mock.patch.object( + windows.BaseWindowsMorphingTools, + '_compile_static_ip_conf_from_registry' + ) + @mock.patch.object( + windows.BaseWindowsMorphingTools, '_write_static_ip_script' + ) + @mock.patch.object( + windows.BaseWindowsMorphingTools, '_get_static_nics_info') + @mock.patch.object( + windows.BaseWindowsMorphingTools, '_unload_registry_hive' + ) + @mock.patch.object( + windows.BaseWindowsMorphingTools, '_load_registry_hive' + ) + @mock.patch.object(windows.uuid, 'uuid4') + def test_set_net_config_no_static_info( + self, mock_uuid4, mock_load_registry_hive, + mock_unload_registry_hive, mock_get_static_nics_info, + mock_write_static_ip_script, + mock_compile_static_ip_conf_from_registry): + dhcp = False + nics_info = [ + {'ip_addresses': ["10.1.10.10"]} + ] + ips_info = [ + {'ip_address': "10.1.10.10"} + ] + mock_compile_static_ip_conf_from_registry.return_value = ips_info + mock_get_static_nics_info.return_value = [] + + self.morphing_tools.set_net_config(nics_info, dhcp=dhcp) + + mock_load_registry_hive.assert_called_once_with( + "HKLM\\%s" % mock_uuid4.return_value, + "%sWindows\\System32\\config\\SYSTEM" % self.os_root_dir) + mock_compile_static_ip_conf_from_registry.assert_called_once_with( + str(mock_uuid4.return_value)) + mock_get_static_nics_info.assert_called_once_with(nics_info, ips_info) + mock_write_static_ip_script.assert_not_called() + mock_unload_registry_hive.assert_called_once_with( + "HKLM\\%s" % mock_uuid4.return_value) + @mock.patch.object( windows.BaseWindowsMorphingTools, '_get_cbslinit_base_dir' ) @@ -836,7 +888,8 @@ def test_set_net_config(self, mock_uuid4, mock_load_registry_hive, @mock.patch.object( windows.BaseWindowsMorphingTools, '_load_registry_hive' ) - @mock.patch.object(windows.BaseWindowsMorphingTools, '_check_ips_info') + @mock.patch.object(windows.BaseWindowsMorphingTools, + '_get_static_nics_info') def test_set_net_config_with_dhcp( self, mock_check_ips_info, mock_load_registry_hive, mock_unload_registry_hive, mock_write_static_ip_script,