Blame SOURCES/0047-v2v-Model-machine-type-explicitly.patch

df3bb2
From 81f35e441d06bff2bf60bff6354d53de137847d9 Mon Sep 17 00:00:00 2001
df3bb2
From: "Richard W.M. Jones" <rjones@redhat.com>
df3bb2
Date: Tue, 19 Jun 2018 10:44:57 +0100
df3bb2
Subject: [PATCH] v2v: Model machine type explicitly.
df3bb2
df3bb2
QEMU for x86 supports two machine types, "pc" (emulating the ancient
df3bb2
Intel i440FX chipset originally used by the Pentium Pro), and "q35"
df3bb2
(https://wiki.qemu.org/Features/Q35).
df3bb2
df3bb2
Currently virt-v2v does not set any machine type, so libvirt or the
df3bb2
target hypervisor will choose some default, probably i440fx.  The
df3bb2
latest advice from the QEMU and libvirt communities is not to rely on
df3bb2
the default machine type but to specify what we need explicitly, but
df3bb2
it may also be that the libvirt configuration file has been changed to
df3bb2
set the default machine type to Q35 (either by the distro or the end
df3bb2
user).
df3bb2
df3bb2
None of this matters for reasonably new guests since they can boot
df3bb2
with either chipset.  However there are some very old guests (notably
df3bb2
Windows XP) which cannot handle Q35.
df3bb2
df3bb2
This commit changes virt-v2v so it always tries to specify the machine
df3bb2
type explicitly (assuming the target supports that, and not all of
df3bb2
them do).  For x86_64 guests this patch always selects i440fx (pc).
df3bb2
In future we hope to get the correct machine type for the guest from
df3bb2
libosinfo but this is not available yet.
df3bb2
df3bb2
For non-x86 architectures we select the "virt" model which will
df3bb2
probably only work for AArch64.  More work is needed for POWER.
df3bb2
df3bb2
For secure boot we still have to force the machine type to Q35.  In a
df3bb2
future version this forcing can be removed since any guest which is
df3bb2
using secure boot will be new enough that it'll be using Q35 anyway
df3bb2
(on x86).
df3bb2
df3bb2
(cherry picked from commit 55879b2f2c5b205352f48f999e20efd9b455ea43)
df3bb2
---
df3bb2
 v2v/convert_linux.ml      |  7 +++++++
df3bb2
 v2v/convert_windows.ml    |  7 +++++++
df3bb2
 v2v/create_libvirt_xml.ml | 37 +++++++++++++++++++++++++------------
df3bb2
 v2v/create_ovf.ml         |  2 ++
df3bb2
 v2v/output_glance.ml      |  5 +++++
df3bb2
 v2v/output_qemu.ml        | 30 +++++++++++++++++++-----------
df3bb2
 v2v/test-v2v-i-ova.xml    |  2 +-
df3bb2
 v2v/types.ml              |  8 ++++++++
df3bb2
 v2v/types.mli             |  6 ++++--
df3bb2
 9 files changed, 78 insertions(+), 26 deletions(-)
df3bb2
df3bb2
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
df3bb2
index 4a7447fe1..fd6b71ba4 100644
df3bb2
--- a/v2v/convert_linux.ml
df3bb2
+++ b/v2v/convert_linux.ml
df3bb2
@@ -122,6 +122,12 @@ let convert (g : G.guestfs) inspect source output rcaps =
df3bb2
 
df3bb2
     SELinux_relabel.relabel g;
df3bb2
 
df3bb2
+    (* XXX Look up this information in libosinfo in future. *)
df3bb2
+    let machine =
df3bb2
+      match inspect.i_arch with
df3bb2
+      | "i386"|"x86_64" -> I440FX
df3bb2
+      | _ -> Virt in
df3bb2
+
df3bb2
     (* Return guest capabilities from the convert () function. *)
df3bb2
     let guestcaps = {
df3bb2
       gcaps_block_bus = block_type;
df3bb2
@@ -130,6 +136,7 @@ let convert (g : G.guestfs) inspect source output rcaps =
df3bb2
       gcaps_virtio_rng = kernel.ki_supports_virtio_rng;
df3bb2
       gcaps_virtio_balloon = kernel.ki_supports_virtio_balloon;
df3bb2
       gcaps_isa_pvpanic = kernel.ki_supports_isa_pvpanic;
df3bb2
+      gcaps_machine = machine;
df3bb2
       gcaps_arch = Utils.kvm_arch inspect.i_arch;
df3bb2
       gcaps_acpi = acpi;
df3bb2
     } in
df3bb2
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
df3bb2
index 163319545..1e058136e 100644
df3bb2
--- a/v2v/convert_windows.ml
df3bb2
+++ b/v2v/convert_windows.ml
df3bb2
@@ -212,6 +212,12 @@ let convert (g : G.guestfs) inspect source output rcaps =
df3bb2
         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.");
df3bb2
     );
