Set boot order for Linux guests based on grub location
resolves: RHEL-108991
This commit is contained in:
parent
8f140b28fb
commit
c6d4be1cf0
98
0027-convert-Model-target-boot-device.patch
Normal file
98
0027-convert-Model-target-boot-device.patch
Normal file
@ -0,0 +1,98 @@
|
||||
From c00234c61eb2a49b2961b24672e41f15d8d734b8 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Thu, 21 Aug 2025 09:45:44 +0100
|
||||
Subject: [PATCH] convert: Model target boot device
|
||||
|
||||
SeaBIOS recently changed how it works so it no longer initializes all
|
||||
disks at boot. To get around this, for some Linux BIOS guests, we
|
||||
will have to assign a boot order to the disks, with <boot order='1'>
|
||||
for the disk that contains the GRUB bootloader, and higher boot orders
|
||||
assigned to the other disks.
|
||||
|
||||
As the first step, model the target boot device.
|
||||
|
||||
In the current commit this is always unset (set to 'None'), so this
|
||||
does nothing.
|
||||
|
||||
(cherry picked from commit e512d84bc8e18734aac7659e839f32c960f6fb0a)
|
||||
---
|
||||
convert/convert.ml | 8 ++++++--
|
||||
lib/types.ml | 3 ++-
|
||||
lib/types.mli | 15 ++++++++++++++-
|
||||
3 files changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/convert/convert.ml b/convert/convert.ml
|
||||
index 45d48a95..f8a35506 100644
|
||||
--- a/convert/convert.ml
|
||||
+++ b/convert/convert.ml
|
||||
@@ -136,7 +136,8 @@ let rec convert input_disks options source =
|
||||
get_target_firmware i_firmware guestcaps source output in
|
||||
|
||||
(* Create target metadata file. *)
|
||||
- let target_meta = { guestcaps; target_buses; target_firmware; target_nics } in
|
||||
+ let target_meta = { guestcaps; target_buses; target_nics;
|
||||
+ target_firmware; target_boot_device = None } in
|
||||
|
||||
(* This is a good place to dump everything we know about the guest. *)
|
||||
if verbose () then debug_info source inspect target_meta mpstats;
|
||||
@@ -366,7 +367,8 @@ and get_target_firmware i_firmware guestcaps source output =
|
||||
* is enabled.
|
||||
*)
|
||||
and debug_info source inspect
|
||||
- { guestcaps; target_buses; target_firmware; target_nics }
|
||||
+ { guestcaps; target_buses; target_nics;
|
||||
+ target_firmware; target_boot_device }
|
||||
mpstats =
|
||||
eprintf "info:\n";
|
||||
eprintf "%s\n" (string_of_source source);
|
||||
@@ -374,6 +376,8 @@ and debug_info source inspect
|
||||
eprintf "%s\n" (string_of_guestcaps guestcaps);
|
||||
eprintf "%s\n" (string_of_target_buses target_buses);
|
||||
eprintf "target firmware: %s\n" (string_of_target_firmware target_firmware);
|
||||
+ eprintf "target boot device: %s\n"
|
||||
+ (match target_boot_device with None -> "" | Some i -> string_of_int i);
|
||||
eprintf "target NICs:\n";
|
||||
List.iter (fun nic -> eprintf "%s\n" (string_of_source_nic nic))
|
||||
target_nics;
|
||||
diff --git a/lib/types.ml b/lib/types.ml
|
||||
index 0196a3fd..bd4ab31c 100644
|
||||
--- a/lib/types.ml
|
||||
+++ b/lib/types.ml
|
||||
@@ -485,8 +485,9 @@ let string_of_target_buses buses =
|
||||
type target_meta = {
|
||||
guestcaps : guestcaps;
|
||||
target_buses : target_buses;
|
||||
+ target_nics : target_nics;
|
||||
target_firmware : target_firmware;
|
||||
- target_nics : target_nics
|
||||
+ target_boot_device : int option;
|
||||
}
|
||||
|
||||
type root_choice = AskRoot | SingleRoot | FirstRoot | RootDev of string
|
||||
diff --git a/lib/types.mli b/lib/types.mli
|
||||
index b3815c8e..0c43b149 100644
|
||||
--- a/lib/types.mli
|
||||
+++ b/lib/types.mli
|
||||
@@ -367,8 +367,21 @@ val string_of_target_buses : target_buses -> string
|
||||
type target_meta = {
|
||||
guestcaps : guestcaps;
|
||||
target_buses : target_buses;
|
||||
+ target_nics : target_nics;
|
||||
+
|
||||
target_firmware : target_firmware;
|
||||
- target_nics : target_nics
|
||||
+
|
||||
+ target_boot_device : int option;
|
||||
+ (** The disk index of the device containing the bootloader (index
|
||||
+ starting from 0).
|
||||
+
|
||||
+ For libvirt guests this should usually be mapped to
|
||||
+ [<boot order='1'>] for this disk, and [<boot order='N'>]
|
||||
+ where N > 1 for each other disk (order does not matter
|
||||
+ for the other disks).
|
||||
+
|
||||
+ This is only necessary for SeaBIOS so only collected for
|
||||
+ a subset of BIOS guests (RHEL-108991). *)
|
||||
}
|
||||
|
||||
(** {2 Command line parameters} *)
|
||||
184
0028-output-Add-boot-order-depending-on-target-boot-devic.patch
Normal file
184
0028-output-Add-boot-order-depending-on-target-boot-devic.patch
Normal file
@ -0,0 +1,184 @@
|
||||
From e7abf2e39ed17e324b54c00f2386f56152660522 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Thu, 21 Aug 2025 09:53:42 +0100
|
||||
Subject: [PATCH] output: Add boot order depending on target boot device
|
||||
|
||||
If no target boot device was specified, we number them <boot order='1'>
|
||||
through <boot order='N'> for each disk.
|
||||
|
||||
If a target boot device was specified, then that disk has
|
||||
<boot order='1'>, and the remaining disks are numbered sequentially
|
||||
starting at 2.
|
||||
|
||||
(cherry picked from commit 08e57a392aa5e0720e8787968a562808cb0a31fe)
|
||||
---
|
||||
lib/create_ovf.ml | 19 ++++++++-----------
|
||||
output/create_libvirt_xml.ml | 16 +++++++++++++++-
|
||||
output/output_qemu.ml | 16 +++++++++++++---
|
||||
tests/test-cdrom.expected | 1 +
|
||||
tests/test-floppy.expected | 1 +
|
||||
tests/test-i-ova.xml | 1 +
|
||||
6 files changed, 39 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/lib/create_ovf.ml b/lib/create_ovf.ml
|
||||
index 0af62c88..f74ba3a7 100644
|
||||
--- a/lib/create_ovf.ml
|
||||
+++ b/lib/create_ovf.ml
|
||||
@@ -544,7 +544,7 @@ let create_meta_files output_alloc output_format sd_uuid image_uuids sizes =
|
||||
|
||||
(* Create the OVF file. *)
|
||||
let rec create_ovf source inspect
|
||||
- { guestcaps; target_firmware; target_nics }
|
||||
+ { guestcaps; target_nics; target_firmware; target_boot_device }
|
||||
sizes
|
||||
output_alloc output_format
|
||||
output_name
|
||||
@@ -763,7 +763,7 @@ let rec create_ovf source inspect
|
||||
] in
|
||||
|
||||
(* Add disks to the OVF XML. *)
|
||||
- add_disks sizes guestcaps output_alloc output_format
|
||||
+ add_disks sizes guestcaps target_boot_device output_alloc output_format
|
||||
sd_uuid image_uuids vol_uuids need_actual_sizes output_disks
|
||||
ovf_flavour ovf;
|
||||
|
||||
@@ -813,7 +813,7 @@ and get_flavoured_section ovf ovirt_path esd_path esd_path_attr = function
|
||||
with Not_found -> assert false
|
||||
|
||||
(* This modifies the OVF DOM, adding a section for each disk. *)
|
||||
-and add_disks sizes guestcaps output_alloc output_format
|
||||
+and add_disks sizes guestcaps target_boot_device output_alloc output_format
|
||||
sd_uuid image_uuids vol_uuids need_actual_sizes output_disks
|
||||
ovf_flavour ovf =
|
||||
let references =
|
||||
@@ -838,14 +838,11 @@ and add_disks sizes guestcaps output_alloc output_format
|
||||
(* Iterate over the disks, adding them to the OVF document. *)
|
||||
List.iteri (
|
||||
fun i (size, image_uuid, vol_uuid, output_uri) ->
|
||||
- (* This sets the boot order to boot the first disk first. This
|
||||
- * isn't generally correct. We should copy over the boot order
|
||||
- * from the source hypervisor. See long discussion in
|
||||
- * https://bugzilla.redhat.com/show_bug.cgi?id=1308535 for
|
||||
- * what we should be doing. (XXX)
|
||||
- *)
|
||||
- let is_bootable_drive = i == 0 in
|
||||
- let boot_order = i+1 in
|
||||
+ let is_bootable_drive, boot_order =
|
||||
+ match target_boot_device with
|
||||
+ | None -> i = 0, i+1
|
||||
+ | Some disk_index when disk_index = i -> true, 1
|
||||
+ | Some _ -> false, i+2 in
|
||||
|
||||
let fileref =
|
||||
match ovf_flavour with
|
||||
diff --git a/output/create_libvirt_xml.ml b/output/create_libvirt_xml.ml
|
||||
index 7ab8d34c..59f2f1f8 100644
|
||||
--- a/output/create_libvirt_xml.ml
|
||||
+++ b/output/create_libvirt_xml.ml
|
||||
@@ -41,7 +41,8 @@ let get_osinfo_id inspect =
|
||||
None
|
||||
|
||||
let create_libvirt_xml ?pool source inspect
|
||||
- { guestcaps; target_buses; target_firmware; target_nics }
|
||||
+ { guestcaps; target_buses; target_nics; target_firmware;
|
||||
+ target_boot_device }
|
||||
target_features outdisk_name output_format output_name =
|
||||
(* The main body of the libvirt XML document. *)
|
||||
let body = ref [] in
|
||||
@@ -206,6 +207,18 @@ let create_libvirt_xml ?pool source inspect
|
||||
| BusSlotDisk d ->
|
||||
let outdisk = outdisk_name d.s_disk_id in
|
||||
|
||||
+ let boot_order =
|
||||
+ match target_boot_device with
|
||||
+ | None ->
|
||||
+ (* No known boot device, just number them sequentially. *)
|
||||
+ i+1
|
||||
+ | Some disk_index when disk_index = i ->
|
||||
+ (* For the boot disk, use order 1. *)
|
||||
+ 1
|
||||
+ | Some _ ->
|
||||
+ (* For the others number them sequentially starting at 2. *)
|
||||
+ i+2 in
|
||||
+
|
||||
e "disk" (
|
||||
[
|
||||
"type", if pool = None then "file" else "volume";
|
||||
@@ -231,6 +244,7 @@ let create_libvirt_xml ?pool source inspect
|
||||
"dev", drive_prefix ^ drive_name i;
|
||||
"bus", bus_name;
|
||||
] [];
|
||||
+ e "boot" [ "order", string_of_int boot_order ] [];
|
||||
]
|
||||
|
||||
| BusSlotRemovable { s_removable_type = CDROM } ->
|
||||
diff --git a/output/output_qemu.ml b/output/output_qemu.ml
|
||||
index 37371aad..dff08b66 100644
|
||||
--- a/output/output_qemu.ml
|
||||
+++ b/output/output_qemu.ml
|
||||
@@ -108,7 +108,8 @@ module QEMU = struct
|
||||
let _, qemu_boot, output_alloc, output_format,
|
||||
output_name, output_storage = options in
|
||||
|
||||
- let { guestcaps; target_buses; target_firmware } = target_meta in
|
||||
+ let { guestcaps; target_buses;
|
||||
+ target_firmware; target_boot_device } = target_meta in
|
||||
|
||||
(* Start the shell script. Write it to a temporary file
|
||||
* which we rename at the end.
|
||||
@@ -282,8 +283,17 @@ module QEMU = struct
|
||||
* "disk_id".
|
||||
*)
|
||||
let outdisk = disk_path output_storage output_name disk_id in
|
||||
- arg_list "-drive" [ "file=" ^ outdisk; "format=" ^ output_format;
|
||||
- "if=none"; "id=" ^ backend_name; "media=disk" ]
|
||||
+ let bootindex =
|
||||
+ match target_boot_device with
|
||||
+ | None -> disk_id+1
|
||||
+ | Some disk_index when disk_index = disk_id -> 1
|
||||
+ | Some _ -> disk_id+2 in
|
||||
+ arg_list "-drive" [ "file=" ^ outdisk;
|
||||
+ "format=" ^ output_format;
|
||||
+ "if=none";
|
||||
+ "id=" ^ backend_name;
|
||||
+ "media=disk";
|
||||
+ sprintf "bootindex=%d" bootindex ]
|
||||
|
||||
and add_cdrom_backend backend_name =
|
||||
(* Add a drive (back-end) for an "ide-cd" or "scsi-cd" device (front-end).
|
||||
diff --git a/tests/test-cdrom.expected b/tests/test-cdrom.expected
|
||||
index 17bd152d..806461e7 100644
|
||||
--- a/tests/test-cdrom.expected
|
||||
+++ b/tests/test-cdrom.expected
|
||||
@@ -1,6 +1,7 @@
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
+ <boot order='1'/>
|
||||
</disk>
|
||||
<disk device='cdrom' type='file'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
diff --git a/tests/test-floppy.expected b/tests/test-floppy.expected
|
||||
index a718c21f..c5bd913b 100644
|
||||
--- a/tests/test-floppy.expected
|
||||
+++ b/tests/test-floppy.expected
|
||||
@@ -1,6 +1,7 @@
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
+ <boot order='1'/>
|
||||
</disk>
|
||||
<disk device='floppy' type='file'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
diff --git a/tests/test-i-ova.xml b/tests/test-i-ova.xml
|
||||
index f1d8f2e3..08b5b9f2 100644
|
||||
--- a/tests/test-i-ova.xml
|
||||
+++ b/tests/test-i-ova.xml
|
||||
@@ -27,6 +27,7 @@
|
||||
<driver name='qemu' type='raw'/>
|
||||
<source file='TestOva-sda'/>
|
||||
<target dev='vda' bus='virtio'/>
|
||||
+ <boot order='1'/>
|
||||
</disk>
|
||||
<disk device='cdrom' type='file'>
|
||||
<driver name='qemu' type='raw'/>
|
||||
@ -0,0 +1,78 @@
|
||||
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.
|
||||
@ -7,7 +7,7 @@
|
||||
Name: virt-v2v
|
||||
Epoch: 1
|
||||
Version: 2.8.1
|
||||
Release: 8%{?dist}
|
||||
Release: 9%{?dist}
|
||||
Summary: Convert a virtual machine to run on KVM
|
||||
|
||||
License: GPL-2.0-or-later AND LGPL-2.0-or-later
|
||||
@ -53,6 +53,9 @@ Patch0023: 0023-RHEL-Add-warning-about-virt-v2v-in-place-not-being-s.patch
|
||||
Patch0024: 0024-remove-timeout-before-installing-virtio-win-drivers.patch
|
||||
Patch0025: 0025-v2v-Fix-SELinux-relabelling.patch
|
||||
Patch0026: 0026-RHEL-10-m4-Depend-on-libguestfs-1.56.1-2.el10-for-gu.patch
|
||||
Patch0027: 0027-convert-Model-target-boot-device.patch
|
||||
Patch0028: 0028-output-Add-boot-order-depending-on-target-boot-devic.patch
|
||||
Patch0029: 0029-convert-Detect-target-boot-device-for-Linux-guests.patch
|
||||
|
||||
%if !0%{?rhel}
|
||||
# libguestfs hasn't been built on i686 for a while since there is no
|
||||
@ -343,7 +346,7 @@ done
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Aug 13 2025 Richard W.M. Jones <rjones@redhat.com> - 1:2.8.1-8
|
||||
* Aug 21 2025 Richard W.M. Jones <rjones@redhat.com> - 1:2.8.1-9
|
||||
- Rebase to virt-v2v 2.8.1
|
||||
related: RHEL-81735
|
||||
- Fix virt-v2v -v --install dnf5 error
|
||||
@ -386,6 +389,8 @@ done
|
||||
resolves: RHEL-104018
|
||||
- Fix SELinux relabelling in Linux split-/usr
|
||||
resolves: RHEL-109130
|
||||
- Set boot order for Linux guests based on grub location
|
||||
resolves: RHEL-108991
|
||||
|
||||
* Tue Feb 11 2025 Richard W.M. Jones <rjones@redhat.com> - 1:2.7.1-4
|
||||
- Rebase to virt-v2v 2.7.1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user