Laszlo Ersek
2021-Dec-14 15:17 UTC
[Libguestfs] [PATCH] convert_linux: translate the first CD-ROM's references in boot conf files
If the only CD-ROM in "s_removables" is on an IDE controller, and the guest kernel represents it with a /dev/hdX device node, then convert references to this device node, in the boot config files, to /dev/cdrom. On the destination (after conversion), /dev/cdrom will point to whataver node we converted the CD-ROM to, masking a potential i440fx -> q35 (IDE -> SATA) board change. If the only CD-ROM is not on an IDE controller, or the guest is modern enough to represent the IDE CD-ROM as /dev/sr0, then perform no translation. Namely, /dev/sr0 survives a potential i440fx -> q35 (IDE -> SATA) board change intact. When multiple CD-ROMs exist, emit a warning, and attempt the conversion on the first CD-ROM, as a guess. This may be inexact, but we can't do better, because: - SATA, SCSI, and (on modern guests) IDE CD-ROMs are lumped together in the /dev/sr* namespace, on the source side, and "s_removable_slot" is useless for telling them apart, as we don't know the exact controller topology (and OS enumeration order); - after conversion: some OSes don't create /dev/cdrom* symlinks to all CD-ROMs, and even if multiple such symlinks are created, their order is basically random. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1637857 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- convert/convert_linux.ml | 25 +++++++++++++++++++++++++ tests/test-v2v-cdrom.expected | 2 +- tests/test-v2v-cdrom.xml.in | 4 +++- tests/test-v2v-i-ova.xml | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml index 8dc648169dcb..9ea94b75bfc9 100644 --- a/convert/convert_linux.ml +++ b/convert/convert_linux.ml @@ -1020,6 +1020,31 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ "xvd" ^ drive_name i, block_prefix_after_conversion ^ drive_name i ) source.s_disks in + (* Check the first CD-ROM. If its controller is IDE, and the OS is RHEL<=5, + * then translate the CD-ROM from "/dev/hd[SLOT]" to "/dev/cdrom". See + * RHBZ#1637857 for details. + *) + let cdroms = List.filter + (fun removable -> removable.s_removable_type = CDROM) + source.s_removables in + + match cdroms with + | _ :: _ :: _ -> warning (f_"multiple CD-ROMs found; translation of \ + CD-ROM references may be inexact") + | _ -> (); + + let map = map @ + (match cdroms with + | cdrom :: _ -> + (match (cdrom.s_removable_controller, cdrom.s_removable_slot, + family, inspect.i_major_version) with + | Some Source_IDE, Some slot, `RHEL_family, v when v <= 5 -> + [("hd" ^ drive_name slot, "cdrom")] + | _ -> [] + ) + | [] -> [] + ) in + if verbose () then ( eprintf "block device map:\n"; List.iter ( diff --git a/tests/test-v2v-cdrom.expected b/tests/test-v2v-cdrom.expected index 34d2bf5961b0..17bd152d8e64 100644 --- a/tests/test-v2v-cdrom.expected +++ b/tests/test-v2v-cdrom.expected @@ -4,5 +4,5 @@ </disk> <disk device='cdrom' type='file'> <driver name='qemu' type='raw'/> - <target dev='hdc' bus='ide'/> + <target dev='sdc' bus='sata'/> </disk> diff --git a/tests/test-v2v-cdrom.xml.in b/tests/test-v2v-cdrom.xml.in index 6bad5eab1cd4..a6e1e3f514d5 100644 --- a/tests/test-v2v-cdrom.xml.in +++ b/tests/test-v2v-cdrom.xml.in @@ -35,7 +35,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='@abs_top_builddir@/test-data/phony-guests/blank-disk.img'/> - <!-- virt-v2v should preserve the device name and bus --> + <!-- virt-v2v should change the bus to sata, due to Windows 7 + triggering a machine type change from i440fx to q35. Beyond that, + virt-v2v should preserve the on-bus index. --> <target dev='hdc' bus='ide'/> </disk> </devices> diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml index d7383905fdc0..9f3c1974243f 100644 --- a/tests/test-v2v-i-ova.xml +++ b/tests/test-v2v-i-ova.xml @@ -28,7 +28,7 @@ </disk> <disk device='cdrom' type='file'> <driver name='qemu' type='raw'/> - <target dev='hda' bus='ide'/> + <target dev='sda' bus='sata'/> </disk> <disk device='floppy' type='file'> <driver name='qemu' type='raw'/> -- 2.19.1.3.g30247aa5d201
Richard W.M. Jones
2021-Dec-14 20:46 UTC
[Libguestfs] [PATCH] convert_linux: translate the first CD-ROM's references in boot conf files
On Tue, Dec 14, 2021 at 04:17:49PM +0100, Laszlo Ersek wrote:> + match cdroms with > + | _ :: _ :: _ -> warning (f_"multiple CD-ROMs found; translation of \ > + CD-ROM references may be inexact") > + | _ -> (); > + > + let map = map @This part is either wrong or indented incorrectly. The "let map ..." part is part of the second branch of the match statement and doesn't run if the warning is printed. In any case it's probably better to replace the confusing first match with something simpler such as: if List.length cdroms > 2 then warning (f_"multiple CD-ROMs found; translation of CD-ROM references may be inexact"); The \ is also not necessary in the original since OCaml lets you have arbitrary length strings over multiple lines (a good thing), plus we automatically wrap warning and error strings on whitespace.> + (match cdroms with > + | cdrom :: _ -> > + (match (cdrom.s_removable_controller, cdrom.s_removable_slot, > + family, inspect.i_major_version) with > + | Some Source_IDE, Some slot, `RHEL_family, v when v <= 5 ->You can just match to arbitrary depth in single match statements, so the whole match would become something like: let map = map @ match cdroms with | { Some Source_IDE, Some slot, `RHEL_family v } :: _ when v <= 5 -> [("hd" ^ drive_name slot, "cdrom")] | _ -> [] in Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org