[Libguestfs] [PATCH v2 1/2] v2v: fill the list of the EFI system partitions

Pavel Butsykin pbutsykin at virtuozzo.com
Sat Jun 11 10:29:41 UTC 2016


Store the list of EFI system partitions on the inspect object in order  to be
able to tune their contents later in the process.

Signed-off-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
---
 v2v/convert_linux.ml  |  7 +++----
 v2v/inspect_source.ml | 34 +++++++++++++++++++++-------------
 v2v/types.ml          | 12 +++++++++---
 v2v/types.mli         |  8 +++++++-
 v2v/v2v.ml            |  5 ++++-
 v2v/v2v_unit_tests.ml |  2 +-
 6 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index 08b27d6..7eef2ab 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -97,10 +97,9 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
       "/boot/grub/grub.conf", `Grub1;
     ] in
     let locations =
-      if inspect.i_uefi then
-        ("/boot/efi/EFI/redhat/grub.cfg", `Grub2) :: locations
-      else
-        locations in
+      match inspect.i_firmware with
+      | I_UEFI devs -> ("/boot/efi/EFI/redhat/grub.cfg", `Grub2) :: locations
+      | I_BIOS -> locations in
     try
       List.find (
         fun (grub_config, _) -> g#is_file ~followsymlinks:true grub_config
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
index 65dcb88..d25c984 100644
--- a/v2v/inspect_source.ml
+++ b/v2v/inspect_source.ml
@@ -65,11 +65,6 @@ let rec inspect_source root_choice g =
       StringMap.add name (app :: vs) map
   ) StringMap.empty apps in
 
-  (* See if this guest could use UEFI to boot.  It should use GPT and
-   * it should have an EFI System Partition (ESP).
-   *)
-  let uefi = has_uefi_bootable_device g in
-
   let inspect = {
     i_root = root;
     i_type = g#inspect_get_type root;
@@ -84,7 +79,7 @@ let rec inspect_source root_choice g =
     i_mountpoints = mps;
     i_apps = apps;
     i_apps_map = apps_map;
-    i_uefi = uefi
+    i_firmware = get_firmware_bootable_device g;
   } in
   debug "%s" (string_of_inspect inspect);
 
@@ -153,10 +148,12 @@ and reject_if_not_installed_image g root =
   if fmt <> "installed" then
     error (f_"libguestfs thinks this is not an installed operating system (it might be, for example, an installer disk or live CD).  If this is wrong, it is probably a bug in libguestfs.  root=%s fmt=%s") root fmt
 
-and has_uefi_bootable_device g =
+and get_firmware_bootable_device g =
   let rec uefi_ESP_guid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
   and is_uefi_ESP dev { G.part_num = partnum } =
     g#part_get_gpt_type dev (Int32.to_int partnum) = uefi_ESP_guid
+  and part_dev_name dev { G.part_num = partnum } =
+    sprintf "%s%d" dev (Int32.to_int partnum)
   and parttype_is_gpt dev =
     try g#part_get_parttype dev = "gpt"
     with G.Error msg as exn ->
@@ -164,14 +161,25 @@ and has_uefi_bootable_device g =
          if g#last_errno () <> G.Errno.errno_EINVAL then raise exn;
          debug "%s (ignored)" msg;
          false
-  and is_uefi_bootable_device dev =
-    parttype_is_gpt dev && (
-      let partitions = Array.to_list (g#part_list dev) in
-      List.exists (is_uefi_ESP dev) partitions
-    )
+  and is_uefi_bootable_part dev part =
+    parttype_is_gpt dev && is_uefi_ESP dev part
   in
   let devices = Array.to_list (g#list_devices ()) in
-  List.exists is_uefi_bootable_device devices
+  let uefi_list = ref [] in
+
+  List.iter (
+    fun dev ->
+    Array.iter (
+      fun part ->
+      if (is_uefi_bootable_part dev part) then (
+        uefi_list := (part_dev_name dev part) :: !uefi_list
+      )
+    ) (g#part_list dev)
+  ) devices;
+
+  match !uefi_list with
+  | [] -> I_BIOS
+  | devices -> I_UEFI devices
 
 (* If some inspection fields are "unknown", then that indicates a
  * failure in inspection, and we shouldn't continue.  For an example
diff --git a/v2v/types.ml b/v2v/types.ml
index 08e1631..bff03a2 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -301,6 +301,10 @@ let string_of_target_firmware = function
   | TargetBIOS -> "bios"
   | TargetUEFI -> "uefi"
 
+type i_firmware =
+  | I_BIOS
+  | I_UEFI of string list
+
 type inspect = {
   i_root : string;
   i_type : string;
@@ -315,7 +319,7 @@ type inspect = {
   i_mountpoints : (string * string) list;
   i_apps : Guestfs.application2 list;
   i_apps_map : Guestfs.application2 list StringMap.t;
-  i_uefi : bool;
+  i_firmware : i_firmware;
 }
 
 let string_of_inspect inspect =
@@ -330,7 +334,7 @@ i_package_format = %s
 i_package_management = %s
 i_product_name = %s
 i_product_variant = %s
-i_uefi = %b
+i_firmware = %s
 " inspect.i_root
   inspect.i_type
   inspect.i_distro
@@ -341,7 +345,9 @@ i_uefi = %b
   inspect.i_package_management
   inspect.i_product_name
   inspect.i_product_variant
-  inspect.i_uefi
+  (match inspect.i_firmware with
+   | I_BIOS -> "BIOS"
+   | I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ", " devices))
 
 type mpstat = {
   mp_dev : string;
diff --git a/v2v/types.mli b/v2v/types.mli
index dacc991..25420df 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -204,6 +204,10 @@ type target_firmware = TargetBIOS | TargetUEFI
 
 val string_of_target_firmware : target_firmware -> string
 
+type i_firmware =
+  | I_BIOS
+  | I_UEFI of string list
+
 type inspect = {
   i_root : string;                      (** Root device. *)
   i_type : string;                      (** Usual inspection fields. *)
@@ -221,7 +225,9 @@ type inspect = {
     (** This is a map from the app name to the application object.
         Since RPM allows multiple packages with the same name to be
         installed, the value is a list. *)
-  i_uefi : bool;        (** True if the guest could boot with UEFI. *)
+  i_firmware : i_firmware;
+    (** The list of EFI system partitions for the guest with UEFI,
+        otherwise the BIOS identifier. *)
 }
 (** Inspection information. *)
 
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index fe81df5..79b6f04 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -555,7 +555,10 @@ and get_target_firmware inspect guestcaps source output =
     | BIOS -> TargetBIOS
     | UEFI -> TargetUEFI
     | UnknownFirmware ->
-       if inspect.i_uefi then TargetUEFI else TargetBIOS in
+       match inspect.i_firmware with
+       | I_BIOS -> TargetBIOS
+       | I_UEFI devs -> TargetUEFI
+  in
   let supported_firmware = output#supported_firmware in
   if not (List.mem target_firmware supported_firmware) then
     error (f_"this guest cannot run on the target, because the target does not support %s firmware (supported firmware on target: %s)")
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index 95d8430..7b41585 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -30,7 +30,7 @@ let inspect_defaults = {
   i_major_version = 0; i_minor_version = 0;
   i_root = ""; i_package_format = ""; i_package_management = "";
   i_product_name = ""; i_product_variant = ""; i_mountpoints = [];
-  i_apps = []; i_apps_map = StringMap.empty; i_uefi = false
+  i_apps = []; i_apps_map = StringMap.empty; i_firmware = BIOS
 }
 
 let test_get_ostype ctx =
-- 
2.8.3




More information about the Libguestfs mailing list