Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 0/9] generate virtio-transitional devices if told so by libosinfo
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 The first part of the series introduces the "gcaps_virtio_1_0" guest capability (default value, according to the current virt-v2v assumption: "true"), and updates the libvirt and JSON outputs to take the new capability into account. In the libvirt output, the virtio device models are flipped to -- or are explicitly introduced as -- virtio-transitional if the machine type is Q35 and the new "gcaps_virtio_1_0" capability is "false". In the JSON output, we don't change any device models, only expose the new capability, and allow CNV / KubeVirt to act upon it. This follows the spirit of <https://bugzilla.redhat.com/show_bug.cgi?id=1942325#c11>. The second part of the series wraps the osinfo_os_get_all_devices() libosinfo API, and introduces a dependent function to retrieve the guest OS's support for each of the Q35 chipset and the virtio-1.0 protocol (extrapolated from support for virtio1.0-net), from the osinfo database. The final patch in the series couples the two previous parts. The Notes section of this patch contains extensive test results. Thanks, Laszlo Laszlo Ersek (9): lib/types: reformat "string_of_guestcaps" lib/types: update "string_of_guestcaps" lib/types: introduce the "gcaps_virtio_1_0" guest capability output/create_libvirt_xml: pick "virtio-transitional" models when needed output/create_json: expose "gcaps_virtio_1_0" convert/libosinfo: wrap osinfo_os_get_all_devices() convert/libosinfo_utils: introduce "string_of_osinfo_device_list" convert/libosinfo_utils: introduce "os_support_of_osinfo_device_list" convert: determine machine type and virtio-1.0 from osinfo for x86 guests convert/convert_linux.ml | 50 +++++++++------ convert/convert_windows.ml | 31 ++++++--- convert/libosinfo-c.c | 66 ++++++++++++++++++++ convert/libosinfo.ml | 14 +++++ convert/libosinfo.mli | 14 +++++ convert/libosinfo_utils.ml | 54 ++++++++++++++++ convert/libosinfo_utils.mli | 17 +++++ lib/types.ml | 24 +++++-- lib/types.mli | 4 ++ output/create_json.ml | 1 + output/create_libvirt_xml.ml | 28 ++++++--- tests/test-v2v-cdrom.expected | 2 +- tests/test-v2v-floppy.expected | 2 +- tests/test-v2v-i-ova.xml | 8 +-- 14 files changed, 266 insertions(+), 49 deletions(-) base-commit: 07b12fe99fb9cf0b75fe45d3eaa07b4bbc1bbe89 -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 1/9] lib/types: reformat "string_of_guestcaps"
The printf format string in "string_of_guestcaps" is hard to read, because it is not indented properly wrt. the rest of the source code. Indent it properly without changing its behavior. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- lib/types.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/types.ml b/lib/types.ml index 894391baecaa..dc3308dc4d87 100644 --- a/lib/types.ml +++ b/lib/types.ml @@ -423,12 +423,13 @@ let string_of_machine = function let string_of_guestcaps gcaps sprintf "\ -gcaps_block_bus = %s -gcaps_net_bus = %s -gcaps_machine = %s -gcaps_arch = %s -gcaps_acpi = %b -" (string_of_block_type gcaps.gcaps_block_bus) + gcaps_block_bus = %s\n\ + gcaps_net_bus = %s\n\ + gcaps_machine = %s\n\ + gcaps_arch = %s\n\ + gcaps_acpi = %b\n\ + " + (string_of_block_type gcaps.gcaps_block_bus) (string_of_net_type gcaps.gcaps_net_bus) (string_of_machine gcaps.gcaps_machine) gcaps.gcaps_arch -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 2/9] lib/types: update "string_of_guestcaps"
The "string_of_guestcaps" function is out of date; the following commits did not update it, when they introduced new fields to the "guestcaps" record type: - d295d6e510a4 ("v2v: Extend guestcaps to record drivers for virtio-rng, balloon and pvpanic.", 2017-04-06) - 05f780c16f01 ("v2v: support configuration of viosock driver", 2021-02-26) Print those fields now. Fixes: d295d6e510a4fb251d545c52c0a9d6dccabe6f78 Fixes: 05f780c16f0135c657615520c2245b42de1efc3e Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- lib/types.ml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/types.ml b/lib/types.ml index dc3308dc4d87..52db1f9e05d0 100644 --- a/lib/types.ml +++ b/lib/types.ml @@ -425,12 +425,20 @@ let string_of_guestcaps gcaps sprintf "\ gcaps_block_bus = %s\n\ gcaps_net_bus = %s\n\ + gcaps_virtio_rng = %b\n\ + gcaps_virtio_balloon = %b\n\ + gcaps_isa_pvpanic = %b\n\ + gcaps_virtio_socket = %b\n\ gcaps_machine = %s\n\ gcaps_arch = %s\n\ gcaps_acpi = %b\n\ " (string_of_block_type gcaps.gcaps_block_bus) (string_of_net_type gcaps.gcaps_net_bus) + gcaps.gcaps_virtio_rng + gcaps.gcaps_virtio_balloon + gcaps.gcaps_isa_pvpanic + gcaps.gcaps_virtio_socket (string_of_machine gcaps.gcaps_machine) gcaps.gcaps_arch gcaps.gcaps_acpi -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 3/9] lib/types: introduce the "gcaps_virtio_1_0" guest capability
Add a new field to the "guestcaps" record to track whether the guest supports the virtio devices that it does at the virtio-1.0 protocol level. Virt-v2v's current assumption is that virtio-1.0 is supported by any guest, namely for those virtio devices specifically that the guest supports -- which in fact may be the empty set. Make this assumption explicit by setting the new field to "true" in "convert/convert_linux.ml" and "convert/convert_windows.ml". Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- lib/types.mli | 4 ++++ convert/convert_linux.ml | 1 + convert/convert_windows.ml | 1 + lib/types.ml | 3 +++ 4 files changed, 9 insertions(+) diff --git a/lib/types.mli b/lib/types.mli index 02913c0cb4a1..0b9b6e251585 100644 --- a/lib/types.mli +++ b/lib/types.mli @@ -270,6 +270,10 @@ type guestcaps = { gcaps_machine : guestcaps_machine; (** Machine model. *) gcaps_arch : string; (** Architecture that KVM must emulate. *) gcaps_acpi : bool; (** True if guest supports acpi. *) + + gcaps_virtio_1_0 : bool; + (** The guest supports the virtio devices that it does at the virtio-1.0 + protocol level. *) } (** Guest capabilities after conversion. eg. Was virtio found or installed? *) diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml index d49ecec03aeb..3f1114ad155d 100644 --- a/convert/convert_linux.ml +++ b/convert/convert_linux.ml @@ -155,6 +155,7 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ gcaps_machine = machine; gcaps_arch = Utils.kvm_arch inspect.i_arch; gcaps_acpi = acpi; + gcaps_virtio_1_0 = true; } in guestcaps diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml index 0ebffb156633..30e494ea02cb 100644 --- a/convert/convert_windows.ml +++ b/convert/convert_windows.ml @@ -259,6 +259,7 @@ let convert (g : G.guestfs) _ inspect _ static_ips gcaps_machine = machine; gcaps_arch = Utils.kvm_arch inspect.i_arch; gcaps_acpi = true; + gcaps_virtio_1_0 = true; } in guestcaps diff --git a/lib/types.ml b/lib/types.ml index 52db1f9e05d0..50c41918b686 100644 --- a/lib/types.ml +++ b/lib/types.ml @@ -404,6 +404,7 @@ type guestcaps = { gcaps_machine : guestcaps_machine; gcaps_arch : string; gcaps_acpi : bool; + gcaps_virtio_1_0 : bool; } and guestcaps_block_type = Virtio_blk | IDE and guestcaps_net_type = Virtio_net | E1000 | RTL8139 @@ -432,6 +433,7 @@ let string_of_guestcaps gcaps gcaps_machine = %s\n\ gcaps_arch = %s\n\ gcaps_acpi = %b\n\ + gcaps_virtio_1_0 = %b\n\ " (string_of_block_type gcaps.gcaps_block_bus) (string_of_net_type gcaps.gcaps_net_bus) @@ -442,6 +444,7 @@ let string_of_guestcaps gcaps (string_of_machine gcaps.gcaps_machine) gcaps.gcaps_arch gcaps.gcaps_acpi + gcaps.gcaps_virtio_1_0 type target_buses = { target_virtio_blk_bus : target_bus_slot array; -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 4/9] output/create_libvirt_xml: pick "virtio-transitional" models when needed
In the domain XML we generate, we do not assign PCI B/D/F addresses to devices; that job is left to libvirtd. When using the Q35 machine type, libvirtd places the virtio devices into PCI Express Root Ports. As a consequence, QEMU disables virtio-0.9.5 support on these devices, and so guest OSes without virtio-1.0 drivers cannot drive them. Prevent QEMU from turning off the virtio-0.9.5 ("legacy") protocol by specifying the "virtio-transitional" (not "virtio") model for our virtio devices: - For non-disk devices, simply change the value of the existent "model" attribute. - For disk devices, add the "model" attribute as a new one. (In fact, libvirtd doesn't (only) add the "disable_legacy=off" QEMU device property for the "virtio-transitional" devices -- libvirtd even moves these devices from PCI Express Root Ports to a dedicated "pcie-to-pci-bridge". This has the same effect on QEMU.) Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Notes: At this point, this patch is unobservable on the domain XML (by intent). output/create_libvirt_xml.ml | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/output/create_libvirt_xml.ml b/output/create_libvirt_xml.ml index 9413cc0bf884..87bfab178a94 100644 --- a/output/create_libvirt_xml.ml +++ b/output/create_libvirt_xml.ml @@ -312,18 +312,26 @@ let create_libvirt_xml ?pool source inspect (* The devices. *) let devices = ref [] in + (* This will affect all of the virtio devices (if any). *) + let virtio_transitional + guestcaps.gcaps_machine = Q35 && not guestcaps.gcaps_virtio_1_0 in + let virtio_model + if virtio_transitional then "virtio-transitional" else "virtio" in + (* Fixed and removable disks. *) let () - let make_disk bus_name drive_prefix i = function + let make_disk bus_name ?(viotrans = false) drive_prefix i = function | BusSlotEmpty -> Comment (sprintf "%s slot %d is empty" bus_name i) | BusSlotDisk d -> let outdisk = outdisk_name d.s_disk_id in - e "disk" [ - "type", if pool = None then "file" else "volume"; - "device", "disk" - ] [ + e "disk" ( + [ + "type", if pool = None then "file" else "volume"; + "device", "disk" + ] @ if (viotrans) then [ "model", "virtio-transitional" ] else [] + ) [ e "driver" [ "name", "qemu"; "type", output_format; @@ -364,7 +372,7 @@ let create_libvirt_xml ?pool source inspect in List.push_back_list devices - (List.mapi (make_disk "virtio" "vd") + (List.mapi (make_disk "virtio" ~viotrans:virtio_transitional "vd") (Array.to_list target_buses.target_virtio_blk_bus)); let ide_disks match guestcaps.gcaps_machine with @@ -392,7 +400,7 @@ let create_libvirt_xml ?pool source inspect let nics let net_model match guestcaps.gcaps_net_bus with - | Virtio_net -> "virtio" | E1000 -> "e1000" | RTL8139 -> "rtl8139" in + | Virtio_net -> virtio_model | E1000 -> "e1000" | RTL8139 -> "rtl8139" in List.map ( fun { s_mac = mac; s_vnet_type = vnet_type; s_vnet = vnet } -> let vnet_type_str @@ -483,7 +491,7 @@ let create_libvirt_xml ?pool source inspect (* Miscellaneous KVM devices. *) if guestcaps.gcaps_virtio_rng then List.push_back devices ( - e "rng" ["model", "virtio"] [ + e "rng" ["model", virtio_model] [ (* XXX Using /dev/urandom requires libvirt >= 1.3.4. Libvirt * was broken before that. *) @@ -496,7 +504,7 @@ let create_libvirt_xml ?pool source inspect List.push_back devices ( e "memballoon" ["model", - if guestcaps.gcaps_virtio_balloon then "virtio" else "none"] + if guestcaps.gcaps_virtio_balloon then virtio_model else "none"] [] ); if guestcaps.gcaps_isa_pvpanic then @@ -508,7 +516,7 @@ let create_libvirt_xml ?pool source inspect List.push_back devices ( e "viosock" ["model", - if guestcaps.gcaps_virtio_socket then "virtio" else "none"] + if guestcaps.gcaps_virtio_socket then virtio_model else "none"] [] ); -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 5/9] output/create_json: expose "gcaps_virtio_1_0"
Let CNV / KubeVirt know about the "gcaps_virtio_1_0" field as well, so that it can make the same determination from "machine" and "gcaps_virtio_1_0" as virt-v2v does in the libvirt output (from an earlier patch in this series). Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Notes: This patch changes the JSON output as follows: > @@ -45,7 +45,8 @@ > "virtio-balloon": true, > "isa-pvpanic": false, > "virtio-socket": false, > - "acpi": true > + "acpi": true, > + "virtio-1-0": true > }, > "sound": { > "model": "ich6" output/create_json.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/output/create_json.ml b/output/create_json.ml index b48902b7d221..985e10a931c8 100644 --- a/output/create_json.ml +++ b/output/create_json.ml @@ -219,6 +219,7 @@ let create_json_metadata source inspect "isa-pvpanic", JSON.Bool guestcaps.gcaps_isa_pvpanic; "virtio-socket", JSON.Bool guestcaps.gcaps_virtio_socket; "acpi", JSON.Bool guestcaps.gcaps_acpi; + "virtio-1-0", JSON.Bool guestcaps.gcaps_virtio_1_0; ] in List.push_back doc ("guestcaps", JSON.Dict guestcaps_dict); -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 6/9] convert/libosinfo: wrap osinfo_os_get_all_devices()
Introduce the "osinfo_os.get_devices" OCaml method, for wrapping the libosinfo API osinfo_os_get_all_devices(). Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- convert/libosinfo.mli | 14 +++++ convert/libosinfo.ml | 14 +++++ convert/libosinfo-c.c | 66 ++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/convert/libosinfo.mli b/convert/libosinfo.mli index 0428ef911088..1ece7b41a310 100644 --- a/convert/libosinfo.mli +++ b/convert/libosinfo.mli @@ -29,11 +29,25 @@ type osinfo_device_driver = { files : string list; } +type osinfo_device = { + id : string; + vendor : string; + vendor_id : string; + product : string; + product_id : string; + name : string; + class_ : string; + bus_type : string; + subsystem : string; +} + class osinfo_os : osinfo_os_t -> object method get_id : unit -> string (** Return the ID. *) method get_device_drivers : unit -> osinfo_device_driver list (** Return the list of device drivers. *) + method get_devices : unit -> osinfo_device list + (** Return the list of devices. *) end (** Minimal OsinfoOs wrapper. *) diff --git a/convert/libosinfo.ml b/convert/libosinfo.ml index bd9ca126f3c0..78271be248ea 100644 --- a/convert/libosinfo.ml +++ b/convert/libosinfo.ml @@ -32,13 +32,27 @@ type osinfo_device_driver = { files : string list; } +type osinfo_device = { + id : string; + vendor : string; + vendor_id : string; + product : string; + product_id : string; + name : string; + class_ : string; + bus_type : string; + subsystem : string; +} + external osinfo_os_get_id : osinfo_os_t -> string = "v2v_osinfo_os_get_id" external osinfo_os_get_device_drivers : osinfo_os_t -> osinfo_device_driver list = "v2v_osinfo_os_get_device_drivers" +external osinfo_os_get_devices : osinfo_os_t -> osinfo_device list = "v2v_osinfo_os_get_all_devices" class osinfo_os h object (self) method get_id () = osinfo_os_get_id h method get_device_drivers () = osinfo_os_get_device_drivers h + method get_devices () = osinfo_os_get_devices h end external osinfo_db_load : unit -> osinfo_db_t = "v2v_osinfo_db_load" diff --git a/convert/libosinfo-c.c b/convert/libosinfo-c.c index 09cf588d1c10..7a8e287aeb26 100644 --- a/convert/libosinfo-c.c +++ b/convert/libosinfo-c.c @@ -50,6 +50,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoFilter, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoLoader, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoOsList, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoDeviceList, g_object_unref) #endif typedef OsinfoDb *OsinfoDb_t; @@ -255,3 +256,68 @@ v2v_osinfo_os_get_device_drivers (value osv) CAMLreturn (rv); } + +/* Collect OsinfoDevice properties from two levels: + * + * - The OSINFO_ENTITY_PROP_ID property, originating from the OsinfoEntity base + * class. This is a unique URI, identifying the device. + * + * - All currently known OSINFO_DEVICE_PROP_* properties, originating from the + * OsinfoDevice class. + * + * All of the above properties have string values. Thus, for uniformity, access + * all these properties by their names at the OsinfoEntity level (i.e., forego + * the class- and property-specific, dedicated property getter functions). + */ +static const char * const device_prop[] = { + OSINFO_ENTITY_PROP_ID, + OSINFO_DEVICE_PROP_VENDOR, + OSINFO_DEVICE_PROP_VENDOR_ID, + OSINFO_DEVICE_PROP_PRODUCT, + OSINFO_DEVICE_PROP_PRODUCT_ID, + OSINFO_DEVICE_PROP_NAME, + OSINFO_DEVICE_PROP_CLASS, + OSINFO_DEVICE_PROP_BUS_TYPE, + OSINFO_DEVICE_PROP_SUBSYSTEM, +}; +#define NUM_DEVICE_PROPS (sizeof device_prop / sizeof device_prop[0]) + +value +v2v_osinfo_os_get_all_devices (value osv) +{ + CAMLparam1 (osv); + CAMLlocal3 (retval, link, props); + g_autoptr (OsinfoDeviceList) dev_list = NULL; + OsinfoList *ent_list; + gint ent_nr; + + retval = Val_emptylist; + dev_list = osinfo_os_get_all_devices (OsinfoOs_t_val (osv), NULL); + ent_list = OSINFO_LIST (dev_list); + ent_nr = osinfo_list_get_length (ent_list); + + while (ent_nr > 0) { + OsinfoEntity *ent; + size_t prop_nr; + + --ent_nr; + ent = osinfo_list_get_nth (ent_list, ent_nr); + + props = caml_alloc (NUM_DEVICE_PROPS, 0); + for (prop_nr = 0; prop_nr < NUM_DEVICE_PROPS; ++prop_nr) { + const gchar *prop_val; + + prop_val = osinfo_entity_get_param_value (ent, device_prop[prop_nr]); + if (prop_val == NULL) + prop_val = ""; + Store_field (props, prop_nr, caml_copy_string (prop_val)); + } + + link = caml_alloc (2, 0); + Store_field (link, 0, props); + Store_field (link, 1, retval); + retval = link; + } + + CAMLreturn (retval); +} -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 7/9] convert/libosinfo_utils: introduce "string_of_osinfo_device_list"
For debugging purposes, we'll want to print the list of devices returned by the previously introduced "osinfo_os#get_devices" method. Format the device list as a nice table. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Notes: Log examples will be shown later in this series, in the Notes section(s) of other patch(es). convert/libosinfo_utils.mli | 3 ++ convert/libosinfo_utils.ml | 35 ++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/convert/libosinfo_utils.mli b/convert/libosinfo_utils.mli index b3714d224ae4..5a703334d9f0 100644 --- a/convert/libosinfo_utils.mli +++ b/convert/libosinfo_utils.mli @@ -27,3 +27,6 @@ val get_os_by_short_id : string -> Libosinfo.osinfo_os val string_of_osinfo_device_driver : Libosinfo.osinfo_device_driver -> string (** Convert a [osinfo_device_driver] to a printable string for debugging. *) + +val string_of_osinfo_device_list : Libosinfo.osinfo_device list -> string +(** Convert an [osinfo_device] list to a printable string for debugging. *) diff --git a/convert/libosinfo_utils.ml b/convert/libosinfo_utils.ml index 1fc138cce321..d5eb082b458c 100644 --- a/convert/libosinfo_utils.ml +++ b/convert/libosinfo_utils.ml @@ -42,3 +42,38 @@ let string_of_osinfo_device_driver { Libosinfo.architecture; location; (if signed then "signed" else "unsigned") priority (String.concat " " files) + +let string_of_osinfo_device_list dev_list + + (* Turn the fields of an "osinfo_device" record into a list. *) + let listify { Libosinfo.id; vendor; vendor_id; product; product_id; name; + class_; bus_type; subsystem } + [ id; vendor; vendor_id; product; product_id; name; + class_; bus_type; subsystem ] + + (* Given a list of strings, and a list of previously known maximum widths, + * "increase" each width, if necessary, to the length of the corresponding + * string. + *) + and grow_widths = List.map2 (fun s -> max (String.length s)) + in + + (* Compute the maximum width for each field in "dev_list". *) + let max_widths + List.fold_right grow_widths (List.map listify dev_list) + [ 0; 0; 0; 0; 0; 0; 0; 0; 0 ] + + (* Given a list of strings and a list of field widths, format "string1 | + * string2 | ... | stringN" such that each field is right-padded to the + * corresponding width. + *) + and columnate strings widths + String.concat " | " (List.map2 (Printf.sprintf "%-*s") widths strings) + in + + (* Format "dev_list" as a table by (a) printing one "osinfo_device" record + * per line, and (b) right-padding each field of each "osinfo_device" record + * to the maximum width of that field. + *) + String.concat "\n" + (List.map (fun dev -> columnate (listify dev) max_widths) dev_list) -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 8/9] convert/libosinfo_utils: introduce "os_support_of_osinfo_device_list"
Add a helper function for calculating q35 support and virtio-1.0 support from the list of devices returned by the previously introduced "osinfo_os#get_devices" method. (Rather than folding the list into a record of bools, implement the function explicitly, recursively. Folding wouldn't stop (without abusing exceptions) once all fields in the record turned "true", but a recursive function can just return the accumulator at that point.) Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- convert/libosinfo_utils.mli | 14 ++++++++++++++ convert/libosinfo_utils.ml | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/convert/libosinfo_utils.mli b/convert/libosinfo_utils.mli index 5a703334d9f0..ab77ec97df30 100644 --- a/convert/libosinfo_utils.mli +++ b/convert/libosinfo_utils.mli @@ -30,3 +30,17 @@ val string_of_osinfo_device_driver : Libosinfo.osinfo_device_driver -> string val string_of_osinfo_device_list : Libosinfo.osinfo_device list -> string (** Convert an [osinfo_device] list to a printable string for debugging. *) + +type os_support = { + q35 : bool; + vio10 : bool; +} +(** Tell whether the operating system supports the Q35 board type and/or + non-transitional (virtio-1.0-only) virtio devices. (Internally, the + virtio-1.0-net device is used as a proxy for the general statement about + virtio-1.0.) + *) + +val os_support_of_osinfo_device_list : Libosinfo.osinfo_device list -> + os_support +(** Get [os_support] from an [osinfo_device] list. *) diff --git a/convert/libosinfo_utils.ml b/convert/libosinfo_utils.ml index d5eb082b458c..b2ed31ab5c42 100644 --- a/convert/libosinfo_utils.ml +++ b/convert/libosinfo_utils.ml @@ -77,3 +77,22 @@ let string_of_osinfo_device_list dev_list *) String.concat "\n" (List.map (fun dev -> columnate (listify dev) max_widths) dev_list) + +type os_support = { + q35 : bool; + vio10 : bool; +} + +let os_support_of_osinfo_device_list + let rec next accu left + match accu, left with + | { q35 = true; vio10 = true }, _ + | _ , [] -> + accu + | { q35; vio10 }, { Libosinfo.id } :: tail -> + let q35 = q35 || id = "http://qemu.org/chipset/x86/q35" + and vio10 = vio10 || id = "http://pcisig.com/pci/1af4/1041" + in + next { q35; vio10 } tail + in + next { q35 = false; vio10 = false } -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-06 14:09 UTC
[Libguestfs] [v2v PATCH 9/9] convert: determine machine type and virtio-1.0 from osinfo for x86 guests
Determine the machine type and virtio-1.0 support from osinfo, for x86 guests. This connects the previous two parts of this series. Keep the original logic from commit ac39fa292c31 ("v2v: Set machine type explicitly for outputs which support it (RHBZ#1581428).", 2020-12-04) for non-x86 guests, and for the case when libosinfo does not recognize the guest OS. Update the "cdrom", "floppy", and "i-ova" test cases, which all use a (phony) Windows 7 image -- Windows 7 does not support virtio-1.0-only devices, according to libosinfo. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Notes: (1) The patch duplicates the following control structure between "convert_linux.ml" and "convert_windows.ml": arch: i386 or x86_64 grab OS device list from libosinfo success: debug-log device list determine machine type (q35 vs. i440fx) from device list determine virtio-1.0 support from device list not found: FALL BACK TO PRE-EXISTENT LOGIC assume "virtio-1.0: yes" arch: something else machine type: pick Virt assume "virtio-1.0: yes" All of this could be factored out to another helper function (the only difference between the Linux and Windows conversion is the "PRE-EXISTENT LOGIC"). However, I couldn't find a good spot for this. "lib/utils.mli" is too low-level, I think, whereas "convert/libosinfo_utils.mli" is not appropriate: the control structure above does not use libosinfo at all if the architecture differs from x86. (2) When converting a RHEL-5.11 guest, the log contains the following: > libosinfo: loaded OS: http://redhat.com/rhel/5.11 > libosinfo devices for OS "rhel5.11": > http://pcisig.com/pci/8086/2668 | Intel Corporation | 8086 | 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller | 2668 | ich6 | audio | pci | > http://pcisig.com/pci/1af4/1001 | Red Hat, Inc. | 1af4 | Virtio block device | 1001 | virtio-block | block | pci | > http://pcisig.com/pci/1af4/1000 | Red Hat, Inc. | 1af4 | Virtio network device | 1000 | virtio-net | net | pci | > gcaps_block_bus = virtio-blk > gcaps_net_bus = virtio-net > gcaps_virtio_rng = false > gcaps_virtio_balloon = true > gcaps_isa_pvpanic = false > gcaps_virtio_socket = false > gcaps_machine = i440fx > gcaps_arch = x86_64 > gcaps_acpi = true > gcaps_virtio_1_0 = false Note that the device list does *not* contain the Q35 chipset, therefore we can expect the machine type to flip from Q35 to I440FX, rather than just the virtio model flipping from virtio to virtio-transitional. (2.1) Accordingly, the JSON output changes as follows: > @@ -11,7 +11,7 @@ > "apic", > "vmport" > ], > - "machine": "q35", > + "machine": "pc", > "disks": [ > { > "dev": "vda", > @@ -39,14 +39,14 @@ > "block-bus": "virtio-blk", > "net-bus": "virtio-net", > "video": "vga", > - "machine": "q35", > + "machine": "i440fx", > "arch": "x86_64", > "virtio-rng": false, > "virtio-balloon": true, > "isa-pvpanic": false, > "virtio-socket": false, > "acpi": true, > - "virtio-1-0": true > + "virtio-1-0": false > }, > "sound": { > "model": "ich6" (2.2) The generated domain XML changes as follows: > @@ -15,7 +15,7 @@ > <apic/> > </features> > <os> > - <type arch='x86_64' machine='q35'>hvm</type> > + <type arch='x86_64' machine='pc'>hvm</type> > </os> > <on_poweroff>destroy</on_poweroff> > <on_reboot>restart</on_reboot> > @@ -28,7 +28,7 @@ > </disk> > <disk device='cdrom' type='file'> > <driver name='qemu' type='raw'/> > - <target dev='sda' bus='sata'/> > + <target dev='hda' bus='ide'/> > </disk> > <interface type='bridge'> > <source bridge='virbr0'/> (2.3) The domain XML, completed by libvirtd, changes as follows: > @@ -10,7 +10,7 @@ > <currentMemory unit='KiB'>1048576</currentMemory> > <vcpu placement='static'>1</vcpu> > <os> > - <type arch='x86_64' machine='pc-q35-6.1'>hvm</type> > + <type arch='x86_64' machine='pc-i440fx-6.1'>hvm</type> > <boot dev='hd'/> > </os> > <features> > @@ -30,60 +30,26 @@ > <driver name='qemu' type='raw'/> > <source pool='default' volume='converted-sda'/> > <target dev='vda' bus='virtio'/> > - <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> > </disk> > <disk type='file' device='cdrom'> > <driver name='qemu' type='raw'/> > - <target dev='sda' bus='sata'/> > + <target dev='hda' bus='ide'/> > <readonly/> > <address type='drive' controller='0' bus='0' target='0' unit='0'/> > </disk> > - <controller type='usb' index='0' model='qemu-xhci'> > - <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> > + <controller type='usb' index='0' model='piix3-uhci'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> > </controller> > - <controller type='sata' index='0'> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> > - </controller> > - <controller type='pci' index='0' model='pcie-root'/> > - <controller type='pci' index='1' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='1' port='0x10'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/> > - </controller> > - <controller type='pci' index='2' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='2' port='0x11'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> > - </controller> > - <controller type='pci' index='3' model='pcie-to-pci-bridge'> > - <model name='pcie-pci-bridge'/> > - <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> > - </controller> > - <controller type='pci' index='4' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='4' port='0x12'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> > - </controller> > - <controller type='pci' index='5' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='5' port='0x13'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> > - </controller> > - <controller type='pci' index='6' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='6' port='0x14'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> > - </controller> > - <controller type='pci' index='7' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='7' port='0x15'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> > + <controller type='pci' index='0' model='pci-root'/> > + <controller type='ide' index='0'> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> > </controller> > <interface type='bridge'> > <mac address='52:54:00:6c:97:64'/> > <source bridge='virbr0'/> > <model type='virtio'/> > - <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> > </interface> > <serial type='pty'> > <target type='isa-serial' port='0'> > @@ -102,15 +68,15 @@ > <listen type='address'/> > </graphics> > <sound model='ich6'> > - <address type='pci' domain='0x0000' bus='0x03' slot='0x01' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> > </sound> > <audio id='1' type='spice'/> > <video> > <model type='vga' vram='16384' heads='1' primary='yes'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> > </video> > <memballoon model='virtio'> > - <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> > </memballoon> > </devices> > </domain> (2.4) The converted RHEL-5.11 guest actually boots. (3) When converting a RHEL-6.10 guest, the log contains: > libosinfo: loaded OS: http://redhat.com/rhel/6.10 > libosinfo devices for OS "rhel6.10": > http://pcisig.com/pci/8086/2668 | Intel Corporation | 8086 | 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller | 2668 | ich6 | audio | pci | > http://usb.org/usb/80ee/0021 | VirtualBox | 80ee | USB Tablet | 0021 | tablet | input | usb | > http://pcisig.com/pci/1af4/1003 | Red Hat, Inc. | 1af4 | Virtio console | 1003 | virtio-console | console | pci | > http://pcisig.com/pci/8086/293e | Intel Corporation | 8086 | 82801I (ICH9 Family) HD Audio Controller | 293e | ich9-hda | audio | pci | > http://qemu.org/chipset/x86/q35 | | | | | qemu-x86-q35 | chipset | | > http://pcisig.com/pci/1af4/1000 | Red Hat, Inc. | 1af4 | Virtio network device | 1000 | virtio-net | net | pci | > http://pcisig.com/pci/8086/10d3 | Intel Corporation | 8086 | 82574L Gigabit Network Connection | 10d3 | e1000e | net | pci | > http://pcisig.com/pci/1af4/1001 | Red Hat, Inc. | 1af4 | Virtio block device | 1001 | virtio-block | block | pci | > gcaps_block_bus = virtio-blk > gcaps_net_bus = virtio-net > gcaps_virtio_rng = true > gcaps_virtio_balloon = true > gcaps_isa_pvpanic = true > gcaps_virtio_socket = false > gcaps_machine = q35 > gcaps_arch = x86_64 > gcaps_acpi = true > gcaps_virtio_1_0 = false Refer to osinfo-db commit ae0add4d1b0f ("os: Add q35/ich9/e1000e to rhel6", 2018-10-11): https://gitlab.com/libosinfo/osinfo-db/-/commit/ae0add4d1b0f (3.1) The JSON output changes as follows (note the machine type in the context): > @@ -42,15 +42,15 @@ > "machine": "q35", > "arch": "x86_64", > "virtio-rng": true, > "virtio-balloon": true, > "isa-pvpanic": true, > "virtio-socket": false, > "acpi": true, > - "virtio-1-0": true > + "virtio-1-0": false > }, > "sound": { > "model": "ich6" > }, > "display": { > "type": "spice" > }, (3.2) The generated domain XML changes like this (note the machine type in the context): > @@ -18,35 +18,35 @@ > <type arch='x86_64' machine='q35'>hvm</type> > </os> > <on_poweroff>destroy</on_poweroff> > <on_reboot>restart</on_reboot> > <on_crash>restart</on_crash> > <devices> > - <disk type='volume' device='disk'> > + <disk type='volume' device='disk' model='virtio-transitional'> > <driver name='qemu' type='raw'/> > <source pool='default' volume='converted-sda'/> > <target dev='vda' bus='virtio'/> > </disk> > <disk device='cdrom' type='file'> > <driver name='qemu' type='raw'/> > <target dev='sda' bus='sata'/> > </disk> > <interface type='bridge'> > <source bridge='virbr0'/> > - <model type='virtio'/> > + <model type='virtio-transitional'/> > <mac address='52:54:00:3f:89:f8'/> > </interface> > <video> > <model type='vga' vram='16384' heads='1'/> > </video> > <graphics type='spice' autoport='yes' port='-1'/> > <sound model='ich6'/> > - <rng model='virtio'> > + <rng model='virtio-transitional'> > <backend model='random'>/dev/urandom</backend> > </rng> > - <memballoon model='virtio'/> > + <memballoon model='virtio-transitional'/> > <panic model='isa'> > <address type='isa' iobase='0x505'/> > </panic> > <viosock model='none'/> > <input type='tablet' bus='usb'/> > <input type='mouse' bus='ps2'/> (3.3) The domain XML, completed by libvirtd, changes as follows: > @@ -26,11 +26,11 @@ > <on_crash>restart</on_crash> > <devices> > <emulator>/usr/bin/qemu-system-x86_64</emulator> > - <disk type='volume' device='disk'> > + <disk type='volume' device='disk' model='virtio-transitional'> > <driver name='qemu' type='raw'/> > <source pool='default' volume='converted-sda'/> > <target dev='vda' bus='virtio'/> > - <address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x02' slot='0x03' function='0x0'/> > </disk> > <disk type='file' device='cdrom'> > <driver name='qemu' type='raw'/> > @@ -39,7 +39,7 @@ > <address type='drive' controller='0' bus='0' target='0' unit='0'/> > </disk> > <controller type='usb' index='0' model='qemu-xhci'> > - <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> > </controller> > <controller type='sata' index='0'> > <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> > @@ -50,45 +50,25 @@ > <target chassis='1' port='0x10'/> > <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0' multifunction='on'/> > </controller> > - <controller type='pci' index='2' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='2' port='0x11'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> > - </controller> > - <controller type='pci' index='3' model='pcie-to-pci-bridge'> > + <controller type='pci' index='2' model='pcie-to-pci-bridge'> > <model name='pcie-pci-bridge'/> > <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> > </controller> > + <controller type='pci' index='3' model='pcie-root-port'> > + <model name='pcie-root-port'/> > + <target chassis='3' port='0x11'/> > + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> > + </controller> > <controller type='pci' index='4' model='pcie-root-port'> > <model name='pcie-root-port'/> > <target chassis='4' port='0x12'/> > <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> > </controller> > - <controller type='pci' index='5' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='5' port='0x13'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> > - </controller> > - <controller type='pci' index='6' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='6' port='0x14'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> > - </controller> > - <controller type='pci' index='7' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='7' port='0x15'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> > - </controller> > - <controller type='pci' index='8' model='pcie-root-port'> > - <model name='pcie-root-port'/> > - <target chassis='8' port='0x16'/> > - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/> > - </controller> > <interface type='bridge'> > <mac address='52:54:00:3f:89:f8'/> > <source bridge='virbr0'/> > - <model type='virtio'/> > - <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> > + <model type='virtio-transitional'/> > + <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x0'/> > </interface> > <serial type='pty'> > <target type='isa-serial' port='0'> > @@ -107,19 +87,19 @@ > <listen type='address'/> > </graphics> > <sound model='ich6'> > - <address type='pci' domain='0x0000' bus='0x03' slot='0x01' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/> > </sound> > <audio id='1' type='spice'/> > <video> > <model type='vga' vram='16384' heads='1' primary='yes'/> > <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> > </video> > - <memballoon model='virtio'> > - <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/> > + <memballoon model='virtio-transitional'> > + <address type='pci' domain='0x0000' bus='0x02' slot='0x04' function='0x0'/> > </memballoon> > - <rng model='virtio'> > + <rng model='virtio-transitional'> > <backend model='random'>/dev/urandom</backend> > - <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/> > + <address type='pci' domain='0x0000' bus='0x02' slot='0x05' function='0x0'/> > </rng> > <panic model='isa'> > <address type='isa' iobase='0x505'/> Which can be summarized like below: - The model of all four virtio devices has changed from virtio to virtio-transitional (the fifth device, virtio-socket, is not supported at all). - The PCIe root ports providing bus numbers 2, 5, 6, 7, originally hosting the virtio devices, have been removed. The virtio devices have been moved to slots of "pcie-to-pci-bridge". - The (empty) PCIe root port providing bus number 8, has been removed. (This likely used to exist for hotplug purposes.) - "pcie-to-pci-bridge" now provides bus number 2, not 3. - The qemu-xhci device has been moved from the PCIe root port providing bus number 4 to a brand new port, providing bus number 3. The port providing bus number 4 is now empty (likely preserved for hotplug purposes). - The ich6 device has been kept on "pcie-to-pci-bridge", just relocated to a different slot. (3.4) The converted RHEL-6.10 guest actually boots. (4) When converting a RHEL-7.9 guest, the log contains: > libosinfo: loaded OS: http://redhat.com/rhel/7.9 > libosinfo devices for OS "rhel7.9": > http://pcisig.com/pci/1af4/1041 | Red Hat, Inc. | 1af4 | Virtio network device | 1041 | virtio1.0-net | net | pci | > http://pcisig.com/pci/8086/293e | Intel Corporation | 8086 | 82801I (ICH9 Family) HD Audio Controller | 293e | ich9-hda | audio | pci | > http://pcisig.com/pci/1033/0194 | NEC Corporation | 1033 | uPD720200 USB 3.0 Host Controller | 0194 | nec-xhci | controller.usb | pci | > http://pcisig.com/pci/1b36/0100 | Red Hat, Inc. | 1b36 | QXL paravirtual graphic card | 0100 | qxl | video | pci | > http://pcisig.com/pci/8086/2668 | Intel Corporation | 8086 | 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller | 2668 | ich6 | audio | pci | > http://pcisig.com/pci/1af4/1003 | Red Hat, Inc. | 1af4 | Virtio console | 1003 | virtio-console | console | pci | > http://pcisig.com/pci/1af4/1049 | Red Hat, Inc. | 1af4 | Virtio filesystem | 1049 | virtio1.0-9p | filesystem | pci | > http://pcisig.com/pci/1af4/1000 | Red Hat, Inc. | 1af4 | Virtio network device | 1000 | virtio-net | net | pci | > http://pcisig.com/pci/1af4/1043 | Red Hat, Inc. | 1af4 | Virtio console | 1043 | virtio1.0-console | console | pci | > http://qemu.org/chipset/x86/q35 | | | | | qemu-x86-q35 | chipset | | > http://usb.org/usb/80ee/0021 | VirtualBox | 80ee | USB Tablet | 0021 | tablet | input | usb | > http://pcisig.com/pci/1af4/1005 | Red Hat, Inc. | 1af4 | Virtio RNG | 1005 | virtio-rng | rng | pci | > http://pcisig.com/pci/8086/10d3 | Intel Corporation | 8086 | 82574L Gigabit Network Connection | 10d3 | e1000e | net | pci | > http://pcisig.com/pci/1af4/1048 | Red Hat, Inc. | 1af4 | Virtio SCSI | 1048 | virtio1.0-scsi | block | pci | > http://pcisig.com/pci/8086/2415 | Intel Corporation | 8086 | 82801AA AC'97 Audio Controller | 2415 | ac97 | audio | pci | > http://pcisig.com/pci/1af4/1045 | Red Hat, Inc. | 1af4 | Virtio memory balloon | 1045 | virtio1.0-balloon | memory.balloon | pci | > http://pcisig.com/pci/1af4/1042 | Red Hat, Inc. | 1af4 | Virtio block device | 1042 | virtio1.0-block | block | pci | > http://pcisig.com/pci/1b36/0004 | Red Hat, Inc. | 1b36 | QEMU PCI Quad-port 16550A Adapter | 0004 | qemu-xhci | controller.usb | pci | > http://pcisig.com/pci/1af4/1001 | Red Hat, Inc. | 1af4 | Virtio block device | 1001 | virtio-block | block | pci | > http://pcisig.com/pci/1af4/1052 | Red Hat, Inc. | 1af4 | Virtio input | 1052 | virtio1.0-input | input | pci | > http://pcisig.com/pci/1af4/1044 | Red Hat, Inc. | 1af4 | Virtio RNG | 1044 | virtio1.0-rng | rng | pci | > gcaps_block_bus = virtio-blk > gcaps_net_bus = virtio-net > gcaps_virtio_rng = true > gcaps_virtio_balloon = true > gcaps_isa_pvpanic = true > gcaps_virtio_socket = false > gcaps_machine = q35 > gcaps_arch = x86_64 > gcaps_acpi = true > gcaps_virtio_1_0 = true Note the presence of both "qemu-x86-q35" ("http://qemu.org/chipset/x86/q35") and "virtio1.0-net" ("http://pcisig.com/pci/1af4/1041"). (4.1) None of the JSON output, the generated libvirt XML, and the completed (imported by libvirtd) domain XML change. (4.2) The converted RHEL-7.9 guest continues booting. convert/convert_linux.ml | 51 ++++++++++++-------- convert/convert_windows.ml | 32 ++++++++---- tests/test-v2v-cdrom.expected | 2 +- tests/test-v2v-floppy.expected | 2 +- tests/test-v2v-i-ova.xml | 8 +-- 5 files changed, 60 insertions(+), 35 deletions(-) diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml index 3f1114ad155d..45ce069ad9bf 100644 --- a/convert/convert_linux.ml +++ b/convert/convert_linux.ml @@ -123,26 +123,39 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ SELinux_relabel.relabel g; - (* Pivot on the year 2007. Any Linux distro from earlier than - * 2007 should use i440fx, anything 2007 or newer should use q35. - * XXX Look up this information in libosinfo in future. - *) - let machine - match inspect.i_arch, inspect.i_distro, inspect.i_major_version with - | ("i386"|"x86_64"), "fedora", _ -> Q35 - | ("i386"|"x86_64"), ("rhel"|"centos"|"scientificlinux"| - "redhat-based"|"oraclelinux"), major -> - if major <= 4 then I440FX else Q35 - | ("i386"|"x86_64"), ("sles"|"suse-based"|"opensuse"), major -> - if major < 10 then I440FX else Q35 - | ("i386"|"x86_64"), ("debian"|"ubuntu"|"linuxmint"| - "kalilinux"), major -> - if major < 4 then I440FX else Q35 + let machine, virtio_1_0 + match inspect.i_arch with + | ("i386"|"x86_64") -> + (try + let os = Libosinfo_utils.get_os_by_short_id inspect.i_osinfo in + let devices = os#get_devices () in + debug "libosinfo devices for OS \"%s\":\n%s" inspect.i_osinfo + (Libosinfo_utils.string_of_osinfo_device_list devices); + let { Libosinfo_utils.q35; vio10 } + Libosinfo_utils.os_support_of_osinfo_device_list devices in + (if q35 then Q35 else I440FX), vio10 + with + | Not_found -> + (* Pivot on the year 2007. Any Linux distro from earlier than 2007 + * should use i440fx, anything 2007 or newer should use q35. + *) + (match inspect.i_distro, inspect.i_major_version with + | "fedora", _ -> Q35 + | ("rhel"|"centos"|"scientificlinux"|"redhat-based"|"oraclelinux"), + major -> + if major <= 4 then I440FX else Q35 + | ("sles"|"suse-based"|"opensuse"), major -> + if major < 10 then I440FX else Q35 + | ("debian"|"ubuntu"|"linuxmint"|"kalilinux"), major -> + if major < 4 then I440FX else Q35 - (* reasonable default for all modern Linux kernels *) - | ("i386"|"x86_64"), _, _ -> Q35 + (* reasonable default for all modern Linux kernels *) + | _, _ -> Q35 + ), true + ) - | _ -> Virt in + | _ -> Virt, true + in (* Return guest capabilities from the convert () function. *) let guestcaps = { @@ -155,7 +168,7 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ gcaps_machine = machine; gcaps_arch = Utils.kvm_arch inspect.i_arch; gcaps_acpi = acpi; - gcaps_virtio_1_0 = true; + gcaps_virtio_1_0 = virtio_1_0; } in guestcaps diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml index 30e494ea02cb..1c2d17f26543 100644 --- a/convert/convert_windows.ml +++ b/convert/convert_windows.ml @@ -238,15 +238,27 @@ let convert (g : G.guestfs) _ inspect _ static_ips warning (f_"this guest has Anti-Virus (AV) software and a new virtio block device driver was installed. In some circumstances, AV may prevent new drivers from working (resulting in a 7B boot error). If this happens, try disabling AV before doing the conversion."); ); - (* Pivot on the year 2007. Any Windows version from earlier than - * 2007 should use i440fx, anything 2007 or newer should use q35. - * Luckily this coincides almost exactly with the release of NT 6. - * XXX Look up this information in libosinfo in future. - *) - let machine - match inspect.i_arch, inspect.i_major_version with - | ("i386"|"x86_64"), major -> if major < 6 then I440FX else Q35 - | _ -> Virt in + let machine, virtio_1_0 + match inspect.i_arch with + | ("i386"|"x86_64") -> + (try + let os = Libosinfo_utils.get_os_by_short_id inspect.i_osinfo in + let devices = os#get_devices () in + debug "libosinfo devices for OS \"%s\":\n%s" inspect.i_osinfo + (Libosinfo_utils.string_of_osinfo_device_list devices); + let { Libosinfo_utils.q35; vio10 } + Libosinfo_utils.os_support_of_osinfo_device_list devices in + (if q35 then Q35 else I440FX), vio10 + with + | Not_found -> + (* Pivot on the year 2007. Any Windows version from earlier than + * 2007 should use i440fx, anything 2007 or newer should use q35. + * Luckily this coincides almost exactly with the release of NT 6. + *) + (if inspect.i_major_version < 6 then I440FX else Q35), true + ) + | _ -> Virt, true + in (* Return guest capabilities from the convert () function. *) let guestcaps = { @@ -259,7 +271,7 @@ let convert (g : G.guestfs) _ inspect _ static_ips gcaps_machine = machine; gcaps_arch = Utils.kvm_arch inspect.i_arch; gcaps_acpi = true; - gcaps_virtio_1_0 = true; + gcaps_virtio_1_0 = virtio_1_0; } in guestcaps diff --git a/tests/test-v2v-cdrom.expected b/tests/test-v2v-cdrom.expected index 17bd152d8e64..b950492969c8 100644 --- a/tests/test-v2v-cdrom.expected +++ b/tests/test-v2v-cdrom.expected @@ -1,4 +1,4 @@ - <disk type='file' device='disk'> + <disk type='file' device='disk' model='virtio-transitional'> <driver name='qemu' type='raw'/> <target dev='vda' bus='virtio'/> </disk> diff --git a/tests/test-v2v-floppy.expected b/tests/test-v2v-floppy.expected index a718c21f94dd..f4b679540c9d 100644 --- a/tests/test-v2v-floppy.expected +++ b/tests/test-v2v-floppy.expected @@ -1,4 +1,4 @@ - <disk type='file' device='disk'> + <disk type='file' device='disk' model='virtio-transitional'> <driver name='qemu' type='raw'/> <target dev='vda' bus='virtio'/> </disk> diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml index 9f3c1974243f..2b6a8de0f432 100644 --- a/tests/test-v2v-i-ova.xml +++ b/tests/test-v2v-i-ova.xml @@ -21,7 +21,7 @@ <on_reboot>restart</on_reboot> <on_crash>restart</on_crash> <devices> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='virtio-transitional'> <driver name='qemu' type='raw'/> <source file='TestOva-sda'/> <target dev='vda' bus='virtio'/> @@ -36,16 +36,16 @@ </disk> <interface type='bridge'> <source bridge='VM Network'/> - <model type='virtio'/> + <model type='virtio-transitional'/> </interface> <video> <model type='vga' vram='16384' heads='1'/> </video> <graphics type='vnc' autoport='yes' port='-1'/> - <rng model='virtio'> + <rng model='virtio-transitional'> <backend model='random'>/dev/urandom</backend> </rng> - <memballoon model='virtio'/> + <memballoon model='virtio-transitional'/> <viosock model='none'/> <input type='tablet' bus='usb'/> <input type='mouse' bus='ps2'/> -- 2.19.1.3.g30247aa5d201
Laszlo Ersek
2022-Jan-07 11:43 UTC
[Libguestfs] [v2v PATCH 0/9] generate virtio-transitional devices if told so by libosinfo
On 01/06/22 15:09, Laszlo Ersek wrote:> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > > The first part of the series introduces the "gcaps_virtio_1_0" guest > capability (default value, according to the current virt-v2v assumption: > "true"), and updates the libvirt and JSON outputs to take the new > capability into account. > > In the libvirt output, the virtio device models are flipped to -- or are > explicitly introduced as -- virtio-transitional if the machine type is > Q35 and the new "gcaps_virtio_1_0" capability is "false". > > In the JSON output, we don't change any device models, only expose the > new capability, and allow CNV / KubeVirt to act upon it. This follows > the spirit of <https://bugzilla.redhat.com/show_bug.cgi?id=1942325#c11>. > > The second part of the series wraps the osinfo_os_get_all_devices() > libosinfo API, and introduces a dependent function to retrieve the guest > OS's support for each of the Q35 chipset and the virtio-1.0 protocol > (extrapolated from support for virtio1.0-net), from the osinfo database. > > The final patch in the series couples the two previous parts. The Notes > section of this patch contains extensive test results. > > Thanks, > Laszlo > > Laszlo Ersek (9): > lib/types: reformat "string_of_guestcaps" > lib/types: update "string_of_guestcaps" > lib/types: introduce the "gcaps_virtio_1_0" guest capability > output/create_libvirt_xml: pick "virtio-transitional" models when > needed > output/create_json: expose "gcaps_virtio_1_0" > convert/libosinfo: wrap osinfo_os_get_all_devices() > convert/libosinfo_utils: introduce "string_of_osinfo_device_list" > convert/libosinfo_utils: introduce "os_support_of_osinfo_device_list" > convert: determine machine type and virtio-1.0 from osinfo for x86 > guests > > convert/convert_linux.ml | 50 +++++++++------ > convert/convert_windows.ml | 31 ++++++--- > convert/libosinfo-c.c | 66 ++++++++++++++++++++ > convert/libosinfo.ml | 14 +++++ > convert/libosinfo.mli | 14 +++++ > convert/libosinfo_utils.ml | 54 ++++++++++++++++ > convert/libosinfo_utils.mli | 17 +++++ > lib/types.ml | 24 +++++-- > lib/types.mli | 4 ++ > output/create_json.ml | 1 + > output/create_libvirt_xml.ml | 28 ++++++--- > tests/test-v2v-cdrom.expected | 2 +- > tests/test-v2v-floppy.expected | 2 +- > tests/test-v2v-i-ova.xml | 8 +-- > 14 files changed, 266 insertions(+), 49 deletions(-) > > > base-commit: 07b12fe99fb9cf0b75fe45d3eaa07b4bbc1bbe89 >Merged as commit range f9d5448d2efe..f0cea012d018, with the following updates (as requested by Rich), and with the test suite re-run:> 1: 6ffaacdf079a ! 1: dc69bb6033bd lib/types: reformat "string_of_guestcaps" > @@ -8,6 +8,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-2-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/lib/types.ml b/lib/types.ml > --- a/lib/types.ml > 2: 47b1335ef3d6 ! 2: 08786886302c lib/types: update "string_of_guestcaps" > @@ -18,6 +18,8 @@ > Fixes: 05f780c16f0135c657615520c2245b42de1efc3e > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-3-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/lib/types.ml b/lib/types.ml > --- a/lib/types.ml > 3: 700768d96d72 ! 3: 789017805ad0 lib/types: introduce the "gcaps_virtio_1_0" guest capability > @@ -13,6 +13,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-4-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/lib/types.mli b/lib/types.mli > --- a/lib/types.mli > 4: cb19eff53aaa ! 4: e4cf85bd3ad4 output/create_libvirt_xml: pick "virtio-transitional" models when needed > @@ -24,6 +24,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-5-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/output/create_libvirt_xml.ml b/output/create_libvirt_xml.ml > --- a/output/create_libvirt_xml.ml > 5: f0162a5024a2 ! 5: 511910e1f7e9 output/create_json: expose "gcaps_virtio_1_0" > @@ -9,6 +9,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-6-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/output/create_json.ml b/output/create_json.ml > --- a/output/create_json.ml > 6: c9a39ebc6842 ! 6: 46f5885dba1b convert/libosinfo: wrap osinfo_os_get_all_devices() > @@ -7,6 +7,9 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-7-lersek at redhat.com> > + [lersek at redhat.com: call OCaml values "<something>v" (Rich)] > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/convert/libosinfo.mli b/convert/libosinfo.mli > --- a/convert/libosinfo.mli > @@ -115,12 +118,12 @@ > +v2v_osinfo_os_get_all_devices (value osv) > +{ > + CAMLparam1 (osv); > -+ CAMLlocal3 (retval, link, props); > ++ CAMLlocal3 (retvalv, linkv, propsv); > + g_autoptr (OsinfoDeviceList) dev_list = NULL; > + OsinfoList *ent_list; > + gint ent_nr; > + > -+ retval = Val_emptylist; > ++ retvalv = Val_emptylist; > + dev_list = osinfo_os_get_all_devices (OsinfoOs_t_val (osv), NULL); > + ent_list = OSINFO_LIST (dev_list); > + ent_nr = osinfo_list_get_length (ent_list); > @@ -132,21 +135,21 @@ > + --ent_nr; > + ent = osinfo_list_get_nth (ent_list, ent_nr); > + > -+ props = caml_alloc (NUM_DEVICE_PROPS, 0); > ++ propsv = caml_alloc (NUM_DEVICE_PROPS, 0); > + for (prop_nr = 0; prop_nr < NUM_DEVICE_PROPS; ++prop_nr) { > + const gchar *prop_val; > + > + prop_val = osinfo_entity_get_param_value (ent, device_prop[prop_nr]); > + if (prop_val == NULL) > + prop_val = ""; > -+ Store_field (props, prop_nr, caml_copy_string (prop_val)); > ++ Store_field (propsv, prop_nr, caml_copy_string (prop_val)); > + } > + > -+ link = caml_alloc (2, 0); > -+ Store_field (link, 0, props); > -+ Store_field (link, 1, retval); > -+ retval = link; > ++ linkv = caml_alloc (2, 0); > ++ Store_field (linkv, 0, propsv); > ++ Store_field (linkv, 1, retvalv); > ++ retvalv = linkv; > + } > + > -+ CAMLreturn (retval); > ++ CAMLreturn (retvalv); > +} > 7: beb6d02a55bf ! 7: 00473c6ac09d convert/libosinfo_utils: introduce "string_of_osinfo_device_list" > @@ -9,6 +9,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-8-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/convert/libosinfo_utils.mli b/convert/libosinfo_utils.mli > --- a/convert/libosinfo_utils.mli > 8: 1f37f5440d66 ! 8: 2a2d7e9e1376 convert/libosinfo_utils: introduce "os_support_of_osinfo_device_list" > @@ -13,6 +13,10 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-9-lersek at redhat.com> > + [lersek at redhat.com: don't break "in" to a new line after a "let" that > + defines a non-function (Rich)] > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/convert/libosinfo_utils.mli b/convert/libosinfo_utils.mli > --- a/convert/libosinfo_utils.mli > @@ -57,8 +61,7 @@ > + accu > + | { q35; vio10 }, { Libosinfo.id } :: tail -> > + let q35 = q35 || id = "http://qemu.org/chipset/x86/q35" > -+ and vio10 = vio10 || id = "http://pcisig.com/pci/1af4/1041" > -+ in > ++ and vio10 = vio10 || id = "http://pcisig.com/pci/1af4/1041" in > + next { q35; vio10 } tail > + in > + next { q35 = false; vio10 = false } > 9: 0ba32aed5e96 ! 9: f0cea012d018 convert: determine machine type and virtio-1.0 from osinfo for x86 guests > @@ -16,6 +16,8 @@ > > Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1942325 > Signed-off-by: Laszlo Ersek <lersek at redhat.com> > + Message-Id: <20220106140910.13695-10-lersek at redhat.com> > + Acked-by: Richard W.M. Jones <rjones at redhat.com> > > diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml > --- a/convert/convert_linux.mlI'll follow up with the "explicit temporaries" patch later. Thanks! Laszlo