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 +++++++
v2v/convert_linux.ml | 284 ++-------------------------------------------
5 files changed, 376 insertions(+), 272 deletions(-)
create mode 100644 v2v/bootloaders.ml
create mode 100644 v2v/bootloaders.mli
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index b7b39fa..35325d9 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -105,6 +105,7 @@ sysprep/sysprep_operation_utmp.ml
sysprep/sysprep_operation_yum_uuid.ml
v2v/DOM.ml
v2v/OVF.ml
+v2v/bootloaders.ml
v2v/changeuid.ml
v2v/cmdline.ml
v2v/convert_linux.ml
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 008c5ba..9a997e9 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -27,6 +27,7 @@ EXTRA_DIST = \
CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-v2v
SOURCES_MLI = \
+ bootloaders.mli \
changeuid.mli \
cmdline.mli \
convert_linux.mli \
@@ -79,6 +80,7 @@ SOURCES_ML = \
input_libvirt_xen_ssh.ml \
input_libvirt.ml \
input_ova.ml \
+ bootloaders.ml \
convert_linux.ml \
convert_windows.ml \
output_null.ml \
diff --git a/v2v/bootloaders.ml b/v2v/bootloaders.ml
new file mode 100644
index 0000000..689d7b4
--- /dev/null
+++ b/v2v/bootloaders.ml
@@ -0,0 +1,317 @@
+(* 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.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+module G = Guestfs
+
+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
+
+(* 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