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

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