From 6c28efdb6275641b476bf532539dbabbd0e8e196 Mon Sep 17 00:00:00 2001 From: Claudiu Belu Date: Fri, 22 May 2026 10:20:31 +0000 Subject: [PATCH] osmorphing: dismount OS on failure Currently, the mounted OS is only dismounted after the entire morphing process. If any exception occurs in between, the OS remains mounted. This may be a problem for minion pools, in which the minions are supposed to remain active after an OS morphing job. --- coriolis/osmorphing/manager.py | 41 ++++++++++++++++------- coriolis/tests/osmorphing/test_manager.py | 2 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/coriolis/osmorphing/manager.py b/coriolis/osmorphing/manager.py index 50493b8a..f8650ae9 100644 --- a/coriolis/osmorphing/manager.py +++ b/coriolis/osmorphing/manager.py @@ -155,6 +155,34 @@ def morph_image(origin_provider, destination_provider, connection_info, osmorphing_info['os_root_dir'] = os_root_dir osmorphing_info['os_root_dev'] = os_root_dev + try: + _morph_image( + origin_provider, destination_provider, connection_info, + osmorphing_info, user_script, event_handler, os_mount_tools, + ) + finally: + event_manager.progress_update("Dismounting OS partitions") + try: + os_mount_tools.dismount_os(os_root_dir) + except Exception as err: + raise exception.CoriolisException( + "Failed to dismount the OS undergoing OSMorphing. This could " + "have been caused by minor FS corruption during the last disk " + "sync. Please ensure that any source-side FS integrity " + "mechanisms (e.g. filesystem quiescing, crash-consistent " + "backups, etc.) are enabled and available for the source " + "machine. If none are available, please try " + "migrating/replicating the source machine while it is powered " + "off. Error was: %s" % str(err)) from err + + +def _morph_image(origin_provider, destination_provider, connection_info, + osmorphing_info, user_script, event_handler, os_mount_tools): + event_manager = events.EventManager(event_handler) + + os_type = osmorphing_info.get('os_type') + os_root_dir = osmorphing_info['os_root_dir'] + os_root_dev = osmorphing_info['os_root_dev'] conn = os_mount_tools.get_connection() environment = os_mount_tools.get_environment() @@ -261,16 +289,3 @@ def morph_image(origin_provider, destination_provider, connection_info, LOG.info("Post packages install") import_os_morphing_tools.post_packages_install(packages_add) - - event_manager.progress_update("Dismounting OS partitions") - try: - os_mount_tools.dismount_os(os_root_dir) - except Exception as err: - raise exception.CoriolisException( - "Failed to dismount the OS undergoing OSMorphing. This could have " - "been caused by minor FS corruption during the last disk sync. " - "Please ensure that any source-side FS integrity mechanisms (e.g. " - "filesystem quiescing, crash-consistent backups, etc.) are " - "enabled and available for the source machine. If none are " - "available, please try migrating/replicating the source machine " - "while it is powered off. Error was: %s" % str(err)) from err diff --git a/coriolis/tests/osmorphing/test_manager.py b/coriolis/tests/osmorphing/test_manager.py index 2012e413..00ade20a 100644 --- a/coriolis/tests/osmorphing/test_manager.py +++ b/coriolis/tests/osmorphing/test_manager.py @@ -230,7 +230,7 @@ def test_morph_image( mock_get_os_mount_tools.assert_called_once_with( 'linux', mock.sentinel.connection_info, self.event_manager, [], 60) - mock_EventManager.assert_called_once_with(self.event_handler) + mock_EventManager.assert_called_with(self.event_handler) self.os_mount_tools.dismount_os.assert_called_once()