df3bb2
 
df3bb2
+    (* XXX Look up this information in libosinfo in future. *)
df3bb2
+    let machine =
df3bb2
+      match inspect.i_arch with
df3bb2
+      | "i386"|"x86_64" -> I440FX
df3bb2
+      | _ -> Virt in
df3bb2
+
df3bb2
     (* Return guest capabilities from the convert () function. *)
df3bb2
     let guestcaps = {
df3bb2
       gcaps_block_bus = block_driver;
df3bb2
@@ -220,6 +226,7 @@ let convert (g : G.guestfs) inspect source output rcaps =
df3bb2
       gcaps_virtio_rng = virtio_rng_supported;
df3bb2
       gcaps_virtio_balloon = virtio_ballon_supported;
df3bb2
       gcaps_isa_pvpanic = isa_pvpanic_supported;
df3bb2
+      gcaps_machine = machine;
df3bb2
       gcaps_arch = Utils.kvm_arch inspect.i_arch;
df3bb2
       gcaps_acpi = true;
df3bb2
     } in
df3bb2
diff --git a/v2v/create_libvirt_xml.ml b/v2v/create_libvirt_xml.ml
df3bb2
index fbe90eeaa..8a34c94b0 100644
df3bb2
--- a/v2v/create_libvirt_xml.ml
df3bb2
+++ b/v2v/create_libvirt_xml.ml
df3bb2
@@ -81,15 +81,17 @@ let create_libvirt_xml ?pool source target_buses guestcaps
df3bb2
     match target_firmware with
df3bb2
     | TargetBIOS -> None
df3bb2
     | TargetUEFI -> Some (find_uefi_firmware guestcaps.gcaps_arch) in
df3bb2
-  let secure_boot_required =
df3bb2
-    match uefi_firmware with
df3bb2
-    | Some { Uefi.flags = flags }
df3bb2
-         when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> true
df3bb2
-    | _ -> false in
df3bb2
-  (* Currently these are required by secure boot, but in theory they
df3bb2
-   * might be independent properties.
df3bb2
-   *)
df3bb2
-  let machine_q35 = secure_boot_required in
df3bb2
+  let machine, secure_boot_required =
df3bb2
+    match guestcaps.gcaps_machine, uefi_firmware with
df3bb2
+    | _, Some { Uefi.flags = flags }
df3bb2
+         when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags ->
df3bb2
+       (* Force machine type to Q35 because PC does not support
df3bb2
+        * secure boot.  We must remove this when we get the
df3bb2
+        * correct machine type from libosinfo in future. XXX
df3bb2
+        *)
df3bb2
+       Q35, true
df3bb2
+    | machine, _ ->
df3bb2
+       machine, false in
df3bb2
   let smm = secure_boot_required in
df3bb2
 
df3bb2
   (* We have the machine features of the guest when it was on the
df3bb2
@@ -140,7 +142,18 @@ let create_libvirt_xml ?pool source target_buses guestcaps
df3bb2
 
df3bb2
   (* The <os> section subelements. *)
df3bb2
   let os_section =
df3bb2
-    let machine = if machine_q35 then [ "machine", "q35" ] else [] in
df3bb2
+    let os = ref [] in
df3bb2
+
df3bb2
+    let machine =
df3bb2
+      match machine with
df3bb2
+      | I440FX -> "pc"
df3bb2
+      | Q35 -> "q35"
df3bb2
+      | Virt -> "virt" in
df3bb2
+
df3bb2
+    List.push_back os
df3bb2
+                   (e "type" ["arch", guestcaps.gcaps_arch;
df3bb2
+                              "machine", machine]
df3bb2
+                      [PCData "hvm"]);
df3bb2
 
df3bb2
     let loader =
df3bb2
       match uefi_firmware with
df3bb2
@@ -152,8 +165,8 @@ let create_libvirt_xml ?pool source target_buses guestcaps
df3bb2
              [ PCData code ];
df3bb2
            e "nvram" ["template", vars_template] [] ] in
df3bb2
 
df3bb2
-    (e "type" (["arch", guestcaps.gcaps_arch] @ machine) [PCData "hvm"])
df3bb2
-    :: loader in
df3bb2
+    List.push_back_list os loader;
df3bb2
+    !os in
df3bb2
 
