[Pkg-libvirt-commits] [libguestfs] 04/14: v2v: Modify conversion step to first do proper inspection and data gathering about the guest.
Hilko Bengen
bengen at moszumanska.debian.org
Sat Aug 30 08:29:05 UTC 2014
This is an automated email from the git hooks/post-receive script.
bengen pushed a commit to annotated tag upstream/1.27.20
in repository libguestfs.
commit 16e817456cf7e5162ba053c92f1a4df24a4160d5
Author: Richard W.M. Jones <rjones at redhat.com>
Date: Mon Jun 23 15:17:02 2014 +0100
v2v: Modify conversion step to first do proper inspection and data
gathering about the guest.
---
po/POTFILES-ml | 1 -
v2v/Makefile.am | 2 -
v2v/convert_linux.ml | 717 ++++++++++++++++++++++++++++++---------------
v2v/convert_linux_grub.ml | 331 ---------------------
v2v/convert_linux_grub.mli | 43 ---
v2v/lib_linux.ml | 100 +------
v2v/lib_linux.mli | 10 -
v2v/utils.ml | 9 +
v2v/virt-v2v.pod | 32 ++
9 files changed, 518 insertions(+), 727 deletions(-)
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index c46b187..4a6cd9c 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -83,7 +83,6 @@ sysprep/sysprep_operation_utmp.ml
sysprep/sysprep_operation_yum_uuid.ml
v2v/cmdline.ml
v2v/convert_linux.ml
-v2v/convert_linux_grub.ml
v2v/convert_windows.ml
v2v/lib_linux.ml
v2v/source_libvirt.ml
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 7735507..b353fb4 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -25,7 +25,6 @@ CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-v2v
SOURCES_MLI = \
convert_linux.mli \
- convert_linux_grub.mli \
convert_windows.mli \
lib_linux.mli \
source_libvirt.mli \
@@ -41,7 +40,6 @@ SOURCES_ML = \
lib_linux.ml \
cmdline.ml \
source_libvirt.ml \
- convert_linux_grub.ml \
convert_linux.ml \
convert_windows.ml \
target_local.ml \
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index 739179b..a869199 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -34,27 +34,330 @@ open Types
module G = Guestfs
+(* Kernel information. *)
+type kernel_info = {
+ ki_app : G.application2; (* The RPM package data. *)
+ ki_name : string; (* eg. "kernel-PAE" *)
+ ki_arch : string; (* Kernel architecture. *)
+ ki_vmlinuz : string; (* The path of the vmlinuz file. *)
+ ki_vmlinuz_stat : G.stat; (* stat(2) of vmlinuz *)
+ ki_modpath : string; (* The module path. *)
+ ki_modules : string list; (* The list of module names. *)
+ ki_supports_virtio : bool; (* Kernel has virtio drivers? *)
+ ki_is_xen_kernel : bool; (* Is a Xen paravirt kernel? *)
+}
+
+let string_of_kernel_info ki =
+ sprintf "(%s, %s, %s, virtio=%b, xen=%b)"
+ ki.ki_name ki.ki_arch ki.ki_vmlinuz
+ ki.ki_supports_virtio ki.ki_is_xen_kernel
+
+(* The conversion function. *)
let rec convert ?(keep_serial_console = true) verbose (g : G.guestfs)
({ i_root = root; i_apps = apps; i_apps_map = apps_map }
as inspect) source =
- let typ = g#inspect_get_type root
- and distro = g#inspect_get_distro root
- and arch = g#inspect_get_arch root
+ (*----------------------------------------------------------------------*)
+ (* Inspect the guest first. We already did some basic inspection in
+ * the common v2v.ml code, but that has to deal with generic guests
+ * (anything common to Linux and Windows). Here we do more detailed
+ * inspection which can make the assumption that we are dealing with
+ * an Enterprise Linux guest using RPM.
+ *)
+
+ (* We use Augeas for inspection and conversion, so initialize it early. *)
+ Lib_linux.augeas_init verbose g;
+
+ (* Basic inspection data available as local variables. *)
+ let typ = g#inspect_get_type root in
+ assert (typ = "linux");
+
+ let distro = g#inspect_get_distro root in
+ let family =
+ match distro with
+ | "rhel" | "centos" | "scientificlinux" | "redhat-based" -> `RHEL_family
+ | "sles" | "suse-based" | "opensuse" -> `SUSE_family
+ | _ -> assert false in
+
+(*
+ let arch = g#inspect_get_arch root
and major_version = g#inspect_get_major_version root
and minor_version = g#inspect_get_minor_version root
- and package_format = g#inspect_get_package_format root
+*)
+ let package_format = g#inspect_get_package_format root
and package_management = g#inspect_get_package_management root in
- assert (typ = "linux");
+ assert (package_format = "rpm");
+
+ (* What grub is installed? *)
+ let grub_config, grub =
+ try
+ List.find (
+ fun (grub_config, _) -> g#is_file ~followsymlinks:true grub_config
+ ) [
+ "/boot/grub2/grub.cfg", `Grub2;
+ "/boot/grub/menu.lst", `Grub1;
+ "/boot/grub/grub.conf", `Grub1;
+ ]
+ 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 root in
+ try
+ List.find (
+ fun path -> List.mem_assoc path mounts
+ ) [ "/boot/grub"; "/boot" ]
+ with Not_found -> "" in
+
+ (* EFI? *)
+ let efi =
+ if Array.length (g#glob_expand "/boot/efi/EFI/*/grub.cfg") < 1 then
+ None
+ else (
+ (* Check the first partition of each device looking for an EFI
+ * boot partition. We can't be sure which device is the boot
+ * device, so we just check them all.
+ *)
+ let devs = g#list_devices () in
+ let devs = Array.to_list devs in
+ try
+ Some (
+ List.find (
+ fun dev ->
+ try
+ g#part_get_gpt_type dev 1
+ = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+ with G.Error _ -> false
+ ) devs
+ )
+ with Not_found -> None
+ ) in
+
+ (* What kernel/kernel-like packages are installed on the current guest? *)
+ let installed_kernels : kernel_info list =
+ let rex = Str.regexp ".*\\.k?o\\(\\.xz\\)?$" in
+ let rex2 = Str.regexp ".*/\\([^/]+\\)\\.k?o\\(\\.xz\\)?$" in
+ filter_map (
+ function
+ | { G.app2_name = name } as app
+ when name = "kernel" || string_prefix name "kernel-" ->
+ (try
+ (* For each kernel, list the files directly owned by the kernel. *)
+ let files = Lib_linux.file_list_of_package verbose g inspect name in
+
+ (* Which of these is the kernel itself? *)
+ let vmlinuz = List.find (
+ fun filename -> string_prefix filename "/boot/vmlinuz-"
+ ) files in
+ (* Which of these is the modpath? *)
+ let modpath = List.find (
+ fun filename ->
+ String.length filename >= 14 &&
+ string_prefix filename "/lib/modules/"
+ ) files in
+
+ (* Check vmlinuz & modpath exist. *)
+ if not (g#is_dir ~followsymlinks:true modpath) then
+ raise Not_found;
+ let vmlinuz_stat =
+ try g#stat vmlinuz with G.Error _ -> raise Not_found in
+
+ (* Get all modules, which might include custom-installed
+ * modules that don't appear in 'files' list above.
+ *)
+ let modules = g#find modpath in
+ let modules = Array.to_list modules in
+ let modules =
+ List.filter (fun m -> Str.string_match rex m 0) modules in
+ assert (List.length modules > 0);
+
+ (* Determine the kernel architecture by looking at the
+ * architecture of an arbitrary kernel module.
+ *)
+ let arch =
+ let any_module = modpath ^ List.hd modules in
+ g#file_architecture any_module in
+
+ (* Just return the module names, without path or extension. *)
+ let modules = filter_map (
+ fun m ->
+ if Str.string_match rex2 m 0 then
+ Some (Str.matched_group 1 m)
+ else
+ None
+ ) modules in
+ assert (List.length modules > 0);
+
+ let supports_virtio = List.mem "virtio_net" modules in
+ let is_xen_kernel = List.mem "xennet" modules in
+
+ Some {
+ ki_app = app;
+ ki_name = name;
+ ki_arch = arch;
+ ki_vmlinuz = vmlinuz;
+ ki_vmlinuz_stat = vmlinuz_stat;
+ ki_modpath = modpath;
+ ki_modules = modules;
+ ki_supports_virtio = supports_virtio;
+ ki_is_xen_kernel = is_xen_kernel;
+ }
+
+ with Not_found -> None
+ )
+
+ | _ -> None
+ ) apps in
+
+ if verbose then (
+ printf "installed kernel packages in this guest:\n";
+ List.iter (
+ fun kernel -> printf "\t%s\n" (string_of_kernel_info kernel)
+ ) installed_kernels;
+ flush stdout
+ );
+
+ if installed_kernels = [] then
+ error (f_"no installed kernel packages were found.\n\nThis probably indicates that %s was unable to inspect this guest properly.")
+ prog;
+
+ (* Now the difficult bit. Get the grub kernels. The first in this
+ * 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 Not_found -> 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
+
+ (* Map these to installed kernels. *)
+ filter_map (
+ fun vmlinuz ->
+ try
+ let statbuf = g#stat vmlinuz in
+ let kernel =
+ List.find (
+ fun { ki_vmlinuz_stat = s } ->
+ statbuf.G.dev = s.G.dev && statbuf.G.ino = s.G.ino
+ ) installed_kernels in
+ Some kernel
+ with Not_found -> None
+ ) vmlinuzes in
+
+ if verbose then (
+ printf "grub kernels in this guest (first in list is default):\n";
+ List.iter (
+ fun kernel -> printf "\t%s\n" (string_of_kernel_info kernel)
+ ) grub_kernels;
+ flush stdout
+ );
+
+ if grub_kernels = [] then
+ error (f_"no kernels were found in the grub configuration.\n\nThis probably indicates that %s was unable to parse the grub configuration of this guest.")
+ prog;
- let is_rhel_family =
- (distro = "rhel" || distro = "centos"
- || distro = "scientificlinux" || distro = "redhat-based")
+ (*----------------------------------------------------------------------*)
+ (* Conversion step. *)
- and is_suse_family =
- (distro = "sles" || distro = "suse-based" || distro = "opensuse") in
+ 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;
+ Lib_linux.augeas_reload verbose g;
+ )
+
+ | `Grub2 -> () (* Not necessary for grub2. *)
- let rec clean_rpmdb () =
+ and clean_rpmdb () =
(* Clean RPM database. *)
assert (package_format = "rpm");
let dbfiles = g#glob_expand "/var/lib/rpm/__db.00?" in
@@ -68,19 +371,6 @@ let rec convert ?(keep_serial_console = true) verbose (g : G.guestfs)
if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" then
g#touch "/.autorelabel";
- and get_grub () =
- (* Detect if grub2 or grub1 is installed by trying to create
- * an object of each sort.
- *)
- try Convert_linux_grub.grub2 verbose g inspect
- with Failure grub2_error ->
- try Convert_linux_grub.grub1 verbose g inspect
- with Failure grub1_error ->
- error (f_"no grub configuration found in this guest.
-Grub2 error was: %s
-Grub1/grub-legacy error was: %s")
- grub2_error grub1_error
-
and unconfigure_xen () =
(* Remove kmod-xenpv-* (RHEL 3). *)
let xenmods =
@@ -133,7 +423,7 @@ Grub1/grub-legacy error was: %s")
);
);
- if is_suse_family then (
+ if family = `SUSE_family then (
(* Remove xen modules from INITRD_MODULES and DOMU_INITRD_MODULES. *)
let variables = ["INITRD_MODULES"; "DOMU_INITRD_MODULES"] in
let xen_modules = ["xennet"; "xen-vnif"; "xenblk"; "xen-vbd"] in
@@ -339,226 +629,88 @@ Grub1/grub-legacy error was: %s")
if !updated then g#aug_save ();
)
- and can_do_virtio () =
- (* In the previous virt-v2v, this was a function that installed
- * virtio, eg. by updating the kernel. However that function
- * (which only applied to RHEL <= 5) was very difficult to write
- * and maintain. Instead what we do here is to check if the kernel
- * supports virtio, warn if it doesn't (and give some hint about
- * what to do) and return false. Note that all recent Linux comes
- * with virtio drivers.
- *)
- match distro, major_version, minor_version with
- (* RHEL 6+ has always supported virtio. *)
- | ("rhel"|"centos"|"scientificlinux"|"redhat-based"), v, _ when v >= 6 ->
- true
- | ("rhel"|"centos"|"scientificlinux"|"redhat-based"), 5, _ ->
- let kernel = check_kernel_package (0_l, "2.6.18", "128.el5") in
- let lvm2 = check_package "lvm2" (0_l, "2.02.40", "6.el5") in
- let selinux =
- check_package ~ifinstalled:true
- "selinux-policy-targeted" (0_l, "2.4.6", "203.el5") in
- kernel && lvm2 && selinux
- | ("rhel"|"centos"|"scientificlinux"|"redhat-based"), 4, _ ->
- check_kernel_package (0_l, "2.6.9", "89.EL")
-
- (* All supported Fedora versions support virtio. *)
- | "fedora", _, _ -> true
-
- (* SLES 11 supports virtio in the kernel. *)
- | ("sles"|"suse-based"), v, _ when v >= 11 -> true
- | ("sles"|"suse-based"), 10, _ ->
- check_kernel_package (0_l, "2.6.16.60", "0.85.1")
-
- (* OpenSUSE. *)
- | "opensuse", v, _ when v >= 11 -> true
- | "opensuse", 10, _ ->
- check_kernel_package (0_l, "2.6.25.5", "1.1")
-
- | _ ->
- warning ~prog (f_"don't know how to install virtio drivers for %s %d\n%!")
- distro major_version;
- false
-
- and check_kernel_package minversion =
- let names = ["kernel"; "kernel-PAE"; "kernel-hugemem"; "kernel-smp";
- "kernel-largesmp"; "kernel-pae"; "kernel-default"] in
- let found = List.exists (
- fun name -> check_package ~warn:false name minversion
- ) names in
- if not found then (
- let _, minversion, minrelease = minversion in
- warning ~prog (f_"cannot enable virtio in this guest.\nTo enable virtio you need to install a kernel >= %s-%s and run %s again.")
- minversion minrelease prog
- );
- found
-
- and check_package ?(ifinstalled = false) ?(warn = true) name minversion =
- let installed =
- let apps = try StringMap.find name apps_map with Not_found -> [] in
- List.rev (List.sort compare_app2_versions apps) in
-
- match ifinstalled, installed with
- (* If the package is not installed, ignore the request. *)
- | true, [] -> true
- (* Is the package already installed at the minimum version? *)
- | _, (installed::_)
- when compare_app2_version_min installed minversion >= 0 -> true
- (* User will need to install the package to get virtio. *)
- | _ ->
- if warn then (
- let _, minversion, minrelease = minversion in
- warning ~prog (f_"cannot enable virtio in this guest.\nTo enable virtio you need to upgrade %s >= %s-%s and run %s again.")
- name minversion minrelease prog
- );
- false
+ and unconfigure_efi () =
+ match efi with
+ | None -> ()
+ | Some dev ->
+ match grub with
+ | `Grub1 ->
+ g#cp "/etc/grub.conf" "/boot/grub/grub.conf";
+ g#ln_sf "/boot/grub/grub.conf" "/etc/grub.conf";
- and configure_kernel virtio grub =
- let kernels = grub#list_kernels () in
+ (* Reload Augeas to pick up new location of grub.conf. *)
+ Lib_linux.augeas_reload verbose g;
- let bootable_kernel =
- let rec loop =
- function
- | [] -> None
- | path :: paths ->
- let kernel =
- Lib_linux.inspect_linux_kernel verbose g inspect path in
- match kernel with
- | None -> loop paths
- | Some kernel when is_hv_kernel kernel -> loop paths
- | Some kernel when virtio && not (supports_virtio kernel) ->
- loop paths
- | Some kernel -> Some kernel
- in
- loop kernels in
+ ignore (g#command [| "grub-install"; dev |])
- (* If virtio == true, then a virtio kernel should have been
- * installed. If we didn't find one, it indicates a bug in
- * virt-v2v.
- *)
- if virtio && bootable_kernel = None then
- error (f_"virtio configured, but no virtio kernel found");
-
- (* No bootable kernel was found. Install one. *)
- let bootable_kernel =
- match bootable_kernel with
- | Some k -> k
- | None ->
- (* Find which kernel is currently used by the guest. *)
- let current_kernel =
- let rec loop = function
- | [] -> "kernel"
- | path :: paths ->
- let kernel =
- Lib_linux.inspect_linux_kernel verbose g inspect
- path in
- match kernel with
- | None -> loop paths
- | Some kernel -> kernel.Lib_linux.base_package
- in
- loop kernels in
-
- (* Replace kernel-xen with a suitable kernel. *)
- let current_kernel =
- if string_find current_kernel "kernel-xen" >= 0 then
- xen_replacement_kernel ()
- else
- current_kernel in
+ | `Grub2 ->
+ (* EFI systems boot using grub2-efi, and probably don't have the
+ * base grub2 package installed.
+ *)
+ Lib_linux.install verbose g inspect ["grub2"];
+
+ (* Relabel the EFI boot partition as a BIOS boot partition. *)
+ g#part_set_gpt_type dev 1 "21686148-6449-6E6F-744E-656564454649";
+
+ (* Delete the fstab entry for the EFI boot partition. *)
+ let nodes = g#aug_match "/files/etc/fstab/*[file = '/boot/efi']" in
+ let nodes = Array.to_list nodes in
+ List.iter (fun node -> ignore (g#aug_rm node)) nodes;
+ g#aug_save ();
- (* Install the kernel. However we need a way to detect the
- * version of the kernel that has just been installed. A quick
- * way is to compare /lib/modules before and after.
+ (* Install grub2 in the BIOS boot partition. This overwrites the
+ * previous contents of the EFI boot partition.
*)
- let files1 = g#ls "/lib/modules" in
- let files1 = Array.to_list files1 in
- Lib_linux.install verbose g inspect [current_kernel];
- let files2 = g#ls "/lib/modules" in
- let files2 = Array.to_list files2 in
-
- (* Note that g#ls is guaranteed to return the strings in order. *)
- let rec loop files1 files2 =
- match files1, files2 with
- | [], [] ->
- error (f_"tried to install '%s', but no kernel package was installed") current_kernel
- | (v1 :: _), [] ->
- error (f_"tried to install '%s', but there are now fewer directories under /lib/modules!") current_kernel
- | [], (v2 :: _) -> v2
- | (v1 :: _), (v2 :: _) when v1 <> v2 -> v2
- | (_ :: v1s), (_ :: v2s) -> loop v1s v2s
- in
- let version = loop files1 files2 in
+ ignore (g#command [| "grub2-install"; dev |]);
- { Lib_linux.base_package = current_kernel;
- version = version; modules = []; arch = "" } in
+ (* Re-generate the grub2 config, and put it in the correct place *)
+ ignore (g#command [| "grub2-mkconfig"; "-o"; "/boot/grub2/grub.cfg" |])
- (* Set /etc/sysconfig/kernel DEFAULTKERNEL to point to the new
- * kernel package name.
+ and configure_kernel () =
+ (* Previously this function would try to install kernels, but we
+ * don't do that any longer.
*)
- if g#is_file ~followsymlinks:true "/etc/sysconfig/kernel" then (
- let base_package = bootable_kernel.Lib_linux.base_package in
- let paths =
- g#aug_match "/files/etc/sysconfig/kernel/DEFAULTKERNEL/value" in
- let paths = Array.to_list paths in
- List.iter (fun path -> g#aug_set path base_package) paths;
- g#aug_save ()
- );
- (* Return the installed kernel version. *)
- bootable_kernel.Lib_linux.version
-
- and supports_virtio { Lib_linux.modules = modules } =
- List.mem "virtio_blk" modules && List.mem "virtio_net" modules
-
- (* Is it a hypervisor-specific kernel? *)
- and is_hv_kernel { Lib_linux.modules = modules } =
- List.mem "xennet" modules (* Xen PV kernel. *)
-
- (* Find a suitable replacement for kernel-xen. *)
- and xen_replacement_kernel () =
- if is_rhel_family then (
- match major_version, arch with
- | 5, ("i386"|"i486"|"i586"|"i686") -> "kernel-PAE"
- | 5, _ -> "kernel"
- | 4, ("i386"|"i486"|"i586"|"i686") ->
- (* If guest has >= 10GB of RAM, give it a hugemem kernel. *)
- if source.s_memory >= 10L *^ 1024L *^ 1024L *^ 1024L then
- "kernel-hugemem"
- (* SMP kernel for guests with > 1 vCPU. *)
- else if source.s_vcpu > 1 then
- "kernel-smp"
- else
- "kernel"
- | 4, _ ->
- if source.s_vcpu > 8 then "kernel-largesmp"
- else if source.s_vcpu > 1 then "kernel-smp"
- else "kernel"
- | _, _ -> "kernel"
- )
- else if is_suse_family then (
- match distro, major_version, arch with
- | "opensuse", _, _ -> "kernel-default"
- | _, v, ("i386"|"i486"|"i586"|"i686") when v >= 11 ->
- if source.s_memory >= 10L *^ 1024L *^ 1024L *^ 1024L then
- "kernel-pae"
- else
- "kernel"
- | _, v, _ when v >= 11 -> "kernel-default"
- | _, 10, ("i386"|"i486"|"i586"|"i686") ->
- if source.s_memory >= 10L *^ 1024L *^ 1024L *^ 1024L then
- "kernel-bigsmp"
- else if source.s_vcpu > 1 then
- "kernel-smp"
- else
- "kernel-default"
- | _, 10, _ ->
- if source.s_vcpu > 1 then
- "kernel-smp"
- else
- "kernel-default"
- | _ -> "kernel-default"
- )
- else
- "kernel" (* conservative default *)
+ (* Check a non-Xen kernel exists. *)
+ let only_xen_kernels = List.for_all (
+ fun { ki_is_xen_kernel = is_xen_kernel } -> is_xen_kernel
+ ) grub_kernels in
+ if only_xen_kernels then
+ error (f_"only Xen kernels are installed in this guest.\n\nRead the %s(1) manual, section \"XEN PARAVIRTUALIZED GUESTS\", to see what to do.") prog;
+
+ (* Enable the best non-Xen kernel, where "best" means the one with
+ * the highest version which supports virtio.
+ *)
+ let best_kernel =
+ let compare_best_kernels k1 k2 =
+ let i = compare k1.ki_supports_virtio k2.ki_supports_virtio in
+ if i <> 0 then i
+ else compare_app2_versions k1.ki_app k2.ki_app
+ in
+ let kernels = grub_kernels in
+ let kernels = List.filter (fun { ki_is_xen_kernel = is_xen_kernel } -> not is_xen_kernel) kernels in
+ let kernels = List.sort compare_best_kernels kernels in
+ 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;
+
+ (* Does the best/bootable kernel support virtio? *)
+ best_kernel.ki_supports_virtio
+
+ and grub_set_bootable kernel =
+ let cmd =
+ if g#exists "/sbin/grubby" then
+ [| "grubby"; "--set-kernel"; 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)
(* We configure a console on ttyS0. Make sure existing console
* references use it. N.B. Note that the RHEL 6 xen guest kernel
@@ -596,6 +748,28 @@ Grub1/grub-legacy error was: %s")
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.
*)
@@ -624,26 +798,84 @@ Grub1/grub-legacy error was: %s")
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 grub_cmdline_expr =
+ if g#exists "/etc/sysconfig/grub" then
+ "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX"
+ else
+ "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT" in
+
+ (try
+ let grub_cmdline = g#aug_get grub_cmdline_expr in
+ let grub_cmdline =
+ if Str.string_match rex grub_cmdline 0 then (
+ if remove then
+ Str.global_replace rex "\\1\\3" grub_cmdline
+ else
+ Str.global_replace rex "\\1console=ttyS0\\3" grub_cmdline
+ )
+ else grub_cmdline in
+ g#aug_set grub_cmdline_expr grub_cmdline;
+ g#aug_save ();
+
+ ignore (g#command [| "grub2-mkconfig"; "-o"; grub_config |])
+ with
+ G.Error msg ->
+ warning ~prog (f_"could not update grub2 console: %s (ignored)")
+ msg
+ )
+
in
+ augeas_grub_configuration ();
clean_rpmdb ();
autorelabel ();
- Lib_linux.augeas_init verbose g;
- let grub = get_grub () in
unconfigure_xen ();
unconfigure_vbox ();
unconfigure_vmware ();
unconfigure_citrix ();
+ unconfigure_efi ();
+
+ let virtio = configure_kernel () in
- let virtio = can_do_virtio () in
- let kernel_version = configure_kernel virtio grub in (*XXX*) ignore kernel_version;
if keep_serial_console then (
configure_console ();
- grub#configure_console ()
+ grub_configure_console ();
) else (
remove_console ();
- grub#remove_console ()
+ grub_remove_console ();
);
@@ -653,7 +885,6 @@ Grub1/grub-legacy error was: %s")
-
let guestcaps = {
gcaps_block_bus = if virtio then "virtio" else "ide";
gcaps_net_bus = if virtio then "virtio" else "e1000";
diff --git a/v2v/convert_linux_grub.ml b/v2v/convert_linux_grub.ml
deleted file mode 100644
index cb8c5c8..0000000
--- a/v2v/convert_linux_grub.ml
+++ /dev/null
@@ -1,331 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-2014 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.
- *)
-
-module G = Guestfs
-
-open Printf
-
-open Common_gettext.Gettext
-open Common_utils
-
-open Utils
-open Types
-
-(* 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"
-
-(* Helper function to check if guest is EFI. *)
-let check_efi g =
- if Array.length (g#glob_expand "/boot/efi/EFI/*/grub.cfg") < 1 then
- raise Not_found;
-
- (* Check the first partition of each device looking for an EFI
- * boot partition. We can't be sure which device is the boot
- * device, so we just check them all.
- *)
- let devs = g#list_devices () in
- let devs = Array.to_list devs in
- List.find (
- fun dev ->
- try g#part_get_gpt_type dev 1 = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
- with G.Error _ -> false
- ) devs
-
-(* Virtual grub superclass. *)
-class virtual grub verbose (g : Guestfs.guestfs) inspect config_file =
-object
- method virtual list_kernels : unit -> string list
-
- method virtual configure_console : unit -> unit
- method virtual remove_console : unit -> unit
-
- method private 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)
-end
-
-(* Concrete implementation for grub1. *)
-class grub1 verbose g inspect config_file grub_fs =
-object (self)
- inherit grub verbose g inspect config_file
-
- method private grub_fs = grub_fs (* grub filesystem prefix *)
-
- method list_kernels () =
- let paths =
- let expr = sprintf "/files%s/title/kernel" config_file in
- let paths = g#aug_match expr in
- let paths = Array.to_list paths in
-
- (* Get the default kernel from grub if it's set. *)
- let default =
- let expr = sprintf "/files%s/default" config_file 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" config_file (idx+1) in
- Some expr
- with Not_found -> None in
-
- (* If a default kernel was set, put it at the beginning of the paths
- * list.
- *)
- match default with
- | None -> paths
- | Some p -> p :: List.filter ((<>) p) paths in
-
- (* Remove duplicates. *)
- let paths =
- let checked = Hashtbl.create 13 in
- let rec loop = function
- | [] -> []
- | p :: ps when Hashtbl.mem checked p -> ps
- | p :: ps -> Hashtbl.add checked p true; p :: loop ps
- in
- loop paths in
-
- (* Resolve the Augeas paths to kernel filenames. *)
- let kernels = List.map g#aug_get paths in
-
- (* Make sure kernel does not begin with (hdX,X). *)
- let kernels = List.map remove_hd_prefix kernels in
-
- (* Prepend grub filesystem. *)
- let kernels = List.map ((^) grub_fs) kernels in
-
- (* Check the actual file exists. *)
- let kernels = List.filter (g#is_file ~followsymlinks:true) kernels in
-
- kernels
-
- method configure_console () =
- let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
- let expr = sprintf "/files%s/title/kernel/console" config_file 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" config_file 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
-
-(* Create a grub1 object. *)
-let rec grub1 verbose (g : Guestfs.guestfs) inspect =
- let root = inspect.i_root in
-
- (* Look for a grub configuration file. *)
- let config_file =
- try
- List.find (
- fun file -> g#is_file ~followsymlinks:true file
- ) ["/boot/grub/menu.lst"; "/boot/grub/grub.conf"]
- with
- Not_found ->
- failwith (s_"no grub/grub1/grub-legacy configuration file was found") in
-
- (* Check for EFI and convert if found. *)
- (try let dev = check_efi g in grub1_convert_from_efi verbose g dev
- with Not_found -> ()
- );
-
- (* Find the path that has to be prepended to filenames in grub.conf
- * in order to make them absolute.
- *)
- let grub_fs =
- let mounts = g#inspect_get_mountpoints root in
- try
- List.find (
- fun path -> List.mem_assoc path mounts
- ) [ "/boot/grub"; "/boot" ]
- with Not_found -> "" in
-
- (* Ensure Augeas is reading the grub configuration file, and if not
- * then add it.
- *)
- let () =
- 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 = config_file) incls in
- if not incls_contains_conf then (
- g#aug_set "/augeas/load/Grub/incl[last()+1]" config_file;
- Lib_linux.augeas_reload verbose g;
- ) in
-
- new grub1 verbose g inspect config_file grub_fs
-
-(* Reinstall grub. *)
-and grub1_convert_from_efi verbose g dev =
- g#cp "/etc/grub.conf" "/boot/grub/grub.conf";
- g#ln_sf "/boot/grub/grub.conf" "/etc/grub.conf";
-
- (* Reload Augeas to pick up new location of grub.conf. *)
- Lib_linux.augeas_reload verbose g;
-
- ignore (g#command [| "grub-install"; dev |])
-
-(* Concrete implementation for grub2. *)
-class grub2 verbose g inspect config_file =
-object (self)
- inherit grub verbose g inspect config_file
-
- method list_kernels () =
- let files =
- (match self#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 files = List.filter (
- fun file -> not (Str.string_match rex file 0)
- ) files in
- files
-
- method private update_console ~remove =
- let rex = Str.regexp "\\(.*\\)\\bconsole=[xh]vc0\\b\\(.*\\)" in
-
- let grub_cmdline_expr =
- if g#exists "/etc/sysconfig/grub" then
- "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX"
- else
- "/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT" in
-
- (try
- let grub_cmdline = g#aug_get grub_cmdline_expr in
- let grub_cmdline =
- if Str.string_match rex grub_cmdline 0 then (
- if remove then
- Str.global_replace rex "\\1\\3" grub_cmdline
- else
- Str.global_replace rex "\\1console=ttyS0\\3" grub_cmdline
- )
- else grub_cmdline in
- g#aug_set grub_cmdline_expr grub_cmdline;
- g#aug_save ();
-
- ignore (g#command [| "grub2-mkconfig"; "-o"; config_file |])
- with
- G.Error msg ->
- warning ~prog (f_"could not update grub2 console: %s (ignored)")
- msg
- )
-
- method configure_console () = self#update_console ~remove:false
- method remove_console () = self#update_console ~remove:true
-end
-
-let rec grub2 verbose (g : Guestfs.guestfs) inspect =
- (* Look for a grub2 configuration file. *)
- let config_file = "/boot/grub2/grub.cfg" in
- if not (g#is_file ~followsymlinks:true config_file) then (
- let msg =
- sprintf (f_"no grub2 configuration file was found (expecting %s)")
- config_file in
- failwith msg
- );
-
- (* Check for EFI and convert if found. *)
- (try
- let dev = check_efi g in
- grub2_convert_from_efi verbose g inspect dev
- with Not_found -> ()
- );
-
- new grub2 verbose g inspect config_file
-
-(* For grub2:
- * - Turn the EFI partition into a BIOS Boot Partition
- * - Remove the former EFI partition from fstab
- * - Install the non-EFI version of grub
- * - Install grub2 in the BIOS Boot Partition
- * - Regenerate grub.cfg
- *)
-and grub2_convert_from_efi verbose g inspect dev =
- (* EFI systems boot using grub2-efi, and probably don't have the
- * base grub2 package installed.
- *)
- Lib_linux.install verbose g inspect ["grub2"];
-
- (* Relabel the EFI boot partition as a BIOS boot partition. *)
- g#part_set_gpt_type dev 1 "21686148-6449-6E6F-744E-656564454649";
-
- (* Delete the fstab entry for the EFI boot partition. *)
- let nodes = g#aug_match "/files/etc/fstab/*[file = '/boot/efi']" in
- let nodes = Array.to_list nodes in
- List.iter (fun node -> ignore (g#aug_rm node)) nodes;
- g#aug_save ();
-
- (* Install grub2 in the BIOS boot partition. This overwrites the
- * previous contents of the EFI boot partition.
- *)
- ignore (g#command [| "grub2-install"; dev |]);
-
- (* Re-generate the grub2 config, and put it in the correct place *)
- ignore (g#command [| "grub2-mkconfig"; "-o"; "/boot/grub2/grub.cfg" |])
diff --git a/v2v/convert_linux_grub.mli b/v2v/convert_linux_grub.mli
deleted file mode 100644
index 324a333..0000000
--- a/v2v/convert_linux_grub.mli
+++ /dev/null
@@ -1,43 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-2014 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.
- *)
-
-(** Common code handling grub1 (grub-legacy) and grub2 operations. *)
-
-class type virtual grub = object
- method virtual list_kernels : unit -> string list
- (** Return a list of kernels from the grub configuration. The
- returned list is a list of filenames. *)
- method virtual configure_console : unit -> unit
- (** Reconfigure the grub console. *)
- method virtual remove_console : unit -> unit
- (** Remove the grub console configuration. *)
-end
-
-val grub1 : bool -> Guestfs.guestfs -> Types.inspect -> grub
-(** Detect if grub1/grub-legacy is used by this guest and return a
- grub object if so.
-
- This raises [Failure] if grub1 is not used by this guest or some
- other problem happens. *)
-
-val grub2 : bool -> Guestfs.guestfs -> Types.inspect -> grub
-(** Detect if grub2 is used by this guest and return a grub object
- if so.
-
- This raises [Failure] if grub2 is not used by this guest or some
- other problem happens. *)
diff --git a/v2v/lib_linux.ml b/v2v/lib_linux.ml
index 580c5ec..8362d2a 100644
--- a/v2v/lib_linux.ml
+++ b/v2v/lib_linux.ml
@@ -123,7 +123,9 @@ let file_list_of_package verbose (g : Guestfs.guestfs) inspect name =
| "rpm" ->
let cmd = [| "rpm"; "-ql"; name |] in
if verbose then eprintf "%s\n%!" (String.concat " " (Array.to_list cmd));
- Array.to_list (g#command_lines cmd)
+ let files = g#command_lines cmd in
+ let files = Array.to_list files in
+ List.sort compare files
| format ->
error (f_"don't know how to get list of files from package using %s")
format
@@ -151,99 +153,3 @@ let rec file_owner verbose g inspect path =
and is_file_owned verbose g inspect path =
try file_owner verbose g inspect path; true
with Not_found -> false
-
-type kernel_info = {
- base_package : string; (* base package, eg. "kernel-PAE" *)
- version : string; (* kernel version *)
- modules : string list; (* list of kernel modules *)
- arch : string; (* kernel arch *)
-}
-
-(* There was some crazy SUSE stuff going on in the Perl version
- * of virt-v2v, which I have dropped from this as I couldn't
- * understand what on earth it was doing. - RWMJ
- *)
-let inspect_linux_kernel verbose (g : Guestfs.guestfs) inspect path =
- let base_package = file_owner verbose g inspect path in
-
- (* Try to get kernel version by examination of the binary.
- * See supermin.git/src/kernel.ml
- *)
- let version =
- try
- let hdrS = g#pread path 4 514L in
- if hdrS <> "HdrS" then raise Not_found;
- let s = g#pread path 2 518L in
- let s = (Char.code s.[1] lsl 8) lor Char.code s.[0] in
- if s < 0x1ff then raise Not_found;
- let offset = g#pread path 2 526L in
- let offset = (Char.code offset.[1] lsl 8) lor Char.code offset.[0] in
- if offset < 0 then raise Not_found;
- let buf = g#pread path (offset + 0x200) 132L in
- let rec loop i =
- if i < 132 then (
- if buf.[i] = '\000' || buf.[i] = ' ' ||
- buf.[i] = '\t' || buf.[i] = '\n' then
- String.sub buf 0 i
- else
- loop (i+1)
- )
- else raise Not_found
- in
- let v = loop 0 in
- (* There must be a corresponding modules directory. *)
- let modpath = sprintf "/lib/modules/%s" v in
- if not (g#is_dir modpath) then
- raise Not_found;
- Some (v, modpath)
- with Not_found -> None in
-
- (* Apparently Xen PV kernels don't contain a version number,
- * so try to guess the version from the filename.
- *)
- let version =
- match version with
- | Some v -> Some v
- | None ->
- let rex = Str.regexp "^/boot/vmlinuz-\\(.*\\)" in
- if Str.string_match rex path 0 then (
- let v = Str.matched_group 1 path in
- let modpath = sprintf "/lib/modules/%s" v in
- if g#is_dir modpath then Some (v, modpath) else None
- )
- else None in
-
- (* If we sill didn't find a version, give up here. *)
- match version with
- | None -> None
- | Some (version, modpath) ->
-
- (* List modules. *)
- let modules = g#find modpath in
- let modules = Array.to_list modules in
- let rex = Str.regexp ".*\\.k?o$" in
- let modules = List.filter (fun m -> Str.string_match rex m 0) modules in
-
- assert (List.length modules > 0);
-
- (* Determine the kernel architecture by looking at the architecture
- * of an arbitrary kernel module.
- *)
- let arch =
- let any_module = modpath ^ List.hd modules in
- g#file_architecture any_module in
-
- (* Just return the module names, without path or extension. *)
- let rex = Str.regexp ".*/\\([^/]+\\)\\.k?o$/" in
- let modules = filter_map (
- fun m ->
- if Str.string_match rex m 0 then
- Some (Str.matched_group 1 m)
- else
- None
- ) modules in
-
- Some { base_package = base_package;
- version = version;
- modules = modules;
- arch = arch }
diff --git a/v2v/lib_linux.mli b/v2v/lib_linux.mli
index 94983c6..e5a3025 100644
--- a/v2v/lib_linux.mli
+++ b/v2v/lib_linux.mli
@@ -39,13 +39,3 @@ val file_owner : bool -> Guestfs.guestfs -> Types.inspect -> string -> string
val is_file_owned : bool -> Guestfs.guestfs -> Types.inspect -> string -> bool
(** Returns true if the file is owned by an installed package. *)
-
-type kernel_info = {
- base_package : string; (* base package, eg. "kernel-PAE" *)
- version : string; (* kernel version *)
- modules : string list; (* list of kernel modules *)
- arch : string; (* kernel arch *)
-}
-
-val inspect_linux_kernel : bool -> Guestfs.guestfs -> Types.inspect -> string -> kernel_info option
-(** Inspect a Linux kernel (by path) and return various information. *)
diff --git a/v2v/utils.ml b/v2v/utils.ml
index 9870f1b..b58c18d 100644
--- a/v2v/utils.ml
+++ b/v2v/utils.ml
@@ -62,3 +62,12 @@ and compare_app2_version_min app1 (min_epoch, min_version, min_release) =
else
compare_version app1.Guestfs.app2_release min_release
)
+
+let remove_duplicates xs =
+ let h = Hashtbl.create (List.length xs) in
+ let rec loop = function
+ | [] -> []
+ | x :: xs when Hashtbl.mem h x -> xs
+ | x :: xs -> Hashtbl.add h x true; x :: loop xs
+ in
+ loop xs
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index b7f4726..c88df5d 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -208,6 +208,38 @@ Enable tracing of libguestfs API calls.
=back
+=head1 XEN PARAVIRTUALIZED GUESTS
+
+Older versions of virt-v2v could turn a Xen paravirtualized (PV) guest
+into a KVM guest by installing a new kernel. This version of virt-v2v
+does I<not> attempt to install any new kernels. Instead it will give
+you an error if there are I<only> Xen PV kernels available.
+
+Therefore before conversion you should check that a regular kernel is
+installed. For some older Linux distributions, this means installing
+a kernel from the table below:
+
+ RHEL 3 (Does not apply, as there was no Xen PV kernel)
+
+ RHEL 4 i686 with > 10GB of RAM: install 'kernel-hugemem'
+ i686 SMP: install 'kernel-smp'
+ other i686: install 'kernel'
+ x86-64 SMP with > 8 CPUs: install 'kernel-largesmp'
+ x86-64 SMP: install 'kernel-smp'
+ other x86-64: install 'kernel'
+
+ RHEL 5 i686: install 'kernel-PAE'
+ x86-64: install 'kernel'
+
+ SLES 10 i586 with > 10GB of RAM: install 'kernel-bigsmp'
+ i586 SMP: install 'kernel-smp'
+ other i586: install 'kernel-default'
+ x86-64 SMP: install 'kernel-smp'
+ other x86-64: install 'kernel-default'
+
+ SLES 11+ i586: install 'kernel-pae'
+ x86-64: install 'kernel-default'
+
=head1 ENABLING VIRTIO
"Virtio" is the name for a set of drivers which make disk (block
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git
More information about the Pkg-libvirt-commits
mailing list