virt-v2v/0029-convert-Detect-target-boot-device-for-Linux-guests.patch

79 lines
3.0 KiB
Diff

From 46af95ecd11c9eda5fd4195b62528b1eea214550 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 21 Aug 2025 10:27:41 +0100
Subject: [PATCH] convert: Detect target boot device for Linux guests
If the guest is Linux, try to detect the boot device, so we can set
<boot order='N'> appropriately. We do this for BIOS or UEFI here, but
this only really matters for SeaBIOS.
Suggested-by: Gerd Hoffmann
Fixes: https://issues.redhat.com/browse/RHEL-108991
(cherry picked from commit ca6ec6317e20a633315f783a8ba4ece3c2fc01f2)
---
convert/convert.ml | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/convert/convert.ml b/convert/convert.ml
index f8a35506..728ea5a1 100644
--- a/convert/convert.ml
+++ b/convert/convert.ml
@@ -95,6 +95,10 @@ let rec convert input_disks options source =
let root = Choose_root.choose_root options.root_choice g in
let inspect = Mount_filesystems.mount_filesystems g root in
+ (* Detect boot device. *)
+ message (f_"Detecting the boot device");
+ let target_boot_device = get_target_boot_device g inspect in
+
let mpstats = get_mpstats g in
check_guest_free_space inspect mpstats;
@@ -137,7 +141,7 @@ let rec convert input_disks options source =
(* Create target metadata file. *)
let target_meta = { guestcaps; target_buses; target_nics;
- target_firmware; target_boot_device = None } in
+ target_firmware; target_boot_device } in
(* This is a good place to dump everything we know about the guest. *)
if verbose () then debug_info source inspect target_meta mpstats;
@@ -362,6 +366,37 @@ and get_target_firmware i_firmware guestcaps source output =
target_firmware
+and get_target_boot_device g inspect =
+ (* We only do it for Linux, as most likely Windows never(?) boots
+ * from any drive other than C:. We can revisit this decision
+ * if someone reports a bug.
+ *)
+ match inspect.i_type with
+ | "linux" ->
+ (try
+ (* In sane cases, the Grub stage1/boot.img (ie. the boot sector) is
+ * always on the same drive as /boot. So we can just find out
+ * where /boot is mounted and use that.
+ *)
+ let boot_mountpoint = List.assoc "/boot" inspect.i_mountpoints in
+ let boot_device = g#part_to_dev boot_mountpoint in
+ let boot_device = g#device_index boot_device in
+ Some boot_device
+ with
+ | Not_found -> None
+ | G.Error msg
+ (* Returned by part_to_dev if the /boot mountpoint is not
+ * a partition name.
+ *)
+ when String.find msg "device name is not a partition" >= 0 -> None
+ | G.Error msg
+ (* Returned by device_index if the /boot device is not
+ * a normal drive name (eg. /dev/mdX).
+ *)
+ when String.find msg "device not found" >= 0 -> None
+ )
+ | _ -> None
+
(* After conversion we dump as much information about the guest
* as we can in one place. Note this is only called when verbose
* is enabled.