Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 00/14] Miscellaneous changes and fixes to virt-v2v
Miscellaneous changes to virt-v2v. This is just a dump of the patchset for virt-v2v that I'm working on, minus "the big one" which changes how virtio kernel/grub inspection works which is not ready for primetime yet. Rich.
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 01/14] v2v: Allow relative paths to appear in -i libvirtxml input.
When writing libvirt XML by hand, or for tests, this is
immensely useful.
---
mllib/common_utils.ml | 4 ++++
v2v/source_libvirt.ml | 28 ++++++++++++++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml
index 1aa81fb..60e3812 100644
--- a/mllib/common_utils.ml
+++ b/mllib/common_utils.ml
@@ -458,3 +458,7 @@ let is_char_device file let is_directory path try
Sys.is_directory path
with Sys_error _ -> false
+
+let absolute_path path + if not (Filename.is_relative path) then path
+ else Sys.getcwd () // path
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
index 3e252ed..245e0d2 100644
--- a/v2v/source_libvirt.ml
+++ b/v2v/source_libvirt.ml
@@ -24,7 +24,24 @@ open Common_utils
open Types
open Utils
-let create_xml xml +let create_xml ?dir xml + (* When reading libvirt XML from
a file (-i libvirtxml) we allow
+ * paths to disk images in the libvirt XML to be relative. Relative
+ * paths are in fact not permitted in real libvirt XML, but they are
+ * very useful when dealing with test images or when writing the XML
+ * by hand.
+ *)
+ let absolute_path_of_disk path + if not (Filename.is_relative path) then
path
+ else (
+ match dir with
+ | None ->
+ error (f_"libvirt returned a non-absolute path in the XML
(%s)") path
+ | Some dir ->
+ dir // path
+ )
+ in
+
let doc = Xml.parse_memory xml in
let xpathctx = Xml.xpath_new_context doc in
@@ -87,10 +104,12 @@ let create_xml xml match xpath_to_string
"@type" "" with
| "block" ->
let path = xpath_to_string "source/@dev" "" in
- if path <> "" then disks := (path, format) :: !disks
+ if path <> "" then
+ disks := (absolute_path_of_disk path, format) :: !disks
| "file" ->
let path = xpath_to_string "source/@file" "" in
- if path <> "" then disks := (path, format) :: !disks
+ if path <> "" then
+ disks := (absolute_path_of_disk path, format) :: !disks
| "network" ->
(* We only handle <source protocol="nbd"> here, and
that is
* intended only for virt-p2v. Any other network disk is
@@ -137,7 +156,8 @@ let create_xml xml
let create_from_xml file let xml = read_whole_file file in
- create_xml xml
+ let dir = Filename.dirname (absolute_path file) in
+ create_xml ~dir xml
let create libvirt_uri guest let cmd --
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 02/14] run: Add v2v/ subdirectory to $PATH.
--- run.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.in b/run.in index db29451..f09b8fd 100755 --- a/run.in +++ b/run.in @@ -74,7 +74,7 @@ fi # Set the PATH to contain all the libguestfs binaries. There are a # lot of binaries, so a lot of path entries. -PATH="$b/align:$b/builder:$b/cat:$b/customize:$b/df:$b/diff:$b/edit:$b/erlang:$b/fish:$b/format:$b/fuse:$b/inspector:$b/make-fs:$b/rescue:$b/resize:$b/sparsify:$b/sysprep:$b/test-tool:$b/tools:$PATH" +PATH="$b/align:$b/builder:$b/cat:$b/customize:$b/df:$b/diff:$b/edit:$b/erlang:$b/fish:$b/format:$b/fuse:$b/inspector:$b/make-fs:$b/rescue:$b/resize:$b/sparsify:$b/sysprep:$b/test-tool:$b/tools:$b/v2v:$PATH" export PATH # Set LD_LIBRARY_PATH to contain library. -- 1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 03/14] v2v: Print qemu-img source overlay command when using -v.
---
v2v/v2v.ml | 1 +
1 file changed, 1 insertion(+)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 6157aa3..4e64b99 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -66,6 +66,7 @@ let rec main () let cmd sprintf
"qemu-img create -q -f qcow2 -b %s -o %s %s"
(quote qemu_uri) (quote options) overlay in
+ if verbose then printf "%s\n%!" cmd;
if Sys.command cmd <> 0 then
error (f_"qemu-img command failed, see earlier errors");
overlay, qemu_uri, format
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 04/14] v2v: string_of_overlay already has trailing \n, don't need to add one.
---
v2v/v2v.ml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 4e64b99..fd6c049 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -162,7 +162,7 @@ let rec main () fun i ov ->
msg (f_"Copying disk %d/%d to %s (%s)")
(i+1) nr_overlays ov.ov_target_file ov.ov_target_format;
- if verbose then printf "%s\n%!" (string_of_overlay ov);
+ if verbose then printf "%s%!" (string_of_overlay ov);
(* It turns out that libguestfs's disk creation code is
* considerably more flexible and easier to use than qemu-img, so
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 05/14] v2v: Dump out 'source' structure when debugging.
---
v2v/types.ml | 24 ++++++++++++++++++++++++
v2v/types.mli | 3 +++
v2v/v2v.ml | 2 ++
3 files changed, 29 insertions(+)
diff --git a/v2v/types.ml b/v2v/types.ml
index 0f5ae86..9a41f18 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -40,6 +40,30 @@ type source = {
}
and source_disk = string * string option
+let rec string_of_source s + sprintf "\
+s_dom_type = %s
+s_name = %s
+s_memory = %Ld
+s_vcpu = %d
+s_arch = %s
+s_features = [%s]
+s_disks = [%s]
+"
+ s.s_dom_type
+ s.s_name
+ s.s_memory
+ s.s_vcpu
+ s.s_arch
+ (String.concat "," s.s_features)
+ (String.concat "," (List.map string_of_source_disk s.s_disks))
+
+and string_of_source_disk (path, format) + path ^
+ match format with
+ | None -> ""
+ | Some format -> " (" ^ format ^ ")"
+
type overlay = {
ov_overlay : string;
ov_target_file : string;
diff --git a/v2v/types.mli b/v2v/types.mli
index e7e72e0..87ba291 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -43,6 +43,9 @@ type source = {
and source_disk = string * string option
(** A source file is a qemu URI and a format. *)
+val string_of_source : source -> string
+val string_of_source_disk : source_disk -> string
+
type overlay = {
ov_overlay : string; (** Local overlay file (qcow2 format). *)
ov_target_file : string; (** Destination file (real). *)
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index fd6c049..838354f 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -45,6 +45,8 @@ let rec main () | InputLibvirtXML filename ->
Source_libvirt.create_from_xml filename in
+ if verbose then printf "%s%!" (string_of_source source);
+
(* Create a qcow2 v3 overlay to protect the source image(s). There
* is a specific reason to use the newer qcow2 variant: Because the
* L2 table can store zero clusters efficiently, and because
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 06/14] v2v: Print \n after warnings.
Using eprintf so this is not implicit (unlike 'error' function).
---
v2v/convert_linux_enterprise.ml | 6 +++---
v2v/convert_linux_grub.ml | 2 +-
v2v/source_libvirt.ml | 5 +++--
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
index 4313fa3..64eb93d 100644
--- a/v2v/convert_linux_enterprise.ml
+++ b/v2v/convert_linux_enterprise.ml
@@ -197,7 +197,7 @@ Grub1/grub-legacy error was: %s")
Convert_linux_common.augeas_reload verbose g
with
G.Error msg ->
- eprintf (f_"%s: warning: VirtualBox Guest Additions were
detected, but uninstallation failed. The error message was: %s (ignored)")
+ eprintf (f_"%s: warning: VirtualBox Guest Additions were
detected, but uninstallation failed. The error message was: %s
(ignored)\n%!")
prog msg
)
@@ -282,7 +282,7 @@ Grub1/grub-legacy error was: %s")
Convert_linux_common.augeas_reload verbose g
with
G.Error msg ->
- eprintf (f_"%s: warning: VMware tools was detected, but
uninstallation failed. The error message was: %s (ignored)")
+ eprintf (f_"%s: warning: VMware tools was detected, but
uninstallation failed. The error message was: %s (ignored)\n%!")
prog msg
)
@@ -372,7 +372,7 @@ Grub1/grub-legacy error was: %s")
upgrade_package "kernel" (0_l, "2.6.25.5",
"1.1")
| _ ->
- eprintf (f_"%s: warning: don't know how to install virtio
drivers for %s %d")
+ eprintf (f_"%s: warning: don't know how to install virtio
drivers for %s %d\n%!")
prog distro major_version;
false
diff --git a/v2v/convert_linux_grub.ml b/v2v/convert_linux_grub.ml
index 59dd4f2..1f4d1ae 100644
--- a/v2v/convert_linux_grub.ml
+++ b/v2v/convert_linux_grub.ml
@@ -272,7 +272,7 @@ object (self)
ignore (g#command [| "grub2-mkconfig"; "-o";
config_file |])
with
G.Error msg ->
- eprintf (f_"%s: warning: could not update grub2 console: %s
(ignored)\n")
+ eprintf (f_"%s: warning: could not update grub2 console: %s
(ignored)\n%!")
prog msg
)
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
index 245e0d2..520b1e3 100644
--- a/v2v/source_libvirt.ml
+++ b/v2v/source_libvirt.ml
@@ -128,11 +128,12 @@ let create_xml ?dir xml )
| "" -> ()
| protocol ->
- eprintf (f_"%s: warning: network <disk> with <source
protocol='%s'> was ignored")
+ eprintf (f_"%s: warning: network <disk> with <source
protocol='%s'> was ignored\n%!")
prog protocol
)
| disk_type ->
- eprintf (f_"%s: warning: <disk type='%s'> was
ignored") prog disk_type
+ eprintf (f_"%s: warning: <disk type='%s'> was
ignored\n%!")
+ prog disk_type
done;
List.rev !disks in
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 07/14] v2v: In -o local mode, name disks <name>-sda instead of disk-sda.
This allows us to use the same shared output directory for multiple
parallel tests.
---
v2v/target_local.ml | 4 ++--
v2v/target_local.mli | 2 +-
v2v/v2v.ml | 12 +++++++++---
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/v2v/target_local.ml b/v2v/target_local.ml
index ed4e5e3..b37b6fa 100644
--- a/v2v/target_local.ml
+++ b/v2v/target_local.ml
@@ -24,10 +24,10 @@ open Common_utils
open Types
open Utils
-let initialize dir overlays +let initialize dir source overlays List.map (
fun ov ->
- let target_file = dir // "disk-" ^ ov.ov_sd in
+ let target_file = dir // source.s_name ^ "-" ^ ov.ov_sd in
{ ov with ov_target_file = target_file; ov_target_file_tmp = target_file
}
) overlays
diff --git a/v2v/target_local.mli b/v2v/target_local.mli
index 1833ecb..4907ac1 100644
--- a/v2v/target_local.mli
+++ b/v2v/target_local.mli
@@ -16,6 +16,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
-val initialize : string -> Types.overlay list -> Types.overlay list
+val initialize : string -> Types.source -> Types.overlay list ->
Types.overlay list
val create_metadata : string -> Types.source -> Types.overlay list ->
Types.guestcaps -> unit
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 838354f..f7d29a3 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -93,7 +93,8 @@ let rec main () * work.
*)
let overlays - initialize_target g output output_alloc output_format
overlays in
+ initialize_target g
+ source output output_alloc output_format output_name overlays in
(* Inspection - this also mounts up the filesystems. *)
msg (f_"Inspecting the overlay");
@@ -214,7 +215,8 @@ let rec main () if debug_gc then
Gc.compact ()
-and initialize_target g output output_alloc output_format overlays +and
initialize_target g
+ source output output_alloc output_format output_name overlays let
overlays mapi (
fun i (overlay, qemu_uri, backing_format) ->
@@ -247,9 +249,13 @@ and initialize_target g output output_alloc output_format
overlays ov_source_file = qemu_uri; ov_source_format =
backing_format; }
) overlays in
let overlays + let renamed_source + match output_name with
+ | None -> source
+ | Some name -> { source with s_name = name } in
match output with
| OutputLibvirt oc -> assert false
- | OutputLocal dir -> Target_local.initialize dir overlays
+ | OutputLocal dir -> Target_local.initialize dir renamed_source overlays
| OutputRHEV os -> assert false in
overlays
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 08/14] v2v: Avoid segfault if xpath expression doesn't match any nodes.
I'm not sure if this indicates that the xpath expression is wrong, but in any case it can be that xpathobj->nodesetval is NULL. In this case, return 0 from xpathobj_nr_nodes instead of segfaulting. --- v2v/xml-c.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/v2v/xml-c.c b/v2v/xml-c.c index a1b796c..cf5bff2 100644 --- a/v2v/xml-c.c +++ b/v2v/xml-c.c @@ -165,7 +165,10 @@ v2v_xml_xpathobj_nr_nodes (value xpathobjv) CAMLparam1 (xpathobjv); xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv); - CAMLreturn (Val_int (xpathobj->nodesetval->nodeNr)); + if (xpathobj->nodesetval == NULL) + CAMLreturn (Val_int (0)); + else + CAMLreturn (Val_int (xpathobj->nodesetval->nodeNr)); } value -- 1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 09/14] v2v: When parsing input libvirt XML, get correct disk image format.
Old Xen PV guests had:
<driver name='tap' type='aio'/>
The previous xpath expression matched any driver type attribute in
order to pick up the format. However we only want to match:
<driver name='qemu' type='raw'/>
so we need to check the name attribute as well.
---
v2v/source_libvirt.ml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
index 520b1e3..4a3c9f1 100644
--- a/v2v/source_libvirt.ml
+++ b/v2v/source_libvirt.ml
@@ -95,7 +95,7 @@ let create_xml ?dir xml
Xml.xpathctx_set_current_context xpathctx node;
let format - let format = xpath_to_string "driver/@type"
"" in
+ let format = xpath_to_string
"driver[name='qemu']/@type" "" in
if format <> "" then Some format else None in
(* The <disk type='...'> attribute may be 'block',
'file' or
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 10/14] mllib: Move common code for comparing version strings to library.
--- builder/get_kernel.ml | 26 -------------------------- mllib/common_utils.ml | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/builder/get_kernel.ml b/builder/get_kernel.ml index 25e4293..7f93728 100644 --- a/builder/get_kernel.ml +++ b/builder/get_kernel.ml @@ -23,9 +23,6 @@ module G = Guestfs open Printf -let rex_numbers = Str.regexp "^\\([0-9]+\\)\\(.*\\)$" -let rex_letters = Str.regexp_case_fold "^\\([a-z]+\\)\\(.*\\)$" - (* Originally: * http://rwmj.wordpress.com/2013/09/13/get-kernel-and-initramfs-from-a-disk-image/ *) @@ -96,26 +93,3 @@ let rec get_kernel ~debug ?format ?output disk (* Shutdown. *) g#shutdown (); g#close () - -and compare_version v1 v2 - compare (split_version v1) (split_version v2) - -and split_version = function - | "" -> [] - | str -> - let first, rest - if Str.string_match rex_numbers str 0 then ( - let n = Str.matched_group 1 str in - let rest = Str.matched_group 2 str in - let n - try `Number (int_of_string n) - with Failure "int_of_string" -> `String n in - n, rest - ) - else if Str.string_match rex_letters str 0 then - `String (Str.matched_group 1 str), Str.matched_group 2 str - else ( - let len = String.length str in - `Char str.[0], String.sub str 1 (len-1) - ) in - first :: split_version rest diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 60e3812..d4a97a7 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -340,6 +340,33 @@ let display_long_options () ) !long_options; exit 0 +(* Compare two version strings intelligently. *) +let rex_numbers = Str.regexp "^\\([0-9]+\\)\\(.*\\)$" +let rex_letters = Str.regexp_case_fold "^\\([a-z]+\\)\\(.*\\)$" + +let compare_version v1 v2 + let rec split_version = function + | "" -> [] + | str -> + let first, rest + if Str.string_match rex_numbers str 0 then ( + let n = Str.matched_group 1 str in + let rest = Str.matched_group 2 str in + let n + try `Number (int_of_string n) + with Failure "int_of_string" -> `String n in + n, rest + ) + else if Str.string_match rex_letters str 0 then + `String (Str.matched_group 1 str), Str.matched_group 2 str + else ( + let len = String.length str in + `Char str.[0], String.sub str 1 (len-1) + ) in + first :: split_version rest + in + compare (split_version v1) (split_version v2) + (* Run an external command, slurp up the output as a list of lines. *) let external_command ~prog cmd let chan = Unix.open_process_in cmd in -- 1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 11/14] v2v: In convert function, add a hash of app name -> app structure.
For quicker lookups than searching the linear list.
---
v2v/convert_linux_enterprise.ml | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
index 64eb93d..11627a9 100644
--- a/v2v/convert_linux_enterprise.ml
+++ b/v2v/convert_linux_enterprise.ml
@@ -32,7 +32,9 @@ open Common_utils
open Utils
open Types
-let rec convert ?(keep_serial_console = true) verbose (g : Guestfs.guestfs)
+module StringMap = Map.Make (String)
+
+let rec convert ?(keep_serial_console = true) verbose (g : G.guestfs)
({ i_root = root; i_apps = apps }
as inspect) source let typ = g#inspect_get_type root
@@ -52,6 +54,17 @@ let rec convert ?(keep_serial_console = true) verbose (g :
Guestfs.guestfs)
and is_suse_family (distro = "sles" || distro =
"suse-based" || distro = "opensuse") in
+ (* A map of app2_name -> application2, for easier lookups. Note
+ * that app names are not unique! (eg. 'kernel' can appear multiple
+ * times)
+ *)
+ let apps_map = List.fold_left (
+ fun map app ->
+ let name = app.G.app2_name in
+ let vs = try StringMap.find name map with Not_found -> [] in
+ StringMap.add name (app :: vs) map
+ ) StringMap.empty apps in
+
let rec clean_rpmdb () (* Clean RPM database. *)
assert (package_format = "rpm");
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 12/14] v2v: Warn only if virtio packages are missing from the guest.
In this version of virt-v2v you have to install a virtio
capable kernel before doing the conversion.
---
v2v/convert_linux_enterprise.ml | 92 ++++++++++++++++++++++++++++++-----------
v2v/virt-v2v.pod | 34 +++++++++++++++
2 files changed, 102 insertions(+), 24 deletions(-)
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
index 11627a9..6544b27 100644
--- a/v2v/convert_linux_enterprise.ml
+++ b/v2v/convert_linux_enterprise.ml
@@ -350,26 +350,28 @@ Grub1/grub-legacy error was: %s")
if !updated then g#aug_save ();
)
- and install_virtio () - (* How you install virtio depends on the guest
type. Note that most
- * modern guests already support virtio, so we do nothing for them.
- * In Perl virt-v2v this was done via a configuration database
- * (virt-v2v.db). This function returns true if virtio is supported
- * already or if we managed to install it.
+ 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 = upgrade_package "kernel" (0_l, "2.6.18",
"128.el5") in
- let lvm2 = upgrade_package "lvm2" (0_l, "2.02.40",
"6.el5") in
+ 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 - upgrade_package ~ifinstalled:true
+ check_package ~ifinstalled:true
"selinux-policy-targeted" (0_l, "2.4.6",
"203.el5") in
kernel && lvm2 && selinux
|
("rhel"|"centos"|"scientificlinux"|"redhat-based"),
4, _ ->
- upgrade_package "kernel" (0_l, "2.6.9",
"89.EL")
+ check_kernel_package (0_l, "2.6.9", "89.EL")
(* All supported Fedora versions support virtio. *)
| "fedora", _, _ -> true
@@ -377,18 +379,71 @@ Grub1/grub-legacy error was: %s")
(* SLES 11 supports virtio in the kernel. *)
| ("sles"|"suse-based"), v, _ when v >= 11 ->
true
| ("sles"|"suse-based"), 10, _ ->
- upgrade_package "kernel" (0_l, "2.6.16.60",
"0.85.1")
+ check_kernel_package (0_l, "2.6.16.60", "0.85.1")
(* OpenSUSE. *)
| "opensuse", v, _ when v >= 11 -> true
| "opensuse", 10, _ ->
- upgrade_package "kernel" (0_l, "2.6.25.5",
"1.1")
+ check_kernel_package (0_l, "2.6.25.5", "1.1")
| _ ->
eprintf (f_"%s: warning: don't know how to install virtio
drivers for %s %d\n%!")
prog 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
+ eprintf (f_"%s: warning: cannot enable virtio in this guest.\nTo
enable virtio you need to install a kernel >= %s-%s and run %s
again.\n%!")
+ prog 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
+ eprintf (f_"%s: warning: cannot enable virtio in this guest.\nTo
enable virtio you need to upgrade %s >= %s-%s and run %s again.\n%!")
+ prog name minversion minrelease prog
+ );
+ false
+
+ and compare_app2_versions app1 app2 + let i = compare app1.G.app2_epoch
app2.G.app2_epoch in
+ if i <> 0 then i
+ else (
+ let i = compare_version app1.G.app2_version app2.G.app2_version in
+ if i <> 0 then i
+ else
+ compare_version app1.G.app2_release app2.G.app2_release
+ )
+
+ and compare_app2_version_min app1 (min_epoch, min_version, min_release) +
let i = compare app1.G.app2_epoch min_epoch in
+ if i <> 0 then i
+ else (
+ let i = compare_version app1.G.app2_version min_version in
+ if i <> 0 then i
+ else
+ compare_version app1.G.app2_release min_release
+ )
+
and configure_kernel virtio grub let kernels = grub#list_kernels () in
@@ -600,17 +655,6 @@ Grub1/grub-legacy error was: %s")
g#aug_save ()
- (* Upgrade 'pkg' to >= minversion. Returns true if that was
possible. *)
- and upgrade_package ?(ifinstalled = false) name minversion -
-
-
-
-
- (* XXX *)
- true
-
-
in
clean_rpmdb ();
@@ -623,7 +667,7 @@ Grub1/grub-legacy error was: %s")
unconfigure_vmware ();
unconfigure_citrix ();
- let virtio = install_virtio () 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 ();
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index 810bed5..b7f4726 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -208,6 +208,40 @@ Enable tracing of libguestfs API calls.
=back
+=head1 ENABLING VIRTIO
+
+"Virtio" is the name for a set of drivers which make disk (block
+device), network and other guest operations work much faster on KVM.
+
+Older versions of virt-v2v could install these drivers for certain
+guests. This version of virt-v2v does I<not> attempt to install these
+drivers, but will warn you if they are not installed already.
+
+In order to enable virtio, and hence improve performance of the guest
+after conversion, you should ensure that the B<minimum> versions of
+packages are installed I<before> conversion, by consulting the table
+below.
+
+ RHEL 3 No virtio drivers are available
+
+ RHEL 4 kernel >= 2.5.9-89.EL
+
+ RHEL 5 kernel >= 2.6.18-128.el5
+ lvm2 >= 2.02.40-6.el5
+ selinux-policy-targeted >= 2.4.6-203.el5
+
+ RHEL 6+ All versions support virtio
+
+ Fedora All versions support virtio
+
+ SLES 11+ All versions support virtio
+
+ SLES 10 kernel >= 2.6.16.60-0.85.1
+
+ OpenSUSE 11+ All versions support virtio
+
+ OpenSUSE 10 kernel >= 2.6.25.5-1.1
+
=head1 MACHINE READABLE OUTPUT
The I<--machine-readable> option can be used to make the output more
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 13/14] mllib: Add an interface for Common_utils library.
It turned out that Common_utils was exporting the 'G' module (an alias
for Guestfs). We want any code that uses G as a shortcut to declare:
module G = Guestfs
at the top, since that avoids confusion for newbie (or experienced)
OCaml programmers.
---
mllib/Makefile.am | 1 +
mllib/common_utils.mli | 116 ++++++++++++++++++++++++++++++++++++++++
sparsify/cmdline.ml | 2 +-
v2v/convert_linux_common.ml | 4 +-
v2v/convert_linux_enterprise.ml | 2 +
5 files changed, 122 insertions(+), 3 deletions(-)
create mode 100644 mllib/common_utils.mli
diff --git a/mllib/Makefile.am b/mllib/Makefile.am
index 72a032c..7c242fc 100644
--- a/mllib/Makefile.am
+++ b/mllib/Makefile.am
@@ -26,6 +26,7 @@ CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o
SOURCES = \
common_gettext.ml \
common_utils.ml \
+ common_utils.mli \
common_utils_tests.ml \
config.ml \
fsync-c.c \
diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli
new file mode 100644
index 0000000..4368e57
--- /dev/null
+++ b/mllib/common_utils.mli
@@ -0,0 +1,116 @@
+(* Common utilities for OCaml tools in libguestfs.
+ * Copyright (C) 2010-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.
+ *)
+
+val ( // ) : string -> string -> string
+(** Concatenate directory and filename. *)
+
+val ( +^ ) : int64 -> int64 -> int64
+val ( -^ ) : int64 -> int64 -> int64
+val ( *^ ) : int64 -> int64 -> int64
+val ( /^ ) : int64 -> int64 -> int64
+val ( &^ ) : int64 -> int64 -> int64
+val ( ~^ ) : int64 -> int64
+(** Various int64 operators. *)
+
+val roundup64 : int64 -> int64 -> int64
+val int_of_le32 : string -> int64
+val le32_of_int : int64 -> string
+
+val wrap : ?chan:out_channel -> ?hanging:int -> string -> unit
+(** Wrap text. *)
+
+val string_prefix : string -> string -> bool
+val string_find : string -> string -> int
+val replace_str : string -> string -> string -> string
+val string_nsplit : string -> string -> string list
+val string_split : string -> string -> string * string
+val string_random8 : unit -> string
+(** Various string functions. *)
+
+val dropwhile : ('a -> bool) -> 'a list -> 'a list
+val takewhile : ('a -> bool) -> 'a list -> 'a list
+val filter_map : ('a -> 'b option) -> 'a list -> 'b
list
+val iteri : (int -> 'a -> 'b) -> 'a list -> unit
+val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
+(** Various higher-order functions. *)
+
+val make_message_function : quiet:bool -> ('a, unit, string, unit)
format4 -> 'a
+(** Timestamped progress messages. Used for ordinary messages when
+ not [--quiet]. *)
+
+val error : prog:string -> ?exit_code:int -> ('a, unit, string,
'b) format4 -> 'a
+(** Standard error function. *)
+
+val read_whole_file : string -> string
+(** Read in the whole file as a string. *)
+
+val parse_size : prog:string -> string -> int64
+(** Parse a size field, eg. [10G] *)
+
+val parse_resize : prog:string -> int64 -> string -> int64
+(** Parse a size field, eg. [10G], [+20%] etc. Used particularly by
+ [virt-resize --resize] and [--resize-force] options. *)
+
+val human_size : int64 -> string
+(** Converts a size in bytes to a human-readable string. *)
+
+val skip_dashes : string -> string
+(** Skip any leading '-' characters when comparing command line args.
*)
+
+val compare_command_line_args : string -> string -> int
+(** Compare command line arguments for equality, ignoring any leading [-]s. *)
+
+val long_options : (Arg.key * Arg.spec * Arg.doc) list ref
+val display_long_options : unit -> 'a
+(** Implements [--long-options]. *)
+
+val compare_version : string -> string -> int
+(** Compare two version strings. *)
+
+val external_command : prog:string -> string -> string list
+(** Run an external command, slurp up the output as a list of lines. *)
+
+val uuidgen : prog:string -> unit -> string
+(** Run uuidgen to return a random UUID. *)
+
+val unlink_on_exit : string -> unit
+(** Unlink a temporary file on exit. *)
+
+val rmdir_on_exit : string -> unit
+(** Remove a temporary directory on exit (using [rm -rf]). *)
+
+val rm_rf_only_files : Guestfs.guestfs -> string -> unit
+(** Using the libguestfs API, recursively remove only files from the
+ given directory. Useful for cleaning [/var/cache] etc in sysprep
+ without removing the actual directory structure. Also if [dir] is
+ not a directory or doesn't exist, ignore it.
+
+ XXX Could be faster with a specific API for doing this. *)
+
+val detect_compression : string -> [`Unknown | `XZ]
+(** Detect compression of a file.
+
+ XXX Only detects the formats we need in virt-builder so far. *)
+
+val is_block_device : string -> bool
+val is_char_device : string -> bool
+val is_directory : string -> bool
+(** These don't throw exceptions, unlike the [Sys] functions. *)
+
+val absolute_path : string -> string
+(** Convert any path to an absolute path. *)
diff --git a/sparsify/cmdline.ml b/sparsify/cmdline.ml
index 01f66f1..11e5895 100644
--- a/sparsify/cmdline.ml
+++ b/sparsify/cmdline.ml
@@ -131,7 +131,7 @@ read the man page virt-sparsify(1).
printf "check-tmpdir\n";
printf "in-place\n";
printf "tmp-option\n";
- let g = new G.guestfs () in
+ let g = new Guestfs.guestfs () in
g#add_drive "/dev/null";
g#launch ();
if g#feature_available [| "ntfsprogs"; "ntfs3g" |] then
diff --git a/v2v/convert_linux_common.ml b/v2v/convert_linux_common.ml
index 4922e2f..57a171a 100644
--- a/v2v/convert_linux_common.ml
+++ b/v2v/convert_linux_common.ml
@@ -96,7 +96,7 @@ and augeas_debug_errors g
flush stdout
with
- G.Error msg -> eprintf "%s: augeas: %s (ignored)\n" prog msg
+ Guestfs.Error msg -> eprintf "%s: augeas: %s (ignored)\n" prog
msg
let install verbose g inspect packages assert false
@@ -125,7 +125,7 @@ let file_owned verbose g inspect file match
package_format with
| "rpm" ->
let cmd = [| "rpm"; "-qf"; file |] in
- (try ignore (g#command cmd); true with G.Error _ -> false)
+ (try ignore (g#command cmd); true with Guestfs.Error _ -> false)
| format ->
error (f_"don't know how to find package owner using %s")
format
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
index 6544b27..8bf8f33 100644
--- a/v2v/convert_linux_enterprise.ml
+++ b/v2v/convert_linux_enterprise.ml
@@ -32,6 +32,8 @@ open Common_utils
open Utils
open Types
+module G = Guestfs
+
module StringMap = Map.Make (String)
let rec convert ?(keep_serial_console = true) verbose (g : G.guestfs)
--
1.9.0
Richard W.M. Jones
2014-Jun-23 11:32 UTC
[Libguestfs] [PATCH 14/14] mllib: Add a common 'warning' utility function.
This commit changes many places in OCaml utilities that print
warnings to use the warning function instead.
---
builder/builder.ml | 7 +++----
customize/customize_run.ml | 11 ++++-------
customize/password.ml | 11 ++++-------
mllib/common_utils.ml | 7 +++++++
mllib/common_utils.mli | 3 +++
resize/resize.ml | 2 +-
sysprep/sysprep_operation_fs_uuids.ml | 6 +++++-
v2v/convert_linux_enterprise.ml | 20 ++++++++++----------
v2v/convert_linux_grub.ml | 5 +++--
v2v/source_libvirt.ml | 7 +++----
10 files changed, 43 insertions(+), 36 deletions(-)
diff --git a/builder/builder.ml b/builder/builder.ml
index 5c2f6bb..70c9430 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -126,7 +126,7 @@ let main () exit 1
)
else if debug then
- eprintf (f_"%s: warning: gpg program is not available\n") prog
+ warning ~prog (f_"gpg program is not available")
);
(* Check that curl works. *)
@@ -150,9 +150,8 @@ let main () | Some dir ->
try Some (Cache.create ~debug ~directory:dir)
with exn ->
- eprintf (f_"%s: warning: cache %s: %s\n") prog dir
- (Printexc.to_string exn);
- eprintf (f_"%s: disabling the cache\n%!") prog;
+ warning ~prog (f_"cache %s: %s") dir (Printexc.to_string
exn);
+ warning ~prog (f_"disabling the cache");
None
in
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 4d83e90..57b888f 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -149,7 +149,7 @@ exec >>%s 2>&1
(* Set the random seed. *)
msg (f_"Setting a random seed");
if not (Random_seed.set_random_seed g root) then
- eprintf (f_"%s: warning: random seed could not be set for this type of
guest\n%!") prog;
+ warning ~prog (f_"random seed could not be set for this type of
guest");
(* Used for numbering firstboot commands. *)
let i = ref 0 in
@@ -216,8 +216,7 @@ exec >>%s 2>&1
| `Hostname hostname ->
msg (f_"Setting the hostname: %s") hostname;
if not (Hostname.set_hostname g root hostname) then
- eprintf (f_"%s: warning: hostname could not be set for this type
of guest\n%!")
- prog
+ warning ~prog (f_"hostname could not be set for this type of
guest")
| `InstallPackages pkgs ->
msg (f_"Installing packages: %s") (String.concat " "
pkgs);
@@ -253,8 +252,7 @@ exec >>%s 2>&1
| `Timezone tz ->
msg (f_"Setting the timezone: %s") tz;
if not (Timezone.set_timezone ~prog g root tz) then
- eprintf (f_"%s: warning: timezone could not be set for this type
of guest\n%!")
- prog
+ warning ~prog (f_"timezone could not be set for this type of
guest")
| `Update ->
msg (f_"Updating core packages");
@@ -294,8 +292,7 @@ exec >>%s 2>&1
set_linux_passwords ~prog ?password_crypto g root passwords
| _ ->
- eprintf (f_"%s: warning: passwords could not be set for this type of
guest\n%!")
- prog
+ warning ~prog (f_"passwords could not be set for this type of
guest")
);
if ops.flags.selinux_relabel then (
diff --git a/customize/password.ml b/customize/password.ml
index 6527138..d76ebea 100644
--- a/customize/password.ml
+++ b/customize/password.ml
@@ -84,7 +84,7 @@ let chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./"
let rec set_linux_passwords ~prog ?password_crypto g root passwords let
crypto match password_crypto with
- | None -> default_crypto g root
+ | None -> default_crypto ~prog g root
| Some c -> c in
(* XXX Would like to use Augeas here, but Augeas doesn't support
@@ -145,7 +145,7 @@ and encrypt password crypto * precede this date only
support md5, whereas all guests after this
* date can support sha512.
*)
-and default_crypto g root +and default_crypto ~prog g root let distro =
g#inspect_get_distro root in
let major = g#inspect_get_major_version root in
match distro, major with
@@ -167,9 +167,6 @@ and default_crypto g root | "ubuntu", _ ->
`MD5
| _, _ ->
- eprintf (f_"\
-virt-sysprep: password: warning: using insecure md5 password encryption for
-guest of type %s version %d.
-If this is incorrect, use --password-crypto option and file a bug.\n%!")
- distro major;
+ warning ~prog (f_"password: using insecure md5 password encryption for
+guest of type %s version %d.\nIf this is incorrect, use --password-crypto
option and file a bug.") distro major;
`MD5
diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml
index d4a97a7..1ce2abe 100644
--- a/mllib/common_utils.ml
+++ b/mllib/common_utils.ml
@@ -208,6 +208,13 @@ let error ~prog ?(exit_code = 1) fs in
ksprintf display fs
+let warning ~prog fs + let display str + wrap ~chan:stderr (sprintf
(f_"%s: warning: %s") prog str);
+ prerr_newline ();
+ in
+ ksprintf display fs
+
let read_whole_file path let buf = Buffer.create 16384 in
let chan = open_in path in
diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli
index 4368e57..16b9dee 100644
--- a/mllib/common_utils.mli
+++ b/mllib/common_utils.mli
@@ -56,6 +56,9 @@ val make_message_function : quiet:bool -> ('a, unit,
string, unit) format4 -> 'a
val error : prog:string -> ?exit_code:int -> ('a, unit, string,
'b) format4 -> 'a
(** Standard error function. *)
+val warning : prog:string -> ('a, unit, string, unit) format4 ->
'a
+(** Standard warning function. *)
+
val read_whole_file : string -> string
(** Read in the whole file as a string. *)
diff --git a/resize/resize.ml b/resize/resize.ml
index c6b6c9e..dec23b1 100644
--- a/resize/resize.ml
+++ b/resize/resize.ml
@@ -1160,7 +1160,7 @@ read the man page virt-resize(1).
(* Sanity check: it contains the NTFS magic. *)
let magic = g#pread_device target 8 3L in
if magic <> "NTFS " then
- eprintf (f_"warning: first partition is NTFS but does not contain
NTFS boot loader magic\n%!")
+ warning ~prog (f_"first partition is NTFS but does not contain
NTFS boot loader magic")
else (
if not quiet then
printf (f_"Fixing first NTFS partition boot record
...\n%!");
diff --git a/sysprep/sysprep_operation_fs_uuids.ml
b/sysprep/sysprep_operation_fs_uuids.ml
index 32ee67d..57ccd68 100644
--- a/sysprep/sysprep_operation_fs_uuids.ml
+++ b/sysprep/sysprep_operation_fs_uuids.ml
@@ -19,10 +19,14 @@
open Printf
open Sysprep_operation
+
open Common_gettext.Gettext
+open Common_utils
module G = Guestfs
+let prog = "virt-sysprep"
+
let rec fs_uuids_perform ~debug ~quiet g root side_effects let fses =
g#list_filesystems () in
List.iter (function
@@ -35,7 +39,7 @@ let rec fs_uuids_perform ~debug ~quiet g root side_effects
g#set_uuid dev new_uuid
with
G.Error msg ->
- eprintf (f_"warning: cannot set random UUID on filesystem %s type
%s: %s\n")
+ warning ~prog (f_"cannot set random UUID on filesystem %s type %s:
%s")
dev typ msg
) fses
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
index 8bf8f33..e3cfab8 100644
--- a/v2v/convert_linux_enterprise.ml
+++ b/v2v/convert_linux_enterprise.ml
@@ -212,8 +212,8 @@ Grub1/grub-legacy error was: %s")
Convert_linux_common.augeas_reload verbose g
with
G.Error msg ->
- eprintf (f_"%s: warning: VirtualBox Guest Additions were
detected, but uninstallation failed. The error message was: %s
(ignored)\n%!")
- prog msg
+ warning ~prog (f_"VirtualBox Guest Additions were detected,
but uninstallation failed. The error message was: %s (ignored)")
+ msg
)
and unconfigure_vmware () @@ -297,8 +297,8 @@ Grub1/grub-legacy error was:
%s")
Convert_linux_common.augeas_reload verbose g
with
G.Error msg ->
- eprintf (f_"%s: warning: VMware tools was detected, but
uninstallation failed. The error message was: %s (ignored)\n%!")
- prog msg
+ warning ~prog (f_"VMware tools was detected, but uninstallation
failed. The error message was: %s (ignored)")
+ msg
)
and unconfigure_citrix () @@ -389,8 +389,8 @@ Grub1/grub-legacy error was:
%s")
check_kernel_package (0_l, "2.6.25.5", "1.1")
| _ ->
- eprintf (f_"%s: warning: don't know how to install virtio
drivers for %s %d\n%!")
- prog distro major_version;
+ warning ~prog (f_"don't know how to install virtio drivers for
%s %d\n%!")
+ distro major_version;
false
and check_kernel_package minversion @@ -401,8 +401,8 @@ Grub1/grub-legacy
error was: %s")
) names in
if not found then (
let _, minversion, minrelease = minversion in
- eprintf (f_"%s: warning: cannot enable virtio in this guest.\nTo
enable virtio you need to install a kernel >= %s-%s and run %s
again.\n%!")
- prog minversion minrelease prog
+ 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
@@ -421,8 +421,8 @@ Grub1/grub-legacy error was: %s")
| _ ->
if warn then (
let _, minversion, minrelease = minversion in
- eprintf (f_"%s: warning: cannot enable virtio in this guest.\nTo
enable virtio you need to upgrade %s >= %s-%s and run %s again.\n%!")
- prog name minversion minrelease prog
+ 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
diff --git a/v2v/convert_linux_grub.ml b/v2v/convert_linux_grub.ml
index 1f4d1ae..1b02141 100644
--- a/v2v/convert_linux_grub.ml
+++ b/v2v/convert_linux_grub.ml
@@ -21,6 +21,7 @@ module G = Guestfs
open Printf
open Common_gettext.Gettext
+open Common_utils
open Utils
open Types
@@ -272,8 +273,8 @@ object (self)
ignore (g#command [| "grub2-mkconfig"; "-o";
config_file |])
with
G.Error msg ->
- eprintf (f_"%s: warning: could not update grub2 console: %s
(ignored)\n%!")
- prog msg
+ warning ~prog (f_"could not update grub2 console: %s
(ignored)")
+ msg
)
method configure_console () = self#update_console ~remove:false
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
index 4a3c9f1..d9c7b5e 100644
--- a/v2v/source_libvirt.ml
+++ b/v2v/source_libvirt.ml
@@ -128,12 +128,11 @@ let create_xml ?dir xml )
| "" -> ()
| protocol ->
- eprintf (f_"%s: warning: network <disk> with <source
protocol='%s'> was ignored\n%!")
- prog protocol
+ warning ~prog (f_"network <disk> with <source
protocol='%s'> was ignored")
+ protocol
)
| disk_type ->
- eprintf (f_"%s: warning: <disk type='%s'> was
ignored\n%!")
- prog disk_type
+ warning ~prog (f_"<disk type='%s'> was
ignored") disk_type
done;
List.rev !disks in
--
1.9.0