|
|
ffd6ed |
From 5eda67359f6fa49b3cc1500f0b2dd88811865a69 Mon Sep 17 00:00:00 2001
|
|
|
ffd6ed |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
ffd6ed |
Date: Thu, 30 Apr 2015 15:24:15 +0100
|
|
|
ffd6ed |
Subject: [PATCH] v2v: efi: Support output of UEFI guests, for some output
|
|
|
ffd6ed |
drivers (RHBZ#1184690).
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Add the Types.target_firmware type, which stores our final decision
|
|
|
ffd6ed |
for whether the guest requires BIOS or UEFI on the target.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Not all output modes support UEFI. In order to fail as early as
|
|
|
ffd6ed |
possible if conversion isn't going to be possible, there is an
|
|
|
ffd6ed |
output#supported_firmware method which returns the list of supported
|
|
|
ffd6ed |
target_firmware.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Add the target_firmware parameter to output#create_metadata so it can
|
|
|
ffd6ed |
select the correct firmware in the final metadata.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(cherry picked from commit 40558450dd87190c9dc2649cadbf284ae0a21606)
|
|
|
ffd6ed |
---
|
|
|
ffd6ed |
v2v/output_glance.ml | 7 ++++++-
|
|
|
ffd6ed |
v2v/output_libvirt.ml | 30 ++++++++++++++++++++++++------
|
|
|
ffd6ed |
v2v/output_libvirt.mli | 2 +-
|
|
|
ffd6ed |
v2v/output_local.ml | 6 ++++--
|
|
|
ffd6ed |
v2v/output_null.ml | 4 +++-
|
|
|
ffd6ed |
v2v/output_qemu.ml | 28 +++++++++++++++++++++++++++-
|
|
|
ffd6ed |
v2v/output_rhev.ml | 7 ++++++-
|
|
|
ffd6ed |
v2v/output_vdsm.ml | 7 ++++++-
|
|
|
ffd6ed |
v2v/types.ml | 9 ++++++++-
|
|
|
ffd6ed |
v2v/types.mli | 9 ++++++++-
|
|
|
ffd6ed |
v2v/utils.ml | 29 +++++++++++++++++++++++++++++
|
|
|
ffd6ed |
v2v/v2v.ml | 20 +++++++++++++++++++-
|
|
|
ffd6ed |
v2v/virt-v2v.pod | 31 +++++++++++++++++++++++++++++++
|
|
|
ffd6ed |
13 files changed, 172 insertions(+), 17 deletions(-)
|
|
|
ffd6ed |
|
|
|
ffd6ed |
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
|
|
|
ffd6ed |
index c2fb553..f120cfa 100644
|
|
|
ffd6ed |
--- a/v2v/output_glance.ml
|
|
|
ffd6ed |
+++ b/v2v/output_glance.ml
|
|
|
ffd6ed |
@@ -40,6 +40,8 @@ object
|
|
|
ffd6ed |
|
|
|
ffd6ed |
method as_options = "-o glance"
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
method prepare_targets source targets =
|
|
|
ffd6ed |
(* This does nothing useful except to check that the user has
|
|
|
ffd6ed |
* supplied all the correct auth environment variables to make
|
|
|
ffd6ed |
@@ -60,7 +62,10 @@ object
|
|
|
ffd6ed |
{ t with target_file = target_file }
|
|
|
ffd6ed |
) targets
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps inspect =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps inspect target_firmware =
|
|
|
ffd6ed |
+ (* See #supported_firmware above. *)
|
|
|
ffd6ed |
+ assert (target_firmware = TargetBIOS);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* Upload the disk image (there should only be one - see above). *)
|
|
|
ffd6ed |
let { target_file = target_file; target_format = target_format } =
|
|
|
ffd6ed |
List.hd targets in
|
|
|
ffd6ed |
diff --git a/v2v/output_libvirt.ml b/v2v/output_libvirt.ml
|
|
|
ffd6ed |
index 368f235..48d39e2 100644
|
|
|
ffd6ed |
--- a/v2v/output_libvirt.ml
|
|
|
ffd6ed |
+++ b/v2v/output_libvirt.ml
|
|
|
ffd6ed |
@@ -75,7 +75,8 @@ let append_attr attr = function
|
|
|
ffd6ed |
| PCData _ | Comment _ -> assert false
|
|
|
ffd6ed |
| Element e -> e.e_attrs <- e.e_attrs @ [attr]
|
|
|
ffd6ed |
|
|
|
ffd6ed |
-let create_libvirt_xml ?pool source targets guestcaps target_features =
|
|
|
ffd6ed |
+let create_libvirt_xml ?pool source targets guestcaps
|
|
|
ffd6ed |
+ target_features target_firmware =
|
|
|
ffd6ed |
let memory_k = source.s_memory /^ 1024L in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(* We have the machine features of the guest when it was on the
|
|
|
ffd6ed |
@@ -113,6 +114,23 @@ let create_libvirt_xml ?pool source targets guestcaps target_features =
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let features = List.sort compare (StringSet.elements features) in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ (* The <os> section subelements. *)
|
|
|
ffd6ed |
+ let os_section =
|
|
|
ffd6ed |
+ let loader =
|
|
|
ffd6ed |
+ match target_firmware with
|
|
|
ffd6ed |
+ | TargetBIOS -> []
|
|
|
ffd6ed |
+ | TargetUEFI ->
|
|
|
ffd6ed |
+ (* danpb is proposing that libvirt supports <loader type="efi"/>,
|
|
|
ffd6ed |
+ * (https://bugzilla.redhat.com/show_bug.cgi?id=1217444#c6) but
|
|
|
ffd6ed |
+ * until that day we have to use a bunch of heuristics. XXX
|
|
|
ffd6ed |
+ *)
|
|
|
ffd6ed |
+ let code, vars_template = find_uefi_firmware guestcaps.gcaps_arch in
|
|
|
ffd6ed |
+ [ e "loader" ["type", "pflash"] [ PCData code ];
|
|
|
ffd6ed |
+ e "nvram" ["template", vars_template] [] ] in
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ (e "type" ["arch", guestcaps.gcaps_arch] [PCData "hvm"]) :: loader in
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ (* Disks. *)
|
|
|
ffd6ed |
let disks =
|
|
|
ffd6ed |
let block_prefix =
|
|
|
ffd6ed |
match guestcaps.gcaps_block_bus with
|
|
|
ffd6ed |
@@ -281,9 +299,7 @@ let create_libvirt_xml ?pool source targets guestcaps target_features =
|
|
|
ffd6ed |
e "memory" ["unit", "KiB"] [PCData (Int64.to_string memory_k)];
|
|
|
ffd6ed |
e "currentMemory" ["unit", "KiB"] [PCData (Int64.to_string memory_k)];
|
|
|
ffd6ed |
e "vcpu" [] [PCData (string_of_int source.s_vcpu)];
|
|
|
ffd6ed |
- e "os" [] [
|
|
|
ffd6ed |
- e "type" ["arch", guestcaps.gcaps_arch] [PCData "hvm"];
|
|
|
ffd6ed |
- ];
|
|
|
ffd6ed |
+ e "os" [] os_section;
|
|
|
ffd6ed |
e "features" [] (List.map (fun s -> e s [] []) features);
|
|
|
ffd6ed |
|
|
|
ffd6ed |
e "on_poweroff" [] [PCData "destroy"];
|
|
|
ffd6ed |
@@ -305,6 +321,8 @@ class output_libvirt verbose oc output_pool = object
|
|
|
ffd6ed |
| None -> sprintf "-o libvirt -os %s" output_pool
|
|
|
ffd6ed |
| Some uri -> sprintf "-o libvirt -oc %s -os %s" uri output_pool
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS; TargetUEFI ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
method prepare_targets source targets =
|
|
|
ffd6ed |
(* Get the capabilities from libvirt. *)
|
|
|
ffd6ed |
let cmd =
|
|
|
ffd6ed |
@@ -360,7 +378,7 @@ class output_libvirt verbose oc output_pool = object
|
|
|
ffd6ed |
{ t with target_file = target_file }
|
|
|
ffd6ed |
) targets
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps _ =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps _ target_firmware =
|
|
|
ffd6ed |
(* We copied directly into the final pool directory. However we
|
|
|
ffd6ed |
* have to tell libvirt.
|
|
|
ffd6ed |
*)
|
|
|
ffd6ed |
@@ -385,7 +403,7 @@ class output_libvirt verbose oc output_pool = object
|
|
|
ffd6ed |
(* Create the metadata. *)
|
|
|
ffd6ed |
let doc =
|
|
|
ffd6ed |
create_libvirt_xml ~pool:output_pool source targets
|
|
|
ffd6ed |
- guestcaps target_features in
|
|
|
ffd6ed |
+ guestcaps target_features target_firmware in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let tmpfile, chan = Filename.open_temp_file "v2vlibvirt" ".xml" in
|
|
|
ffd6ed |
DOM.doc_to_chan chan doc;
|
|
|
ffd6ed |
diff --git a/v2v/output_libvirt.mli b/v2v/output_libvirt.mli
|
|
|
ffd6ed |
index da41956..def1b05 100644
|
|
|
ffd6ed |
--- a/v2v/output_libvirt.mli
|
|
|
ffd6ed |
+++ b/v2v/output_libvirt.mli
|
|
|
ffd6ed |
@@ -23,5 +23,5 @@ val output_libvirt : bool -> string option -> string -> Types.output
|
|
|
ffd6ed |
{!Types.output} object specialized for writing output to
|
|
|
ffd6ed |
libvirt. *)
|
|
|
ffd6ed |
|
|
|
ffd6ed |
-val create_libvirt_xml : ?pool:string -> Types.source -> Types.target list -> Types.guestcaps -> string list -> DOM.doc
|
|
|
ffd6ed |
+val create_libvirt_xml : ?pool:string -> Types.source -> Types.target list -> Types.guestcaps -> string list -> Types.target_firmware -> DOM.doc
|
|
|
ffd6ed |
(** This is called from {!Output_local} to generate the libvirt XML. *)
|
|
|
ffd6ed |
diff --git a/v2v/output_local.ml b/v2v/output_local.ml
|
|
|
ffd6ed |
index ffcfad0..3df0769 100644
|
|
|
ffd6ed |
--- a/v2v/output_local.ml
|
|
|
ffd6ed |
+++ b/v2v/output_local.ml
|
|
|
ffd6ed |
@@ -29,6 +29,8 @@ class output_local verbose dir = object
|
|
|
ffd6ed |
|
|
|
ffd6ed |
method as_options = sprintf "-o local -os %s" dir
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS; TargetUEFI ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
method prepare_targets source targets =
|
|
|
ffd6ed |
List.map (
|
|
|
ffd6ed |
fun t ->
|
|
|
ffd6ed |
@@ -36,7 +38,7 @@ class output_local verbose dir = object
|
|
|
ffd6ed |
{ t with target_file = target_file }
|
|
|
ffd6ed |
) targets
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps _ =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps _ target_firmware =
|
|
|
ffd6ed |
(* We don't know what target features the hypervisor supports, but
|
|
|
ffd6ed |
* assume a common set that libvirt supports.
|
|
|
ffd6ed |
*)
|
|
|
ffd6ed |
@@ -48,7 +50,7 @@ class output_local verbose dir = object
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let doc =
|
|
|
ffd6ed |
Output_libvirt.create_libvirt_xml source targets
|
|
|
ffd6ed |
- guestcaps target_features in
|
|
|
ffd6ed |
+ guestcaps target_features target_firmware in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let name = source.s_name in
|
|
|
ffd6ed |
let file = dir // name ^ ".xml" in
|
|
|
ffd6ed |
diff --git a/v2v/output_null.ml b/v2v/output_null.ml
|
|
|
ffd6ed |
index 97495e6..81aaf5f 100644
|
|
|
ffd6ed |
--- a/v2v/output_null.ml
|
|
|
ffd6ed |
+++ b/v2v/output_null.ml
|
|
|
ffd6ed |
@@ -39,6 +39,8 @@ object
|
|
|
ffd6ed |
|
|
|
ffd6ed |
method as_options = "-o null"
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS; TargetUEFI ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
method prepare_targets source targets =
|
|
|
ffd6ed |
List.map (
|
|
|
ffd6ed |
fun t ->
|
|
|
ffd6ed |
@@ -46,7 +48,7 @@ object
|
|
|
ffd6ed |
{ t with target_file = target_file }
|
|
|
ffd6ed |
) targets
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- method create_metadata _ _ _ _ = ()
|
|
|
ffd6ed |
+ method create_metadata _ _ _ _ _ = ()
|
|
|
ffd6ed |
end
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let output_null = new output_null
|
|
|
ffd6ed |
diff --git a/v2v/output_qemu.ml b/v2v/output_qemu.ml
|
|
|
ffd6ed |
index 77152a4..c593030 100644
|
|
|
ffd6ed |
--- a/v2v/output_qemu.ml
|
|
|
ffd6ed |
+++ b/v2v/output_qemu.ml
|
|
|
ffd6ed |
@@ -31,6 +31,8 @@ object
|
|
|
ffd6ed |
method as_options =
|
|
|
ffd6ed |
sprintf "-o qemu -os %s%s" dir (if qemu_boot then " --qemu-boot" else "")
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS; TargetUEFI ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
method prepare_targets source targets =
|
|
|
ffd6ed |
List.map (
|
|
|
ffd6ed |
fun t ->
|
|
|
ffd6ed |
@@ -38,20 +40,44 @@ object
|
|
|
ffd6ed |
{ t with target_file = target_file }
|
|
|
ffd6ed |
) targets
|
|
|
ffd6ed |
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps inspect =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps inspect target_firmware =
|
|
|
ffd6ed |
let name = source.s_name in
|
|
|
ffd6ed |
let file = dir // name ^ ".sh" in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ let uefi_firmware =
|
|
|
ffd6ed |
+ match target_firmware with
|
|
|
ffd6ed |
+ | TargetBIOS -> None
|
|
|
ffd6ed |
+ | TargetUEFI ->
|
|
|
ffd6ed |
+ Some (find_uefi_firmware guestcaps.gcaps_arch) in
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
let chan = open_out file in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
let fpf fs = fprintf chan fs in
|
|
|
ffd6ed |
let nl = " \\\n\t" in
|
|
|
ffd6ed |
fpf "#!/bin/sh -\n";
|
|
|
ffd6ed |
fpf "\n";
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ (match uefi_firmware with
|
|
|
ffd6ed |
+ | None -> ()
|
|
|
ffd6ed |
+ | Some (_, vars_template) ->
|
|
|
ffd6ed |
+ fpf "# Make a copy of the UEFI variables template\n";
|
|
|
ffd6ed |
+ fpf "uefi_vars=\"$(mktemp)\"\n";
|
|
|
ffd6ed |
+ fpf "cp %s \"$uefi_vars\"\n" (quote vars_template);
|
|
|
ffd6ed |
+ fpf "\n"
|
|
|
ffd6ed |
+ );
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
fpf "/usr/libexec/qemu-kvm";
|
|
|
ffd6ed |
fpf "%s-no-user-config -nodefaults" nl;
|
|
|
ffd6ed |
fpf "%s-name %s" nl (quote source.s_name);
|
|
|
ffd6ed |
fpf "%s-machine accel=kvm:tcg" nl;
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+ (match uefi_firmware with
|
|
|
ffd6ed |
+ | None -> ()
|
|
|
ffd6ed |
+ | Some (code, _) ->
|
|
|
ffd6ed |
+ fpf "%s-drive if=pflash,format=raw,file=%s,readonly" nl (quote code);
|
|
|
ffd6ed |
+ fpf "%s-drive if=pflash,format=raw,file=\"$uefi_vars\"" nl
|
|
|
ffd6ed |
+ );
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
fpf "%s-m %Ld" nl (source.s_memory /^ 1024L /^ 1024L);
|
|
|
ffd6ed |
if source.s_vcpu > 1 then
|
|
|
ffd6ed |
fpf "%s-smp %d" nl source.s_vcpu;
|
|
|
ffd6ed |
diff --git a/v2v/output_rhev.ml b/v2v/output_rhev.ml
|
|
|
ffd6ed |
index 0671e14..826bb5f 100644
|
|
|
ffd6ed |
--- a/v2v/output_rhev.ml
|
|
|
ffd6ed |
+++ b/v2v/output_rhev.ml
|
|
|
ffd6ed |
@@ -122,6 +122,8 @@ object
|
|
|
ffd6ed |
| Some `Server -> " --vmtype server"
|
|
|
ffd6ed |
| Some `Desktop -> " --vmtype desktop")
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* RHEV doesn't support serial consoles. This causes the conversion
|
|
|
ffd6ed |
* step to remove it.
|
|
|
ffd6ed |
*)
|
|
|
ffd6ed |
@@ -276,7 +278,10 @@ object
|
|
|
ffd6ed |
)
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(* This is called after conversion to write the OVF metadata. *)
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps inspect =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps inspect target_firmware =
|
|
|
ffd6ed |
+ (* See #supported_firmware above. *)
|
|
|
ffd6ed |
+ assert (target_firmware = TargetBIOS);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* Create the metadata. *)
|
|
|
ffd6ed |
let ovf = OVF.create_ovf verbose source targets guestcaps inspect
|
|
|
ffd6ed |
output_alloc vmtype esd_uuid image_uuids vol_uuids vm_uuid in
|
|
|
ffd6ed |
diff --git a/v2v/output_vdsm.ml b/v2v/output_vdsm.ml
|
|
|
ffd6ed |
index c7a243e..35edeb5 100644
|
|
|
ffd6ed |
--- a/v2v/output_vdsm.ml
|
|
|
ffd6ed |
+++ b/v2v/output_vdsm.ml
|
|
|
ffd6ed |
@@ -50,6 +50,8 @@ object
|
|
|
ffd6ed |
| Some `Server -> " --vmtype server"
|
|
|
ffd6ed |
| Some `Desktop -> " --vmtype desktop")
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ method supported_firmware = [ TargetBIOS ]
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* RHEV doesn't support serial consoles. This causes the conversion
|
|
|
ffd6ed |
* step to remove it.
|
|
|
ffd6ed |
*)
|
|
|
ffd6ed |
@@ -163,7 +165,10 @@ object
|
|
|
ffd6ed |
?clustersize path format size
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(* This is called after conversion to write the OVF metadata. *)
|
|
|
ffd6ed |
- method create_metadata source targets guestcaps inspect =
|
|
|
ffd6ed |
+ method create_metadata source targets guestcaps inspect target_firmware =
|
|
|
ffd6ed |
+ (* See #supported_firmware above. *)
|
|
|
ffd6ed |
+ assert (target_firmware = TargetBIOS);
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* Create the metadata. *)
|
|
|
ffd6ed |
let ovf = OVF.create_ovf verbose source targets guestcaps inspect
|
|
|
ffd6ed |
output_alloc vmtype dd_uuid
|
|
|
ffd6ed |
diff --git a/v2v/types.ml b/v2v/types.ml
|
|
|
ffd6ed |
index 01c65a3..41d2686 100644
|
|
|
ffd6ed |
--- a/v2v/types.ml
|
|
|
ffd6ed |
+++ b/v2v/types.ml
|
|
|
ffd6ed |
@@ -216,6 +216,12 @@ target_overlay.ov_source = %s
|
|
|
ffd6ed |
t.target_overlay.ov_overlay_file
|
|
|
ffd6ed |
t.target_overlay.ov_source.s_qemu_uri
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+type target_firmware = TargetBIOS | TargetUEFI
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+let string_of_target_firmware = function
|
|
|
ffd6ed |
+ | TargetBIOS -> "bios"
|
|
|
ffd6ed |
+ | TargetUEFI -> "uefi"
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
type inspect = {
|
|
|
ffd6ed |
i_root : string;
|
|
|
ffd6ed |
i_type : string;
|
|
|
ffd6ed |
@@ -305,8 +311,9 @@ end
|
|
|
ffd6ed |
class virtual output verbose = object
|
|
|
ffd6ed |
method virtual as_options : string
|
|
|
ffd6ed |
method virtual prepare_targets : source -> target list -> target list
|
|
|
ffd6ed |
+ method virtual supported_firmware : target_firmware list
|
|
|
ffd6ed |
method check_target_free_space (_ : source) (_ : target list) = ()
|
|
|
ffd6ed |
method disk_create = (new Guestfs.guestfs ())#disk_create
|
|
|
ffd6ed |
- method virtual create_metadata : source -> target list -> guestcaps -> inspect -> unit
|
|
|
ffd6ed |
+ method virtual create_metadata : source -> target list -> guestcaps -> inspect -> target_firmware -> unit
|
|
|
ffd6ed |
method keep_serial_console = true
|
|
|
ffd6ed |
end
|
|
|
ffd6ed |
diff --git a/v2v/types.mli b/v2v/types.mli
|
|
|
ffd6ed |
index 9fc9e29..da398d3 100644
|
|
|
ffd6ed |
--- a/v2v/types.mli
|
|
|
ffd6ed |
+++ b/v2v/types.mli
|
|
|
ffd6ed |
@@ -133,6 +133,10 @@ type target = {
|
|
|
ffd6ed |
|
|
|
ffd6ed |
val string_of_target : target -> string
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+type target_firmware = TargetBIOS | TargetUEFI
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+val string_of_target_firmware : target_firmware -> string
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
type inspect = {
|
|
|
ffd6ed |
i_root : string; (** Root device. *)
|
|
|
ffd6ed |
i_type : string; (** Usual inspection fields. *)
|
|
|
ffd6ed |
@@ -195,10 +199,13 @@ class virtual output : bool -> object
|
|
|
ffd6ed |
This is just used for pretty-printing log messages. *)
|
|
|
ffd6ed |
method virtual prepare_targets : source -> target list -> target list
|
|
|
ffd6ed |
(** Called before conversion to prepare the output. *)
|
|
|
ffd6ed |
+ method virtual supported_firmware : target_firmware list
|
|
|
ffd6ed |
+ (** Does this output method support UEFI? Allows us to abort early if
|
|
|
ffd6ed |
+ conversion is impossible. *)
|
|
|
ffd6ed |
method check_target_free_space : source -> target list -> unit
|
|
|
ffd6ed |
(** Called before conversion. Can be used to check there is enough space
|
|
|
ffd6ed |
on the target, using the [target.target_estimated_size] field. *)
|
|
|
ffd6ed |
- method virtual create_metadata : source -> target list -> guestcaps -> inspect -> unit
|
|
|
ffd6ed |
+ method virtual create_metadata : source -> target list -> guestcaps -> inspect -> target_firmware -> unit
|
|
|
ffd6ed |
(** Called after conversion to finish off and create metadata. *)
|
|
|
ffd6ed |
method disk_create : ?backingfile:string -> ?backingformat:string -> ?preallocation:string -> ?compat:string -> ?clustersize:int -> string -> string -> int64 -> unit
|
|
|
ffd6ed |
(** Called in order to create disks on the target. The method has the
|
|
|
ffd6ed |
diff --git a/v2v/utils.ml b/v2v/utils.ml
|
|
|
ffd6ed |
index 477033d..e9d3262 100644
|
|
|
ffd6ed |
--- a/v2v/utils.ml
|
|
|
ffd6ed |
+++ b/v2v/utils.ml
|
|
|
ffd6ed |
@@ -84,6 +84,35 @@ let qemu_supports_sound_card = function
|
|
|
ffd6ed |
| USBAudio
|
|
|
ffd6ed |
-> false
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+(* Find the UEFI firmware. *)
|
|
|
ffd6ed |
+let find_uefi_firmware guest_arch =
|
|
|
ffd6ed |
+ let files =
|
|
|
ffd6ed |
+ match guest_arch with
|
|
|
ffd6ed |
+ | "i386" | "i486" | "i586" | "i686" ->
|
|
|
ffd6ed |
+ [ "/usr/share/edk2.git/ovmf-ia32/OVMF_CODE-pure-efi.fd",
|
|
|
ffd6ed |
+ "/usr/share/edk2.git/ovmf-ia32/OVMF_VARS-pure-efi.fd" ]
|
|
|
ffd6ed |
+ | "x86_64" ->
|
|
|
ffd6ed |
+ [ "/usr/share/OVMF/OVMF_CODE.fd",
|
|
|
ffd6ed |
+ "/usr/share/OVMF/OVMF_VARS.fd";
|
|
|
ffd6ed |
+ "/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd",
|
|
|
ffd6ed |
+ "/usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd" ]
|
|
|
ffd6ed |
+ | "aarch64" ->
|
|
|
ffd6ed |
+ [ "/usr/share/AAVMF/AAVMF_CODE.fd",
|
|
|
ffd6ed |
+ "/usr/share/AAVMF/AAVMF_VARS.fd";
|
|
|
ffd6ed |
+ "/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw",
|
|
|
ffd6ed |
+ "/usr/share/edk2.git/aarch64/vars-template-pflash.raw" ]
|
|
|
ffd6ed |
+ | arch ->
|
|
|
ffd6ed |
+ error (f_"don't know how to convert UEFI guests for architecture %s")
|
|
|
ffd6ed |
+ guest_arch in
|
|
|
ffd6ed |
+ let rec loop = function
|
|
|
ffd6ed |
+ | [] ->
|
|
|
ffd6ed |
+ error (f_"cannot find firmware for UEFI guests.\n\nYou probably need to install OVMF, or Gerd's firmware repo (https://www.kraxel.org/repos/), or AAVMF (if using aarch64)")
|
|
|
ffd6ed |
+ | ((code, vars_template) as ret) :: rest ->
|
|
|
ffd6ed |
+ if Sys.file_exists code && Sys.file_exists vars_template then ret
|
|
|
ffd6ed |
+ else loop rest
|
|
|
ffd6ed |
+ in
|
|
|
ffd6ed |
+ loop files
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
let compare_app2_versions app1 app2 =
|
|
|
ffd6ed |
let i = compare app1.Guestfs.app2_epoch app2.Guestfs.app2_epoch in
|
|
|
ffd6ed |
if i <> 0 then i
|
|
|
ffd6ed |
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
|
|
|
ffd6ed |
index eb1c66e..859b92a 100644
|
|
|
ffd6ed |
--- a/v2v/v2v.ml
|
|
|
ffd6ed |
+++ b/v2v/v2v.ml
|
|
|
ffd6ed |
@@ -217,6 +217,24 @@ let rec main () =
|
|
|
ffd6ed |
msg (f_"Inspecting the overlay");
|
|
|
ffd6ed |
let inspect = inspect_source ~verbose g root_choice in
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+ (* Does the guest require UEFI on the target? *)
|
|
|
ffd6ed |
+ let target_firmware =
|
|
|
ffd6ed |
+ match source.s_firmware with
|
|
|
ffd6ed |
+ | BIOS -> TargetBIOS
|
|
|
ffd6ed |
+ | UEFI -> TargetUEFI
|
|
|
ffd6ed |
+ | UnknownFirmware ->
|
|
|
ffd6ed |
+ if inspect.i_uefi then TargetUEFI else TargetBIOS in
|
|
|
ffd6ed |
+ let supported_firmware = output#supported_firmware in
|
|
|
ffd6ed |
+ if not (List.mem target_firmware supported_firmware) then
|
|
|
ffd6ed |
+ error (f_"this guest cannot run on the target, because the target does not support %s firmware (supported firmware on target: %s)")
|
|
|
ffd6ed |
+ (string_of_target_firmware target_firmware)
|
|
|
ffd6ed |
+ (String.concat " "
|
|
|
ffd6ed |
+ (List.map string_of_target_firmware supported_firmware));
|
|
|
ffd6ed |
+ (match target_firmware with
|
|
|
ffd6ed |
+ | TargetBIOS -> ()
|
|
|
ffd6ed |
+ | TargetUEFI ->
|
|
|
ffd6ed |
+ info ~prog (f_"This guest requires UEFI on the target to boot."));
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
(* The guest free disk space check and the target free space
|
|
|
ffd6ed |
* estimation both require statvfs information from mountpoints, so
|
|
|
ffd6ed |
* get that information first.
|
|
|
ffd6ed |
@@ -409,7 +427,7 @@ let rec main () =
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(* Create output metadata. *)
|
|
|
ffd6ed |
msg (f_"Creating output metadata");
|
|
|
ffd6ed |
- output#create_metadata source targets guestcaps inspect;
|
|
|
ffd6ed |
+ output#create_metadata source targets guestcaps inspect target_firmware;
|
|
|
ffd6ed |
|
|
|
ffd6ed |
(* Save overlays if --debug-overlays option was used. *)
|
|
|
ffd6ed |
if debug_overlays then (
|
|
|
ffd6ed |
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
|
|
|
ffd6ed |
index 5ee3bd8..7d24ceb 100644
|
|
|
ffd6ed |
--- a/v2v/virt-v2v.pod
|
|
|
ffd6ed |
+++ b/v2v/virt-v2v.pod
|
|
|
ffd6ed |
@@ -699,6 +699,37 @@ loaded.
|
|
|
ffd6ed |
|
|
|
ffd6ed |
=back
|
|
|
ffd6ed |
|
|
|
ffd6ed |
+=head1 UEFI
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+VMware allows you to present UEFI firmware to guests (instead of the
|
|
|
ffd6ed |
+ordinary PC BIOS). Virt-v2v can convert these guests, but requires
|
|
|
ffd6ed |
+that UEFI is supported by the target hypervisor.
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+Currently KVM supports OVMF, a partially open source UEFI firmware,
|
|
|
ffd6ed |
+and can run these guests.
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+Since OVMF support was only recently added to KVM (in 2014/2015), not
|
|
|
ffd6ed |
+all target environments support UEFI guests yet:
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+=over 4
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+=item UEFI on libvirt, qemu
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+Supported. Virt-v2v will generate the correct libvirt XML (metadata)
|
|
|
ffd6ed |
+automatically, but note that the same version of OVMF must be
|
|
|
ffd6ed |
+installed on the conversion host as is installed on the target
|
|
|
ffd6ed |
+hypervisor, else you will have to adjust paths in the metadata.
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+=item UEFI on OpenStack
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+Not supported.
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+=item UEFI on RHEV
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+Not supported.
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
+=back
|
|
|
ffd6ed |
+
|
|
|
ffd6ed |
=head1 NETWORKS AND BRIDGES
|
|
|
ffd6ed |
|
|
|
ffd6ed |
Guests are usually connected to one or more networks, and when
|
|
|
ffd6ed |
--
|
|
|
ffd6ed |
1.8.3.1
|
|
|
ffd6ed |
|