[Libguestfs] [PATCH v2] v2v: factor out bootloader handling
Richard W.M. Jones
rjones at redhat.com
Mon Aug 15 15:26:51 UTC 2016
On Mon, Aug 15, 2016 at 04:48:29PM +0200, Pino Toscano wrote:
> Create an object hierarchy to represent different bootloaders for Linux
> guests, moving the separate handling of grub1 and grub2 in different
> classes: this isolates the code for each type of bootloader together,
> instead of scattering it all around.
>
> This is mostly code refactoring, with no actual behaviour change.
> ---
> po/POTFILES-ml | 1 +
> v2v/Makefile.am | 2 +
> v2v/bootloaders.ml | 317 +++++++++++++++++++++++++++++++++++++++++++++++++++
> v2v/bootloaders.mli | 44 +++++++
Is this really "bootloaders"? It's more like "linux_bootloaders",
unless this might one day be extended to include NTLDR.
> +class virtual bootloader = object
> + method virtual name : string
> + method virtual augeas_device_patterns : string list
> + method virtual list_kernels : unit -> string list
> + method virtual set_default_kernel : string -> unit
> + method set_augeas_configuration () = false
> + method virtual configure_console : unit -> unit
> + method virtual remove_console : unit -> unit
> + method update () = ()
> +end
I think you'll also find that you don't need to use inheritance at
all. You can just declare bootloader as a class type and declare two
(unrelated) classes which implement the class type. They won't be
able to inherit the two trivial non-virtual functions, but IMHO that's
a feature.
I still don't much see the point versus an implementation which used a
type Bootloader.t declared as:
type t = Grub1 of <any local data grub1 needs>
| Grub2 of <any local data grub2 needs>
(and not exposed through the mli file). As this is to some extent my
personal preference, I'll let it slide.
I checked all of the code and it appears to be correct and there is
nothing omitted from the current implementation.
Rich.
> +(* Helper type used in detect_bootloader. *)
> +type bootloader_type =
> + | Grub1
> + | Grub2
> +
> +(* Helper function for SUSE: remove (hdX,X) prefix from a path. *)
> +let remove_hd_prefix path =
> + let rex = Str.regexp "^(hd.*)\\(.*\\)" in
> + Str.replace_first rex "\\1" path
> +
> +(* Grub1 (AKA grub-legacy) representation. *)
> +class bootloader_grub1 (g : G.guestfs) inspect grub_config =
> + (* Grub prefix? Usually "/boot". *)
> + let grub_prefix =
> + let mounts = g#inspect_get_mountpoints inspect.i_root in
> + try
> + List.find (
> + fun path -> List.mem_assoc path mounts
> + ) [ "/boot/grub"; "/boot" ]
> + with Not_found -> "" in
> +object
> + inherit bootloader
> +
> + method name = "grub1"
> +
> + method augeas_device_patterns = [
> + "/files" ^ grub_config ^ "/*/kernel/root";
> + "/files" ^ grub_config ^ "/*/kernel/resume";
> + "/files/boot/grub/device.map/*[label() != \"#comment\"]";
> + "/files/etc/sysconfig/grub/boot";
> + ]
> +
> + method list_kernels () =
> + let paths =
> + let expr = sprintf "/files%s/title/kernel" grub_config in
> + let paths = g#aug_match expr in
> + let paths = Array.to_list paths in
> +
> + (* Remove duplicates. *)
> + let paths = remove_duplicates paths in
> +
> + (* Get the default kernel from grub if it's set. *)
> + let default =
> + let expr = sprintf "/files%s/default" grub_config in
> + try
> + let idx = g#aug_get expr in
> + let idx = int_of_string idx in
> + (* Grub indices are zero-based, augeas is 1-based. *)
> + let expr =
> + sprintf "/files%s/title[%d]/kernel" grub_config (idx+1) in
> + Some expr
> + with G.Error msg
> + when String.find msg "aug_get: no matching node" >= 0 ->
> + None in
> +
> + (* If a default kernel was set, put it at the beginning of the paths
> + * list. If not set, assume the first kernel always boots (?)
> + *)
> + match default with
> + | None -> paths
> + | Some p -> p :: List.filter ((<>) p) paths in
> +
> + (* Resolve the Augeas paths to kernel filenames. *)
> + let vmlinuzes = List.map g#aug_get paths in
> +
> + (* Make sure kernel does not begin with (hdX,X). *)
> + let vmlinuzes = List.map remove_hd_prefix vmlinuzes in
> +
> + (* Prepend grub filesystem. *)
> + List.map ((^) grub_prefix) vmlinuzes
> +
> + method set_default_kernel vmlinuz =
> + if not (String.is_prefix vmlinuz grub_prefix) then
> + error (f_"kernel %s is not under grub tree %s")
> + vmlinuz grub_prefix;
> + let kernel_under_grub_prefix =
> + let prefix_len = String.length grub_prefix in
> + let kernel_len = String.length vmlinuz in
> + String.sub vmlinuz prefix_len (kernel_len - prefix_len) in
> +
> + (* Find the grub entry for the given kernel. *)
> + let paths = g#aug_match (sprintf "/files%s/title/kernel[. = '%s']"
> + grub_config kernel_under_grub_prefix) in
> + let paths = Array.to_list paths in
> + if paths = [] then
> + error (f_"didn't find grub entry for kernel %s") vmlinuz;
> + let path = List.hd paths in
> + let rex = Str.regexp ".*/title\\[\\([1-9][0-9]*\\)\\]/kernel" in
> + if not (Str.string_match rex path 0) then
> + error (f_"internal error: regular expression did not match '%s'")
> + path;
> + let index = int_of_string (Str.matched_group 1 path) - 1 in
> + g#aug_set (sprintf "/files%s/default" grub_config) (string_of_int index);
> + g#aug_save ()
> +
> + method set_augeas_configuration () =
> + let incls = g#aug_match "/augeas/load/Grub/incl" in
> + let incls = Array.to_list incls in
> + let incls_contains_conf =
> + List.exists (fun incl -> g#aug_get incl = grub_config) incls in
> + if not incls_contains_conf then (
> + g#aug_set "/augeas/load/Grub/incl[last()+1]" grub_config;
> + true;
> + ) else false
> +
> + method configure_console () =
> + let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
> + let expr = sprintf "/files%s/title/kernel/console" grub_config in
> +
> + let paths = g#aug_match expr in
> + let paths = Array.to_list paths in
> + List.iter (
> + fun path ->
> + let console = g#aug_get path in
> + if Str.string_match rex console 0 then (
> + let console = Str.global_replace rex "\\1ttyS0\\3" console in
> + g#aug_set path console
> + )
> + ) paths;
> +
> + g#aug_save ()
> +
> + method remove_console () =
> + let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
> + let expr = sprintf "/files%s/title/kernel/console" grub_config in
> +
> + let rec loop = function
> + | [] -> ()
> + | path :: paths ->
> + let console = g#aug_get path in
> + if Str.string_match rex console 0 then (
> + ignore (g#aug_rm path);
> + (* All the paths are invalid, restart the loop. *)
> + let paths = g#aug_match expr in
> + let paths = Array.to_list paths in
> + loop paths
> + )
> + else
> + loop paths
> + in
> + let paths = g#aug_match expr in
> + let paths = Array.to_list paths in
> + loop paths;
> +
> + g#aug_save ()
> +end
> +
> +(* Grub2 representation. *)
> +class bootloader_grub2 (g : G.guestfs) grub_config =
> + let grub2_update_console ~remove =
> + let rex = Str.regexp "\\(.*\\)\\bconsole=[xh]vc0\\b\\(.*\\)" in
> +
> + let paths = [
> + "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX";
> + "/files/etc/default/grub/GRUB_CMDLINE_LINUX";
> + "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT"
> + ] in
> + let paths = List.map g#aug_match paths in
> + let paths = List.map Array.to_list paths in
> + let paths = List.flatten paths in
> + match paths with
> + | [] ->
> + if not remove then
> + warning (f_"could not add grub2 serial console (ignored)")
> + else
> + warning (f_"could not remove grub2 serial console (ignored)")
> + | path :: _ ->
> + let grub_cmdline = g#aug_get path in
> + if Str.string_match rex grub_cmdline 0 then (
> + let new_grub_cmdline =
> + if not remove then
> + Str.global_replace rex "\\1console=ttyS0\\2" grub_cmdline
> + else
> + Str.global_replace rex "\\1\\2" grub_cmdline in
> + g#aug_set path new_grub_cmdline;
> + g#aug_save ();
> +
> + try
> + ignore (g#command [| "grub2-mkconfig"; "-o"; grub_config |])
> + with
> + G.Error msg ->
> + warning (f_"could not rebuild grub2 configuration file (%s). This may mean that grub output will not be sent to the serial port, but otherwise should be harmless. Original error message: %s")
> + grub_config msg
> + ) in
> +object
> + inherit bootloader
> +
> + method name = "grub2"
> +
> + method augeas_device_patterns = [
> + "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX";
> + "/files/etc/default/grub/GRUB_CMDLINE_LINUX";
> + "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT";
> + "/files/boot/grub2/device.map/*[label() != \"#comment\"]";
> + ]
> +
> + method list_kernels () =
> + let get_default_image () =
> + let cmd =
> + if g#exists "/sbin/grubby" then
> + [| "grubby"; "--default-kernel" |]
> + else
> + [| "/usr/bin/perl"; "-MBootloader::Tools"; "-e"; "
> + InitLibrary();
> + my $default = Bootloader::Tools::GetDefaultSection();
> + print $default->{image};
> + " |] in
> + match g#command cmd with
> + | "" -> None
> + | k ->
> + let len = String.length k in
> + let k =
> + if len > 0 && k.[len-1] = '\n' then
> + String.sub k 0 (len-1)
> + else k in
> + Some (remove_hd_prefix k)
> + in
> +
> + let vmlinuzes =
> + (match get_default_image () with
> + | None -> []
> + | Some k -> [k]) @
> + (* This is how the grub2 config generator enumerates kernels. *)
> + Array.to_list (g#glob_expand "/boot/kernel-*") @
> + Array.to_list (g#glob_expand "/boot/vmlinuz-*") @
> + Array.to_list (g#glob_expand "/vmlinuz-*") in
> + let rex = Str.regexp ".*\\.\\(dpkg-.*|rpmsave|rpmnew\\)$" in
> + let vmlinuzes = List.filter (
> + fun file -> not (Str.string_match rex file 0)
> + ) vmlinuzes in
> + vmlinuzes
> +
> + method set_default_kernel vmlinuz =
> + let cmd =
> + if g#exists "/sbin/grubby" then
> + [| "grubby"; "--set-default"; vmlinuz |]
> + else
> + [| "/usr/bin/perl"; "-MBootloader::Tools"; "-e"; sprintf "
> + InitLibrary();
> + my @sections = GetSectionList(type=>image, image=>\"%s\");
> + my $section = GetSection(@sections);
> + my $newdefault = $section->{name};
> + SetGlobals(default, \"$newdefault\");
> + " vmlinuz |] in
> + ignore (g#command cmd)
> +
> + method configure_console () =
> + grub2_update_console ~remove:false
> +
> + method remove_console () =
> + grub2_update_console ~remove:true
> +
> + method update () =
> + ignore (g#command [| "grub2-mkconfig"; "-o"; grub_config |])
> +end
> +
> +let detect_bootloader (g : G.guestfs) inspect =
> + let config_file, typ =
> + let locations = [
> + "/boot/grub2/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) :: locations
> + | I_BIOS -> locations in
> + try
> + List.find (
> + fun (grub_config, _) -> g#is_file ~followsymlinks:true grub_config
> + ) locations
> + with
> + Not_found ->
> + error (f_"no bootloader detected") in
> +
> + match typ with
> + | Grub1 -> new bootloader_grub1 g inspect config_file
> + | Grub2 -> new bootloader_grub2 g config_file
> diff --git a/v2v/bootloaders.mli b/v2v/bootloaders.mli
> new file mode 100644
> index 0000000..477312b
> --- /dev/null
> +++ b/v2v/bootloaders.mli
> @@ -0,0 +1,44 @@
> +(* virt-v2v
> + * Copyright (C) 2009-2016 Red Hat Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *)
> +
> +class virtual bootloader : object
> + method virtual name : string
> + (** The name of the bootloader. *)
> + method virtual augeas_device_patterns : string list
> + (** A list of augeas patterns to search for device names. *)
> + method virtual list_kernels : unit -> string list
> + (** Lists all the kernels configured in the bootloader. *)
> + method virtual set_default_kernel : string -> unit
> + (** Sets the specified vmlinuz path as default bootloader entry. *)
> + method set_augeas_configuration : unit -> bool
> + (** Checks whether augeas is reading the configuration file
> + of the bootloader, and if not then add it.
> +
> + Returns whether augeas needs to be reloaded. *)
> + method virtual configure_console : unit -> unit
> + (** Sets up the console for the available kernels. *)
> + method virtual remove_console : unit -> unit
> + (** Removes the console in all the available kernels. *)
> + method update : unit -> unit
> + (** Update the bootloader. *)
> +end
> +(** Encapsulates a UNIX boot loader as object. *)
> +
> +val detect_bootloader : Guestfs.guestfs -> Types.inspect -> bootloader
> +(** Detects the bootloader on the guest, and creates the object
> + representing it. *)
> diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
> index f9aa334..77d9d8e 100644
> --- a/v2v/convert_linux.ml
> +++ b/v2v/convert_linux.ml
> @@ -89,36 +89,8 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> let dbfiles = Array.to_list dbfiles in
> List.iter g#rm_f dbfiles;
>
> - (* What grub is installed? *)
> - let grub_config, grub =
> - let locations = [
> - "/boot/grub2/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) :: locations
> - | I_BIOS -> locations in
> - try
> - List.find (
> - fun (grub_config, _) -> g#is_file ~followsymlinks:true grub_config
> - ) locations
> - with
> - Not_found ->
> - error (f_"no grub1/grub-legacy or grub2 configuration file was found") in
> -
> - (* Grub prefix? Usually "/boot". *)
> - let grub_prefix =
> - match grub with
> - | `Grub2 -> ""
> - | `Grub1 ->
> - let mounts = g#inspect_get_mountpoints inspect.i_root in
> - try
> - List.find (
> - fun path -> List.mem_assoc path mounts
> - ) [ "/boot/grub"; "/boot" ]
> - with Not_found -> "" in
> + (* Detect the installed bootloader. *)
> + let bootloader = Bootloaders.detect_bootloader g inspect in
>
> (* What kernel/kernel-like packages are installed on the current guest? *)
> let installed_kernels : kernel_info list =
> @@ -269,88 +241,7 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> * list is the default booting kernel.
> *)
> let grub_kernels : kernel_info list =
> - (* Helper function for SUSE: remove (hdX,X) prefix from a path. *)
> - let remove_hd_prefix =
> - let rex = Str.regexp "^(hd.*)\\(.*\\)" in
> - Str.replace_first rex "\\1"
> - in
> -
> - let vmlinuzes =
> - match grub with
> - | `Grub1 ->
> - let paths =
> - let expr = sprintf "/files%s/title/kernel" grub_config in
> - let paths = g#aug_match expr in
> - let paths = Array.to_list paths in
> -
> - (* Remove duplicates. *)
> - let paths = remove_duplicates paths in
> -
> - (* Get the default kernel from grub if it's set. *)
> - let default =
> - let expr = sprintf "/files%s/default" grub_config in
> - try
> - let idx = g#aug_get expr in
> - let idx = int_of_string idx in
> - (* Grub indices are zero-based, augeas is 1-based. *)
> - let expr =
> - sprintf "/files%s/title[%d]/kernel" grub_config (idx+1) in
> - Some expr
> - with G.Error msg
> - when String.find msg "aug_get: no matching node" >= 0 ->
> - None in
> -
> - (* If a default kernel was set, put it at the beginning of the paths
> - * list. If not set, assume the first kernel always boots (?)
> - *)
> - match default with
> - | None -> paths
> - | Some p -> p :: List.filter ((<>) p) paths in
> -
> - (* Resolve the Augeas paths to kernel filenames. *)
> - let vmlinuzes = List.map g#aug_get paths in
> -
> - (* Make sure kernel does not begin with (hdX,X). *)
> - let vmlinuzes = List.map remove_hd_prefix vmlinuzes in
> -
> - (* Prepend grub filesystem. *)
> - List.map ((^) grub_prefix) vmlinuzes
> -
> - | `Grub2 ->
> - let get_default_image () =
> - let cmd =
> - if g#exists "/sbin/grubby" then
> - [| "grubby"; "--default-kernel" |]
> - else
> - [| "/usr/bin/perl"; "-MBootloader::Tools"; "-e"; "
> - InitLibrary();
> - my $default = Bootloader::Tools::GetDefaultSection();
> - print $default->{image};
> - " |] in
> - match g#command cmd with
> - | "" -> None
> - | k ->
> - let len = String.length k in
> - let k =
> - if len > 0 && k.[len-1] = '\n' then
> - String.sub k 0 (len-1)
> - else k in
> - Some (remove_hd_prefix k)
> - in
> -
> - let vmlinuzes =
> - (match get_default_image () with
> - | None -> []
> - | Some k -> [k]) @
> - (* This is how the grub2 config generator enumerates kernels. *)
> - Array.to_list (g#glob_expand "/boot/kernel-*") @
> - Array.to_list (g#glob_expand "/boot/vmlinuz-*") @
> - Array.to_list (g#glob_expand "/vmlinuz-*") in
> - let rex = Str.regexp ".*\\.\\(dpkg-.*|rpmsave|rpmnew\\)$" in
> - let vmlinuzes = List.filter (
> - fun file -> not (Str.string_match rex file 0)
> - ) vmlinuzes in
> - vmlinuzes in
> + let vmlinuzes = bootloader#list_kernels () in
>
> (* Map these to installed kernels. *)
> filter_map (
> @@ -389,21 +280,8 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> (* Conversion step. *)
>
> let rec augeas_grub_configuration () =
> - match grub with
> - | `Grub1 ->
> - (* Ensure Augeas is reading the grub configuration file, and if not
> - * then add it.
> - *)
> - let incls = g#aug_match "/augeas/load/Grub/incl" in
> - let incls = Array.to_list incls in
> - let incls_contains_conf =
> - List.exists (fun incl -> g#aug_get incl = grub_config) incls in
> - if not incls_contains_conf then (
> - g#aug_set "/augeas/load/Grub/incl[last()+1]" grub_config;
> - Linux.augeas_reload g;
> - )
> -
> - | `Grub2 -> () (* Not necessary for grub2. *)
> + if bootloader#set_augeas_configuration () then
> + Linux.augeas_reload g
>
> and unconfigure_xen () =
> (* Remove kmod-xenpv-* (RHEL 3). *)
> @@ -733,7 +611,7 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> let kernels = List.rev kernels (* so best is first *) in
> List.hd kernels in
> if best_kernel <> List.hd grub_kernels then
> - grub_set_bootable best_kernel;
> + bootloader#set_default_kernel best_kernel.ki_vmlinuz;
>
> (* Does the best/bootable kernel support virtio? *)
> let virtio = best_kernel.ki_supports_virtio in
> @@ -751,46 +629,6 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
>
> best_kernel, virtio
>
> - and grub_set_bootable kernel =
> - match grub with
> - | `Grub1 ->
> - if not (String.is_prefix kernel.ki_vmlinuz grub_prefix) then
> - error (f_"kernel %s is not under grub tree %s")
> - kernel.ki_vmlinuz grub_prefix;
> - let kernel_under_grub_prefix =
> - let prefix_len = String.length grub_prefix in
> - let kernel_len = String.length kernel.ki_vmlinuz in
> - String.sub kernel.ki_vmlinuz prefix_len (kernel_len - prefix_len) in
> -
> - (* Find the grub entry for the given kernel. *)
> - let paths = g#aug_match (sprintf "/files%s/title/kernel[. = '%s']"
> - grub_config kernel_under_grub_prefix) in
> - let paths = Array.to_list paths in
> - if paths = [] then
> - error (f_"didn't find grub entry for kernel %s") kernel.ki_vmlinuz;
> - let path = List.hd paths in
> - let rex = Str.regexp ".*/title\\[\\([1-9][0-9]*\\)\\]/kernel" in
> - if not (Str.string_match rex path 0) then
> - error (f_"internal error: regular expression did not match '%s'")
> - path;
> - let index = int_of_string (Str.matched_group 1 path) - 1 in
> - g#aug_set (sprintf "/files%s/default" grub_config) (string_of_int index);
> - g#aug_save ()
> -
> - | `Grub2 ->
> - let cmd =
> - if g#exists "/sbin/grubby" then
> - [| "grubby"; "--set-default"; kernel.ki_vmlinuz |]
> - else
> - [| "/usr/bin/perl"; "-MBootloader::Tools"; "-e"; sprintf "
> - InitLibrary();
> - my @sections = GetSectionList(type=>image, image=>\"%s\");
> - my $section = GetSection(@sections);
> - my $newdefault = $section->{name};
> - SetGlobals(default, \"$newdefault\");
> - " kernel.ki_vmlinuz |] in
> - ignore (g#command cmd)
> -
> (* Even though the kernel was already installed (this version of
> * virt-v2v does not install new kernels), it could have an
> * initrd that does not have support virtio. Therefore rebuild
> @@ -956,28 +794,6 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
>
> g#aug_save ()
>
> - and grub_configure_console () =
> - match grub with
> - | `Grub1 ->
> - let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
> - let expr = sprintf "/files%s/title/kernel/console" grub_config in
> -
> - let paths = g#aug_match expr in
> - let paths = Array.to_list paths in
> - List.iter (
> - fun path ->
> - let console = g#aug_get path in
> - if Str.string_match rex console 0 then (
> - let console = Str.global_replace rex "\\1ttyS0\\3" console in
> - g#aug_set path console
> - )
> - ) paths;
> -
> - g#aug_save ()
> -
> - | `Grub2 ->
> - grub2_update_console ~remove:false
> -
> (* If the target doesn't support a serial console, we want to remove
> * all references to it instead.
> *)
> @@ -1006,71 +822,6 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
>
> g#aug_save ()
>
> - and grub_remove_console () =
> - match grub with
> - | `Grub1 ->
> - let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
> - let expr = sprintf "/files%s/title/kernel/console" grub_config in
> -
> - let rec loop = function
> - | [] -> ()
> - | path :: paths ->
> - let console = g#aug_get path in
> - if Str.string_match rex console 0 then (
> - ignore (g#aug_rm path);
> - (* All the paths are invalid, restart the loop. *)
> - let paths = g#aug_match expr in
> - let paths = Array.to_list paths in
> - loop paths
> - )
> - else
> - loop paths
> - in
> - let paths = g#aug_match expr in
> - let paths = Array.to_list paths in
> - loop paths;
> -
> - g#aug_save ()
> -
> - | `Grub2 ->
> - grub2_update_console ~remove:true
> -
> - and grub2_update_console ~remove =
> - let rex = Str.regexp "\\(.*\\)\\bconsole=[xh]vc0\\b\\(.*\\)" in
> -
> - let paths = [
> - "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX";
> - "/files/etc/default/grub/GRUB_CMDLINE_LINUX";
> - "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT"
> - ] in
> - let paths = List.map g#aug_match paths in
> - let paths = List.map Array.to_list paths in
> - let paths = List.flatten paths in
> - match paths with
> - | [] ->
> - if not remove then
> - warning (f_"could not add grub2 serial console (ignored)")
> - else
> - warning (f_"could not remove grub2 serial console (ignored)")
> - | path :: _ ->
> - let grub_cmdline = g#aug_get path in
> - if Str.string_match rex grub_cmdline 0 then (
> - let new_grub_cmdline =
> - if not remove then
> - Str.global_replace rex "\\1console=ttyS0\\2" grub_cmdline
> - else
> - Str.global_replace rex "\\1\\2" grub_cmdline in
> - g#aug_set path new_grub_cmdline;
> - g#aug_save ();
> -
> - try
> - ignore (g#command [| "grub2-mkconfig"; "-o"; grub_config |])
> - with
> - G.Error msg ->
> - warning (f_"could not rebuild grub2 configuration file (%s). This may mean that grub output will not be sent to the serial port, but otherwise should be harmless. Original error message: %s")
> - grub_config msg
> - )
> -
> and supports_acpi () =
> (* ACPI known to cause RHEL 3 to fail. *)
> if family = `RHEL_family && inspect.i_major_version == 3 then
> @@ -1296,19 +1047,9 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> let paths = [
> (* /etc/fstab *)
> "/files/etc/fstab/*/spec";
> -
> - (* grub-legacy config *)
> - "/files" ^ grub_config ^ "/*/kernel/root";
> - "/files" ^ grub_config ^ "/*/kernel/resume";
> - "/files/boot/grub/device.map/*[label() != \"#comment\"]";
> - "/files/etc/sysconfig/grub/boot";
> -
> - (* grub2 config *)
> - "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX";
> - "/files/etc/default/grub/GRUB_CMDLINE_LINUX";
> - "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT";
> - "/files/boot/grub2/device.map/*[label() != \"#comment\"]";
> ] in
> + (* Bootloader config *)
> + let paths = paths @ bootloader#augeas_device_patterns in
>
> (* Which of these paths actually exist? *)
> let paths =
> @@ -1386,9 +1127,8 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
> if !changed then (
> g#aug_save ();
>
> - (* If it's grub2, we have to regenerate the config files. *)
> - if grub = `Grub2 then
> - ignore (g#command [| "grub2-mkconfig"; "-o"; grub_config |]);
> + (* Make sure the bootloader is up-to-date. *)
> + bootloader#update ();
>
> Linux.augeas_reload g
> );
> @@ -1418,10 +1158,10 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps =
>
> if keep_serial_console then (
> configure_console ();
> - grub_configure_console ();
> + bootloader#configure_console ();
> ) else (
> remove_console ();
> - grub_remove_console ();
> + bootloader#remove_console ();
> );
>
> let acpi = supports_acpi () in
> --
> 2.7.4
>
> _______________________________________________
> Libguestfs mailing list
> Libguestfs at redhat.com
> https://www.redhat.com/mailman/listinfo/libguestfs
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html
More information about the Libguestfs
mailing list