On Wednesday, 19 April 2017 15:58:57 CEST Pavel Butsykin wrote:
> This patch improves the search of grub config on EFI partition. This
> means that the config will be found not only for rhel but also for
> many other distributions.  Tests were performed on the following
> distributions: centos, fedora, ubuntu, suse. In all cases, the config
> path was /boot/efi/EFI/*distname*/grub.cfg
> 
> The main purpose of the patch is to improve support for converting of
> vm with UEFI for most distributions. Unfortunately this patch does not
> solve the problem for all distributions, for example Debian does not
> store grub config on the EFI partition, therefore for such
> distributions another solution is necessary.
> 
> Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com>
> Signed-off-by: Richard W.M. Jones <rjo...@redhat.com>
> ---
>  v2v/linux_bootloaders.ml | 86 
> +++++++++++++++++++++++++++++++-----------------
>  1 file changed, 55 insertions(+), 31 deletions(-)
> 
> diff --git a/v2v/linux_bootloaders.ml b/v2v/linux_bootloaders.ml
> index cad72a829..593797f4e 100644
> --- a/v2v/linux_bootloaders.ml
> +++ b/v2v/linux_bootloaders.ml
> @@ -42,6 +42,10 @@ type bootloader_type =
>    | Grub1
>    | Grub2
>  
> +let string_of_bootloader_type = function
> +  | Grub1 -> "Grub1"
> +  | Grub2 -> "Grub2"
> +
>  (* Helper function for SUSE: remove (hdX,X) prefix from a path. *)
>  let remove_hd_prefix path =
>    let rex = Str.regexp "^(hd.*)\\(.*\\)" in
> @@ -49,6 +53,13 @@ let remove_hd_prefix path =
>  
>  (* Grub1 (AKA grub-legacy) representation. *)
>  class bootloader_grub1 (g : G.guestfs) inspect grub_config =
> +    let () =

Wrong indentation here.

> +    (* Apply the "grub" lens if it is not handling the file
> +     * already -- Augeas < 1.7.0 will error out otherwise.
> +     *)
> +    if g#aug_ls ("/files" ^ grub_config) = [||] then
> +      g#aug_transform "grub" grub_config in
> +
>    (* Grub prefix?  Usually "/boot". *)
>    let grub_prefix =
>      let mounts = g#inspect_get_mountpoints inspect.i_root in
> @@ -191,7 +202,7 @@ type default_kernel_method =
>    | MethodNone  (** No known way. *)
>  
>  (* Grub2 representation. *)
> -class bootloader_grub2 (g : G.guestfs) grub_config =
> +class bootloader_grub2 (g : G.guestfs) inspect grub_config =

NACK, see below.

>  
>    let grub2_mkconfig_cmd =
>      let elems = [
> @@ -335,33 +346,46 @@ object (self)
>  end
>  
>  let detect_bootloader (g : G.guestfs) inspect =
> -  let config_file, typ =
> -    let locations = [
> -      "/boot/grub2/grub.cfg", Grub2;
> -      "/boot/grub/grub.cfg", Grub2;
> -      "/boot/grub/menu.lst", Grub1;
> -      "/boot/grub/grub.conf", Grub1;
> -    ] in
> -    let locations =
> -      match inspect.i_firmware with
> -      | I_UEFI _ ->
> -        [
> -          "/boot/efi/EFI/redhat/grub.cfg", Grub2;
> -          "/boot/efi/EFI/redhat/grub.conf", Grub1;
> -        ] @ locations
> -      | I_BIOS -> locations in
> -    try
> -      List.find (
> -        fun (config_file, _) -> g#is_file ~followsymlinks:true config_file
> -      ) locations
> -    with
> -      Not_found ->
> -        error (f_"no bootloader detected") in
> -
> -  match typ with
> -  | Grub1 ->
> -    if config_file = "/boot/efi/EFI/redhat/grub.conf" then
> -      g#aug_transform "grub" "/boot/efi/EFI/redhat/grub.conf";
> -
> -    new bootloader_grub1 g inspect config_file
> -  | Grub2 -> new bootloader_grub2 g config_file
> +  (* Where to start searching for bootloaders. *)
> +  let mp =
> +    match inspect.i_firmware with
> +    | I_BIOS -> "/boot"
> +    | I_UEFI _ -> "/boot/efi/EFI" in
> +
> +  (* Find all paths below the mountpoint, then filter them to find
> +   * the grub config file.
> +   *)
> +  let paths =
> +    try List.map ((^) mp) (Array.to_list (g#find mp))
> +    with G.Error msg ->
> +      error (f_"could not find bootloader mount point (%s): %s") mp msg in
> +
> +  (* We can determine if the bootloader config file is grub 1 or
> +   * grub 2 just by looking at the filename.
> +   *)
> +  let bootloader_type_of_filename path =
> +    match last_part_of path '/' with
> +    | Some "grub.cfg" -> Some Grub2
> +    | Some ("grub.conf" | "menu.lst") -> Some Grub1
> +    | Some _
> +    | None -> None
> +  in
> +
> +  let grub_config, typ =
> +    let rec loop = function
> +      | [] -> error (f_"no bootloader detected")
> +      | path :: paths ->
> +         match bootloader_type_of_filename path with
> +         | None -> loop paths
> +         | Some typ ->
> +            if not (g#is_file ~followsymlinks:true path) then loop paths
> +            else path, typ
> +    in
> +    loop paths in
> +
> +  debug "detected bootloader %s at %s"
> +        (string_of_bootloader_type typ) grub_config;

You don't need string_of_bootloader_type, there's already the #name
method of the bootloader object.  The only change would be moving this
message after the creation of the bootloader subclass.

Another option is adding a new virtual method to the bootloader object,
something like output#as_options, e.g.
  method debug = "grub1(" ^ grub_config ^ ")"
so you can change the code to be:

  let bl =
    match typ with
    | Grub1 -> new bootloader_grub1 g inspect config_file
    | Grub2 -> new bootloader_grub2 g config_file in
  debug "detected bootloader: %s" bl#debug;

> +  (match typ with
> +   | Grub1 -> new bootloader_grub1
> +   | Grub2 -> new bootloader_grub2) g inspect grub_config

Just leave the current way, which is more readable.

Thanks,
-- 
Pino Toscano

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs

Reply via email to