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