From 7adcf74c25730f7a4d77f7d9faf3aa741441f00b Mon Sep 17 00:00:00 2001 From: Daniel Vincze Date: Wed, 9 Jun 2021 13:10:45 +0300 Subject: [PATCH] Reorder root disk as first disk in OSMorphing stage --- coriolis/osmorphing/osmount/windows.py | 8 +++- coriolis/tasks/osmorphing_tasks.py | 65 ++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/coriolis/osmorphing/osmount/windows.py b/coriolis/osmorphing/osmount/windows.py index 93882aaae..0e7f6688c 100644 --- a/coriolis/osmorphing/osmount/windows.py +++ b/coriolis/osmorphing/osmount/windows.py @@ -213,7 +213,13 @@ def mount_os(self): for fs_root in [r for r in fs_roots if not r[:-1] == system_drive]: if self._conn.test_path("%sWindows\\System32" % fs_root): - return fs_root, None + root_disk_id = None + root_disk_ids = self._get_disk_ids_from_drive_letters( + [fs_root.split(':')[0]]) + if root_disk_ids: + root_disk_id = root_disk_ids[0] + + return fs_root, root_disk_id raise exception.OperatingSystemNotFound("root partition not found") diff --git a/coriolis/tasks/osmorphing_tasks.py b/coriolis/tasks/osmorphing_tasks.py index 7e6aafc41..89b7dc33e 100644 --- a/coriolis/tasks/osmorphing_tasks.py +++ b/coriolis/tasks/osmorphing_tasks.py @@ -1,6 +1,8 @@ # Copyright 2016 Cloudbase Solutions Srl # All Rights Reserved. +import re + from oslo_log import log as logging from coriolis import constants @@ -14,6 +16,55 @@ LOG = logging.getLogger(__name__) +def _reorder_root_disk(volumes_info, root_device, os_type): + """ + Reorders volumes_info so that the root disk will always be the first volume + + root_device is returned by the OSMount Tools as the root partition device + (i.e. /dev/vdd2 for linux). + + For Linux, we need to strip the trailing digits + to get the actual disk device. After that, we convert the last letter of + the disk device name into the equivalent index by alphabetical order. + + Windows OSMount Tools should directly return the root disk index extracted + from diskpart (as string; i.e. '1'). + + Reordering is done by swapping the indexes of the volumes_info list. + """ + if not root_device: + LOG.warn('os_root_dev was not returned by OSMount Tools. ' + 'Skipping root disk reordering') + return + + # the default disk device of the migrated VM should be /dev/Xdb, because + # /dev/Xda should be the worker's root disk. Same for Windows: Disk 0 + # should be the worker's root disk, and Disk 1 the migrated VM's root disk + linux_root_default = 'b' + windows_root_default = 1 + + supported_os_types = [constants.OS_TYPE_LINUX, constants.OS_TYPE_WINDOWS] + if os_type == constants.OS_TYPE_LINUX: + pattern = r'[0-9]' + root_disk = re.sub(pattern, '', root_device) + disk_index = ord(root_disk[-1]) - ord(linux_root_default) + elif os_type == constants.OS_TYPE_WINDOWS: + disk_index = int(root_device) - windows_root_default + else: + LOG.warn('Root disk reordering only supported for %s. Got OS type: %s.' + 'Skipping root disk reordering', supported_os_types, os_type) + return + + if disk_index > 0: + if disk_index < len(volumes_info): + volumes_info[0], volumes_info[disk_index] = ( + volumes_info[disk_index], volumes_info[0]) + else: + LOG.warn('Disk device name index out of range: %s for device %s' + 'Skipping root disk reordering', disk_index, root_device) + + + class OSMorphingTask(base.TaskRunner): @classmethod @@ -28,7 +79,7 @@ def get_required_task_info_properties(cls): @classmethod def get_returned_task_info_properties(cls): - return [] + return ["instance_deployment_info"] @classmethod def get_required_provider_types(cls): @@ -53,13 +104,14 @@ def _run(self, ctxt, instance, origin, destination, task_info, osmorphing_connection_info = base.unmarshal_migr_conn_info( task_info['osmorphing_connection_info']) osmorphing_info = task_info.get('osmorphing_info', {}) + instance_deployment_info = task_info.get('instance_deployment_info', {}) user_scripts = task_info.get("user_scripts") + os_type = osmorphing_info.get("os_type") instance_script = None if user_scripts: instance_script = user_scripts.get("instances", {}).get(instance) if not instance_script: - os_type = osmorphing_info.get("os_type") if os_type: instance_script = user_scripts.get( "global", {}).get(os_type) @@ -72,7 +124,14 @@ def _run(self, ctxt, instance, origin, destination, task_info, instance_script, event_handler) - return {} + volumes_info = instance_deployment_info.get('volumes_info', []) + LOG.debug('Volumes info before root disk reordering: %s', volumes_info) + _reorder_root_disk(volumes_info, osmorphing_info.get('os_root_dev'), + os_type) + LOG.debug('Volumes info after root disk reordering: %s', volumes_info) + + return { + 'instance_deployment_info': instance_deployment_info} class DeployOSMorphingResourcesTask(base.TaskRunner):