Blame SOURCES/0063-v2v-bootloaders-search-grub-config-for-all-distribut.patch

151578
From 54c42d18d82ae4c5c0562600b47a7710a583ea07 Mon Sep 17 00:00:00 2001
151578
From: Pavel Butsykin <pbutsykin@virtuozzo.com>
151578
Date: Tue, 2 May 2017 15:35:06 +0300
151578
Subject: [PATCH] v2v: bootloaders: search grub config for all distributions
151578
151578
This patch improves the search of grub config on EFI partition. This
151578
means that the config will be found not only for rhel but also for
151578
many other distributions.  Tests were performed on the following
151578
distributions: centos, fedora, ubuntu, suse. In all cases, the config
151578
path was /boot/efi/EFI/*distname*/grub.cfg
151578
151578
The main purpose of the patch is to improve support for converting of
151578
vm with UEFI for most distributions. Unfortunately this patch does not
151578
solve the problem for all distributions, for example Debian does not
151578
store grub config on the EFI partition, therefore for such
151578
distributions another solution is necessary.
151578
151578
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
151578
(cherry picked from commit a76e9040b20f97eb5c9accbefcbf55999554dc48)
151578
---
151578
 v2v/linux_bootloaders.ml | 76 ++++++++++++++++++++++++++++++------------------
151578
 1 file changed, 48 insertions(+), 28 deletions(-)
151578
151578
diff --git a/v2v/linux_bootloaders.ml b/v2v/linux_bootloaders.ml
151578
index c3fd09ca8..25dab02fe 100644
151578
--- a/v2v/linux_bootloaders.ml
151578
+++ b/v2v/linux_bootloaders.ml
151578
@@ -49,6 +49,13 @@ let remove_hd_prefix path =
151578
 
151578
 (* Grub1 (AKA grub-legacy) representation. *)
151578
 class bootloader_grub1 (g : G.guestfs) inspect grub_config =
151578
+  let () =
151578
+  (* Apply the "grub" lens if it is not handling the file
151578
+   * already -- Augeas < 1.7.0 will error out otherwise.
151578
+   *)
151578
+  if g#aug_ls ("/files" ^ grub_config) = [||] then
151578
+    g#aug_transform "grub" grub_config in
151578
+
151578
   (* Grub prefix?  Usually "/boot". *)
151578
   let grub_prefix =
151578
     let mounts = g#inspect_get_mountpoints inspect.i_root in
151578
@@ -345,33 +352,46 @@ object (self)
151578
 end
151578
 
151578
 let detect_bootloader (g : G.guestfs) inspect =
151578
-  let config_file, typ =
151578
-    let locations = [
151578
-      "/boot/grub2/grub.cfg", Grub2;
151578
-      "/boot/grub/grub.cfg", Grub2;
151578
-      "/boot/grub/menu.lst", Grub1;
151578
-      "/boot/grub/grub.conf", Grub1;
151578
-    ] in
151578
-    let locations =
151578
-      match inspect.i_firmware with
151578
-      | I_UEFI _ ->
151578
-        [
151578
-          "/boot/efi/EFI/redhat/grub.cfg", Grub2;
151578
-          "/boot/efi/EFI/redhat/grub.conf", Grub1;
151578
-        ] @ locations
151578
-      | I_BIOS -> locations in
151578
-    try
151578
-      List.find (
151578
-        fun (config_file, _) -> g#is_file ~followsymlinks:true config_file
151578
-      ) locations
151578
-    with
151578
-      Not_found ->
151578
-        error (f_"no bootloader detected") in
151578
+  (* Where to start searching for bootloaders. *)
151578
+  let mp =
151578
+    match inspect.i_firmware with
151578
+    | I_BIOS -> "/boot"
151578
+    | I_UEFI _ -> "/boot/efi/EFI" in
151578
 
151578
-  match typ with
151578
-  | Grub1 ->
151578
-    if config_file = "/boot/efi/EFI/redhat/grub.conf" then
151578
-      g#aug_transform "grub" "/boot/efi/EFI/redhat/grub.conf";
151578
+  (* Find all paths below the mountpoint, then filter them to find
151578
+   * the grub config file.
151578
+   *)
151578
+  let paths =
151578
+    try List.map ((^) mp) (Array.to_list (g#find mp))
151578
+    with G.Error msg ->
151578
+      error (f_"could not find bootloader mount point (%s): %s") mp msg in
151578
 
151578
-    new bootloader_grub1 g inspect config_file
151578
-  | Grub2 -> new bootloader_grub2 g config_file
151578
+  (* We can determine if the bootloader config file is grub 1 or
151578
+   * grub 2 just by looking at the filename.
151578
+   *)
151578
+  let bootloader_type_of_filename path =
151578
+    match last_part_of path '/' with
151578
+    | Some "grub.cfg" -> Some Grub2
151578
+    | Some ("grub.conf" | "menu.lst") -> Some Grub1
151578
+    | Some _
151578
+    | None -> None
151578
+  in
151578
+
151578
+  let grub_config, typ =
151578
+    let rec loop = function
151578
+      | [] -> error (f_"no bootloader detected")
151578
+      | path :: paths ->
151578
+         match bootloader_type_of_filename path with
151578
+         | None -> loop paths
151578
+         | Some typ ->
151578
+            if not (g#is_file ~followsymlinks:true path) then loop paths
151578
+            else path, typ
151578
+    in
151578
+    loop paths in
151578
+
151578
+  let bl =
151578
+    (match typ with
151578
+     | Grub1 -> new bootloader_grub1 g inspect grub_config
151578
+     | Grub2 -> new bootloader_grub2 g grub_config) in
151578
+  debug "detected bootloader %s at %s" bl#name grub_config;
151578
+  bl
151578
-- 
151578
2.14.3
151578