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

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