df3bb2
   List.push_back_list body [
df3bb2
     e "os" [] os_section;
df3bb2
diff --git a/v2v/create_ovf.ml b/v2v/create_ovf.ml
df3bb2
index 5db239d66..01970013e 100644
df3bb2
--- a/v2v/create_ovf.ml
df3bb2
+++ b/v2v/create_ovf.ml
df3bb2
@@ -602,6 +602,8 @@ let rec create_ovf source targets guestcaps inspect
df3bb2
                                      source.s_vcpu memsize_mb)]
df3bb2
       ] in
df3bb2
 
df3bb2
+      (* XXX How to set machine type for Q35? *)
df3bb2
+
df3bb2
       List.push_back virtual_hardware_section_items (
df3bb2
         e "Item" [] ([
df3bb2
           e "rasd:Caption" [] [PCData (sprintf "%d virtual cpu" source.s_vcpu)];
df3bb2
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
df3bb2
index c334def42..96c31da59 100644
df3bb2
--- a/v2v/output_glance.ml
df3bb2
+++ b/v2v/output_glance.ml
df3bb2
@@ -86,6 +86,11 @@ object
df3bb2
         (match guestcaps.gcaps_video with
df3bb2
          | QXL -> "qxl"
df3bb2
          | Cirrus -> "cirrus");
df3bb2
+        "hw_machine_type",
df3bb2
+        (match guestcaps.gcaps_machine with
df3bb2
+         | I440FX -> "pc"
df3bb2
+         | Q35 -> "q35"
df3bb2
+         | Virt -> "virt");
df3bb2
         "architecture", guestcaps.gcaps_arch;
df3bb2
         "hypervisor_type", "kvm";
df3bb2
         "vm_mode", "hvm";
df3bb2
diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml
df3bb2
index 952660de2..e23f22e12 100644
df3bb2
--- a/v2v/output_qemu.ml
df3bb2
+++ b/v2v/output_qemu.ml
df3bb2
@@ -56,17 +56,25 @@ object
df3bb2
       match target_firmware with
df3bb2
       | TargetBIOS -> None
df3bb2
       | TargetUEFI -> Some (find_uefi_firmware guestcaps.gcaps_arch) in
df3bb2
-    let secure_boot_required =
df3bb2
-      match uefi_firmware with
df3bb2
-      | Some { Uefi.flags }
df3bb2
-           when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags -> true
df3bb2
-      | _ -> false in
df3bb2
-    (* Currently these are required by secure boot, but in theory they
df3bb2
-     * might be independent properties.
df3bb2
-     *)
df3bb2
-    let machine_q35 = secure_boot_required in
df3bb2
+    let machine, secure_boot_required =
df3bb2
+      match guestcaps.gcaps_machine, uefi_firmware with
df3bb2
+      | _, Some { Uefi.flags }
df3bb2
+           when List.mem Uefi.UEFI_FLAG_SECURE_BOOT_REQUIRED flags ->
df3bb2
+         (* Force machine type to Q35 because PC does not support
df3bb2
+          * secure boot.  We must remove this when we get the
df3bb2
+          * correct machine type from libosinfo in future. XXX
df3bb2
+          *)
df3bb2
+         Q35, true
df3bb2
+      | machine, _ ->
df3bb2
+         machine, false in
df3bb2
     let smm = secure_boot_required in
df3bb2
 
df3bb2
+    let machine =
df3bb2
+      match machine with
df3bb2
+      | I440FX -> "pc"
df3bb2
+      | Q35 -> "q35"
df3bb2
+      | Virt -> "virt" in
df3bb2
+
df3bb2
     (* Construct the command line.  Note that the [Qemuopts]
df3bb2
      * module deals with shell and qemu comma quoting.
df3bb2
      *)
df3bb2
@@ -80,8 +88,8 @@ object
df3bb2
 
df3bb2
     flag "-no-user-config"; flag "-nodefaults";
df3bb2
     arg "-name" source.s_name;
df3bb2
-    arg_list "-machine" (if machine_q35 then ["q35"] else [] @
df3bb2
-                         if smm then ["smm=on"] else [] @
df3bb2
+    arg_list "-machine" (machine ::
df3bb2
+                         (if smm then ["smm=on"] else []) @
df3bb2
                          ["accel=kvm:tcg"]);
df3bb2
 
df3bb2
     (match uefi_firmware with
df3bb2
diff --git a/v2v/test-v2v-i-ova.xml b/v2v/test-v2v-i-ova.xml
df3bb2
index 5a303b80a..b277193a8 100644
df3bb2
--- a/v2v/test-v2v-i-ova.xml
df3bb2
+++ b/v2v/test-v2v-i-ova.xml
df3bb2
@@ -10,7 +10,7 @@
df3bb2
     <apic/>
df3bb2
   </features>
df3bb2
   <os>
df3bb2
-    <type arch='x86_64'>hvm</type>
df3bb2
+    <type arch='x86_64' machine='pc'>hvm</type>
df3bb2
   </os>
df3bb2
   <on_poweroff>destroy</on_poweroff>
df3bb2
   <on_reboot>restart</on_reboot>
df3bb2
diff --git a/v2v/types.ml b/v2v/types.ml
df3bb2
index bb77e5669..9851386f7 100644
df3bb2
--- a/v2v/types.ml
df3bb2
+++ b/v2v/types.ml
df3bb2
@@ -401,6 +401,7 @@ type guestcaps = {
df3bb2
   gcaps_virtio_rng : bool;
df3bb2
   gcaps_virtio_balloon : bool;
df3bb2
   gcaps_isa_pvpanic : bool;
df3bb2
+  gcaps_machine : guestcaps_machine;
df3bb2
   gcaps_arch : string;
df3bb2
   gcaps_acpi : bool;
df3bb2
 }
df3bb2
@@ -412,6 +413,7 @@ and requested_guestcaps = {
df3bb2
 and guestcaps_block_type = Virtio_blk | Virtio_SCSI | IDE
df3bb2
 and guestcaps_net_type = Virtio_net | E1000 | RTL8139
df3bb2
 and guestcaps_video_type = QXL | Cirrus
df3bb2
+and guestcaps_machine = I440FX | Q35 | Virt
df3bb2
 
df3bb2
 let string_of_block_type = function
df3bb2
   | Virtio_blk -> "virtio-blk"
df3bb2
@@ -424,17 +426,23 @@ let string_of_net_type = function
df3bb2
 let string_of_video = function
df3bb2
   | QXL -> "qxl"
df3bb2
   | Cirrus -> "cirrus"
df3bb2
+let string_of_machine = function
df3bb2
+  | I440FX -> "i440fx"
df3bb2
+  | Q35 -> "q35"
df3bb2
+  | Virt -> "virt"
df3bb2
 
df3bb2
 let string_of_guestcaps gcaps =
df3bb2
   sprintf "\
df3bb2
 gcaps_block_bus = %s
df3bb2
 gcaps_net_bus = %s
df3bb2
 gcaps_video = %s
df3bb2
+gcaps_machine = %s
df3bb2
 gcaps_arch = %s
df3bb2
 gcaps_acpi = %b
df3bb2
 " (string_of_block_type gcaps.gcaps_block_bus)
df3bb2
   (string_of_net_type gcaps.gcaps_net_bus)
df3bb2
   (string_of_video gcaps.gcaps_video)
df3bb2
+  (string_of_machine gcaps.gcaps_machine)
df3bb2
   gcaps.gcaps_arch
df3bb2
   gcaps.gcaps_acpi
df3bb2
 
df3bb2
diff --git a/v2v/types.mli b/v2v/types.mli
df3bb2
index f60e5c98f..5e33b1de9 100644
df3bb2
--- a/v2v/types.mli
df3bb2
+++ b/v2v/types.mli
df3bb2
@@ -240,8 +240,9 @@ type guestcaps = {
df3bb2
   gcaps_virtio_balloon : bool;  (** Guest supports virtio balloon. *)
df3bb2
   gcaps_isa_pvpanic : bool;     (** Guest supports ISA pvpanic device. *)
df3bb2
 
df3bb2
-  gcaps_arch : string;      (** Architecture that KVM must emulate. *)
df3bb2
-  gcaps_acpi : bool;        (** True if guest supports acpi. *)
df3bb2
+  gcaps_machine : guestcaps_machine; (** Machine model. *)
df3bb2
+  gcaps_arch : string;          (** Architecture that KVM must emulate. *)
df3bb2
+  gcaps_acpi : bool;            (** True if guest supports acpi. *)
df3bb2
 }
df3bb2
 (** Guest capabilities after conversion.  eg. Was virtio found or installed? *)
df3bb2
 
df3bb2
@@ -257,6 +258,7 @@ and requested_guestcaps = {
df3bb2
 and guestcaps_block_type = Virtio_blk | Virtio_SCSI | IDE
df3bb2
 and guestcaps_net_type = Virtio_net | E1000 | RTL8139
df3bb2
 and guestcaps_video_type = QXL | Cirrus
df3bb2
+and guestcaps_machine = I440FX | Q35 | Virt
df3bb2
 
df3bb2
 val string_of_guestcaps : guestcaps -> string
df3bb2
 val string_of_requested_guestcaps : requested_guestcaps -> string
df3bb2
-- 
df3bb2
2.21.0
df3bb2