[PATCH] sysprep: remove also hidden files/dirs in temporary dirs
by Pino Toscano
List manually and remove the content left (hidden files/directories) in
temporary directories after the glob listing & removal.
---
sysprep/sysprep_operation_tmp_files.ml | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/sysprep/sysprep_operation_tmp_files.ml b/sysprep/sysprep_operation_tmp_files.ml
index dc0247e..d5a52f3 100644
--- a/sysprep/sysprep_operation_tmp_files.ml
+++ b/sysprep/sysprep_operation_tmp_files.ml
@@ -24,15 +24,22 @@ module G = Guestfs
let tmp_files_perform ~debug ~quiet g root side_effects =
let typ = g#inspect_get_type root in
if typ <> "windows" then (
- let paths = [ "/tmp/*";
- "/var/tmp/*"; ] in
+ let paths = [ "/tmp";
+ "/var/tmp"; ] in
List.iter (
fun path ->
- let files = g#glob_expand path in
+ let files = g#glob_expand (path ^ "/*") in
Array.iter (
fun file ->
g#rm_rf file;
) files;
+ (try
+ let files = g#ls path in
+ Array.iter (
+ fun file ->
+ g#rm_rf (path ^ "/" ^ file);
+ ) files
+ with G.Error _ -> ());
) paths
)
--
1.9.0
10 years, 7 months
[PATCH] listfs: If LDM not available, don't inhibit partition detection (RHBZ#1079182).
by Richard W.M. Jones
If a disk has type 0x42 partition (which would indicate LDM), but LDM
is not available then try parsing the partition anyway. It might be
parseable as plain old NTFS.
---
src/listfs.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/listfs.c b/src/listfs.c
index bbdb0a2..ffb0adc 100644
--- a/src/listfs.c
+++ b/src/listfs.c
@@ -47,8 +47,11 @@ guestfs__list_filesystems (guestfs_h *g)
{
size_t i;
DECLARE_STRINGSBUF (ret);
+
const char *lvm2[] = { "lvm2", NULL };
+ int has_lvm2 = guestfs_feature_available (g, (char **) lvm2);
const char *ldm[] = { "ldm", NULL };
+ int has_ldm = guestfs_feature_available (g, (char **) ldm);
CLEANUP_FREE_STRING_LIST char **devices = NULL;
CLEANUP_FREE_STRING_LIST char **partitions = NULL;
@@ -83,7 +86,7 @@ guestfs__list_filesystems (guestfs_h *g)
/* Use vfs-type to check for filesystems on partitions. */
for (i = 0; partitions[i] != NULL; ++i) {
- if (! is_mbr_partition_type_42 (g, partitions[i])) {
+ if (has_ldm == 0 || ! is_mbr_partition_type_42 (g, partitions[i])) {
if (check_with_vfs_type (g, partitions[i], &ret) == -1)
goto error;
}
@@ -94,7 +97,7 @@ guestfs__list_filesystems (guestfs_h *g)
if (check_with_vfs_type (g, mds[i], &ret) == -1)
goto error;
- if (guestfs_feature_available (g, (char **) lvm2)) {
+ if (has_lvm2 > 0) {
/* Use vfs-type to check for filesystems on LVs. */
lvs = guestfs_lvs (g);
if (lvs == NULL) goto error;
@@ -104,7 +107,7 @@ guestfs__list_filesystems (guestfs_h *g)
goto error;
}
- if (guestfs_feature_available (g, (char **) ldm)) {
+ if (has_ldm > 0) {
/* Use vfs-type to check for filesystems on Windows dynamic disks. */
ldmvols = guestfs_list_ldm_volumes (g);
if (ldmvols == NULL) goto error;
--
1.8.5.3
10 years, 7 months
Problem with virt-sysprep
by Stuart Young
Hi there,
I was wondering if you could help me with a problem I'm having with
virt-sysprep. It's a recurrent problem running virt-sysprep:
Examining the guest ...
Fatal error: exception Guestfs.Error("guestfs_launch failed.
See http://libguestfs.org/guestfs-faq.1.html#debugging-libguestfs
and/or run 'libguestfs-test-tool'.")
So I ran virt-sysprep and libguestfs-test-tool after setting these:
export LIBGUESTFS_DEBUG=1
export LIBGUESTFS_TRACE=1
... and have attached the output files.
Do you have any ideas on how to fix this?
Bests,
Stuart
--
Stuart Young
Director of Bioinformatics
Annai Systems
2100 Palomar Airport Road, Suite 210,
Carlsbad, CA 92008
Mobile: 305-781-2286
Email: stuarty(a)annaisystems.com
10 years, 7 months
[PATCH 1/8] sysprep: remove systemd journals
by Pino Toscano
---
sysprep/sysprep_operation_logfiles.ml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sysprep/sysprep_operation_logfiles.ml b/sysprep/sysprep_operation_logfiles.ml
index cf525c2..bb35daf 100644
--- a/sysprep/sysprep_operation_logfiles.ml
+++ b/sysprep/sysprep_operation_logfiles.ml
@@ -101,6 +101,9 @@ let globs = List.sort compare [
(* Red Hat subscription manager log files *)
"/var/log/rhsm/*";
+
+ (* journals of systemd *)
+ "/var/log/journal/*";
]
let globs_as_pod = String.concat "\n" (List.map ((^) " ") globs)
--
1.9.0
10 years, 7 months
[PATCH v3 NOT TO BE APPLIED] New tool: virt-v2v.
by Richard W.M. Jones
This is a rewrite of the original virt-v2v tool. The original was
written by Matt Booth et al in Perl between 2009 and 2013.
---
.gitignore | 5 +
Makefile.am | 6 +-
configure.ac | 3 +-
fish/guestfish.pod | 1 +
po/POTFILES | 2 +
po/POTFILES-ml | 11 ++
src/guestfs.pod | 5 +
v2v/Makefile.am | 185 +++++++++++++++++++++
v2v/README | 15 ++
v2v/cmdline.ml | 197 ++++++++++++++++++++++
v2v/convert_linux_common.ml | 131 +++++++++++++++
v2v/convert_linux_common.mli | 35 ++++
v2v/convert_linux_enterprise.ml | 185 +++++++++++++++++++++
v2v/convert_linux_enterprise.mli | 19 +++
v2v/convert_linux_grub.ml | 160 ++++++++++++++++++
v2v/convert_linux_grub.mli | 35 ++++
v2v/convert_windows.ml | 22 +++
v2v/convert_windows.mli | 19 +++
v2v/source_libvirt.ml | 118 ++++++++++++++
v2v/source_libvirt.mli | 27 +++
v2v/target_local.ml | 86 ++++++++++
v2v/target_local.mli | 21 +++
v2v/types.ml | 84 ++++++++++
v2v/types.mli | 77 +++++++++
v2v/utils-c.c | 43 +++++
v2v/utils.ml | 44 +++++
v2v/v2v.ml | 344 +++++++++++++++++++++++++++++++++++++++
v2v/virt-v2v.pod | 301 ++++++++++++++++++++++++++++++++++
v2v/xml-c.c | 240 +++++++++++++++++++++++++++
v2v/xml.ml | 50 ++++++
v2v/xml.mli | 57 +++++++
31 files changed, 2525 insertions(+), 3 deletions(-)
create mode 100644 v2v/Makefile.am
create mode 100644 v2v/README
create mode 100644 v2v/cmdline.ml
create mode 100644 v2v/convert_linux_common.ml
create mode 100644 v2v/convert_linux_common.mli
create mode 100644 v2v/convert_linux_enterprise.ml
create mode 100644 v2v/convert_linux_enterprise.mli
create mode 100644 v2v/convert_linux_grub.ml
create mode 100644 v2v/convert_linux_grub.mli
create mode 100644 v2v/convert_windows.ml
create mode 100644 v2v/convert_windows.mli
create mode 100644 v2v/source_libvirt.ml
create mode 100644 v2v/source_libvirt.mli
create mode 100644 v2v/target_local.ml
create mode 100644 v2v/target_local.mli
create mode 100644 v2v/types.ml
create mode 100644 v2v/types.mli
create mode 100644 v2v/utils-c.c
create mode 100644 v2v/utils.ml
create mode 100644 v2v/v2v.ml
create mode 100644 v2v/virt-v2v.pod
create mode 100644 v2v/xml-c.c
create mode 100644 v2v/xml.ml
create mode 100644 v2v/xml.mli
diff --git a/.gitignore b/.gitignore
index dc8aaf8..9032597 100644
--- a/.gitignore
+++ b/.gitignore
@@ -256,6 +256,7 @@ Makefile.in
/html/virt-tar.1.html
/html/virt-tar-in.1.html
/html/virt-tar-out.1.html
+/html/virt-v2v.1.html
/html/virt-win-reg.1.html
/inspector/actual-*.xml
/inspector/stamp-virt-inspector.pod
@@ -526,3 +527,7 @@ Makefile.in
/test-tool/libguestfs-test-tool-helper
/test-tool/stamp-libguestfs-test-tool.pod
/tools/virt-*.1
+/v2v/.depend
+/v2v/stamp-virt-v2v.pod
+/v2v/virt-v2v
+/v2v/virt-v2v.1
diff --git a/Makefile.am b/Makefile.am
index b135d65..3102e0b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,7 +132,8 @@ SUBDIRS += \
builder builder/website \
resize \
sparsify \
- sysprep
+ sysprep \
+ v2v
endif
# Perl tools.
@@ -257,6 +258,7 @@ HTMLFILES = \
html/virt-tar.1.html \
html/virt-tar-in.1.html \
html/virt-tar-out.1.html \
+ html/virt-v2v.1.html \
html/virt-win-reg.1.html
HTMLSUPPORTFILES = \
@@ -319,7 +321,7 @@ all-local:
grep -v -E '^python/utils.c$$' | \
LC_ALL=C sort > po/POTFILES
cd $(srcdir); \
- find builder customize mllib resize sparsify sysprep -name '*.ml' | \
+ find builder customize mllib resize sparsify sysprep v2v -name '*.ml' | \
LC_ALL=C sort > po/POTFILES-ml
# Manual pages in top level directory.
diff --git a/configure.ac b/configure.ac
index 8abdc90..060e954 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1710,7 +1710,8 @@ AC_CONFIG_FILES([Makefile
tests/tmpdirs/Makefile
tests/xfs/Makefile
tests/xml/Makefile
- tools/Makefile])
+ tools/Makefile
+ v2v/Makefile])
AC_OUTPUT
dnl Produce summary.
diff --git a/fish/guestfish.pod b/fish/guestfish.pod
index 25279fb..5cf6ebc 100644
--- a/fish/guestfish.pod
+++ b/fish/guestfish.pod
@@ -1624,6 +1624,7 @@ L<virt-sysprep(1)>,
L<virt-tar(1)>,
L<virt-tar-in(1)>,
L<virt-tar-out(1)>,
+L<virt-v2v(1)>,
L<virt-win-reg(1)>,
L<libguestfs-tools.conf(5)>,
L<display(1)>,
diff --git a/po/POTFILES b/po/POTFILES
index 0fac8fe..b481157 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -318,3 +318,5 @@ src/test-utils.c
src/tmpdirs.c
src/utils.c
test-tool/test-tool.c
+v2v/utils-c.c
+v2v/xml-c.c
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 4dce0e5..b48a9de 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -80,3 +80,14 @@ sysprep/sysprep_operation_udev_persistent_net.ml
sysprep/sysprep_operation_user_account.ml
sysprep/sysprep_operation_utmp.ml
sysprep/sysprep_operation_yum_uuid.ml
+v2v/cmdline.ml
+v2v/convert_linux_common.ml
+v2v/convert_linux_enterprise.ml
+v2v/convert_linux_grub.ml
+v2v/convert_windows.ml
+v2v/source_libvirt.ml
+v2v/target_local.ml
+v2v/types.ml
+v2v/utils.ml
+v2v/v2v.ml
+v2v/xml.ml
diff --git a/src/guestfs.pod b/src/guestfs.pod
index 0f54625..f634442 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -4396,6 +4396,10 @@ created by another.
Command line tools written in Perl (L<virt-win-reg(1)> and many others).
+=item C<v2v>
+
+L<virt-v2v(1)> command and documentation.
+
=item C<csharp>
=item C<erlang>
@@ -4749,6 +4753,7 @@ L<virt-sysprep(1)>,
L<virt-tar(1)>,
L<virt-tar-in(1)>,
L<virt-tar-out(1)>,
+L<virt-v2v(1)>,
L<virt-win-reg(1)>,
L<guestfs-faq(1)>,
L<guestfs-performance(1)>,
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
new file mode 100644
index 0000000..707b15e
--- /dev/null
+++ b/v2v/Makefile.am
@@ -0,0 +1,185 @@
+# libguestfs virt-v2v tool
+# 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.
+
+include $(top_srcdir)/subdir-rules.mk
+
+EXTRA_DIST = \
+ $(SOURCES) \
+ virt-v2v.pod
+
+CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-v2v
+
+# Alphabetical order.
+SOURCES = \
+ cmdline.ml \
+ convert_linux_common.ml \
+ convert_linux_common.mli \
+ convert_linux_enterprise.ml \
+ convert_linux_enterprise.mli \
+ convert_linux_grub.ml \
+ convert_linux_grub.mli \
+ convert_windows.ml \
+ convert_windows.mli \
+ source_libvirt.ml \
+ source_libvirt.mli \
+ target_local.ml \
+ target_local.mli \
+ types.ml \
+ types.mli \
+ utils.ml \
+ utils-c.c \
+ v2v.ml \
+ xml.ml \
+ xml.mli \
+ xml-c.c
+
+if HAVE_OCAML
+
+# Note this list must be in dependency order.
+deps = \
+ $(top_builddir)/fish/guestfish-progress.o \
+ $(top_builddir)/mllib/tty-c.o \
+ $(top_builddir)/mllib/progress-c.o \
+ $(top_builddir)/mllib/common_gettext.cmx \
+ $(top_builddir)/mllib/common_utils.cmx \
+ $(top_builddir)/mllib/tTY.cmx \
+ $(top_builddir)/mllib/progress.cmx \
+ $(top_builddir)/mllib/config.cmx \
+ types.cmx \
+ utils-c.o \
+ utils.cmx \
+ xml-c.o \
+ xml.cmx \
+ source_libvirt.cmx \
+ convert_linux_common.cmx \
+ convert_linux_grub.cmx \
+ convert_linux_enterprise.cmx \
+ convert_windows.cmx \
+ target_local.cmx \
+ cmdline.cmx \
+ v2v.cmx
+
+if HAVE_OCAMLOPT
+OBJECTS = $(deps)
+else
+OBJECTS = $(patsubst %.cmx,%.cmo,$(deps))
+endif
+
+bin_SCRIPTS = virt-v2v
+
+# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
+# option to be passed to gcc, so we don't try linking against an
+# installed copy of libguestfs.
+OCAMLPACKAGES = \
+ -package str,unix \
+ -I $(top_builddir)/src/.libs \
+ -I ../gnulib/lib/.libs \
+ -I $(top_builddir)/ocaml \
+ -I $(top_builddir)/mllib
+if HAVE_OCAML_PKG_GETTEXT
+OCAMLPACKAGES += -package gettext-stub
+endif
+
+OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES)
+OCAMLOPTFLAGS = $(OCAMLCFLAGS)
+
+if HAVE_OCAMLOPT
+virt-v2v: $(OBJECTS)
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
+ mlguestfs.cmxa -linkpkg $^ \
+ -cclib '-lutils -lncurses $(LIBXML2_LIBS) -lgnu' \
+ $(OCAML_GCOV_LDFLAGS) \
+ -o $@
+else
+virt-v2v: $(OBJECTS)
+ $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
+ mlguestfs.cma -linkpkg $^ \
+ -cclib '-lutils -lncurses $(LIBXML2_LIBS) -lgnu' \
+ -custom \
+ $(OCAML_GCOV_LDFLAGS) \
+ -o $@
+endif
+
+.mli.cmi:
+ $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+.ml.cmo:
+ $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+.ml.cmx:
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+
+# automake will decide we don't need C support in this file. Really
+# we do, so we have to provide it ourselves.
+
+DEFAULT_INCLUDES = \
+ -I. \
+ -I$(top_builddir) \
+ -I$(shell $(OCAMLC) -where) \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/fish \
+ $(LIBXML2_CFLAGS)
+
+.c.o:
+ $(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+
+# Manual pages and HTML files for the website.
+
+man_MANS = virt-v2v.1
+
+noinst_DATA = $(top_builddir)/html/virt-v2v.1.html
+
+virt-v2v.1 $(top_builddir)/html/virt-v2v.1.html: stamp-virt-v2v.pod
+
+stamp-virt-v2v.pod: virt-v2v.pod
+ $(PODWRAPPER) \
+ --man virt-v2v.1 \
+ --html $(top_builddir)/html/virt-v2v.1.html \
+ --license GPLv2+ \
+ $<
+ touch $@
+
+CLEANFILES += stamp-virt-v2v.pod
+
+# Tests.
+
+TESTS_ENVIRONMENT = $(top_builddir)/run --test
+
+if ENABLE_APPLIANCE
+TESTS =
+endif ENABLE_APPLIANCE
+
+check-valgrind:
+ $(MAKE) VG="$(top_builddir)/run @VG@" check
+
+# Dependencies.
+depend: .depend
+
+.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml)
+ rm -f $@ $@-t
+ $(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib $^ | \
+ $(SED) 's/ *$$//' | \
+ $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
+ $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \
+ sort > $@-t
+ mv $@-t $@
+
+-include .depend
+
+endif
+
+DISTCLEANFILES = .depend
+
+.PHONY: depend docs
diff --git a/v2v/README b/v2v/README
new file mode 100644
index 0000000..259b211
--- /dev/null
+++ b/v2v/README
@@ -0,0 +1,15 @@
+Notes on the support matrix for upstream virt-v2v:
+
+All these in 32- and 64-bit variants.
+
+All these as Xen HV and PV variants, and ESX guests.
+
+RHEL 3, 4, 5, 6, 7.
+RHEL 4.5, 4.8, 5.2, 5.4 - tested particularly because virtio was added
+ between these releases.
+
+Windows XP, 2000, 2003, 2008.
+
+SUSE: To do.
+
+VirtualBox: Not tested.
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
new file mode 100644
index 0000000..966fe42
--- /dev/null
+++ b/v2v/cmdline.ml
@@ -0,0 +1,197 @@
+(* 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.
+ *)
+
+(* Command line argument parsing. *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+let parse_cmdline () =
+ let display_version () =
+ printf "virt-v2v %s\n" Config.package_version;
+ exit 0
+ in
+
+ let debug_gc = ref false in
+ let input_conn = ref "" in
+ let output_conn = ref "" in
+ let output_format = ref "" in
+ let output_name = ref "" in
+ let output_storage = ref "" in
+ let machine_readable = ref false in
+ let quiet = ref false in
+ let verbose = ref false in
+ let trace = ref false in
+
+ let input_mode = ref `Libvirt in
+ let set_input_mode = function
+ | "libvirt" -> input_mode := `Libvirt
+ | "libvirtxml" -> input_mode := `LibvirtXML
+ | s ->
+ error (f_"unknown -i option: %s") s
+ in
+
+ let output_mode = ref `Libvirt in
+ let set_output_mode = function
+ | "libvirt" -> output_mode := `Libvirt
+ | "local" -> output_mode := `Local
+ | "ovirt" | "rhev" -> output_mode := `RHEV
+ | s ->
+ error (f_"unknown -o option: %s") s
+ in
+
+ let output_alloc = ref `Sparse in
+ let set_output_alloc = function
+ | "sparse" -> output_alloc := `Sparse
+ | "preallocated" -> output_alloc := `Preallocated
+ | s ->
+ error (f_"unknown -oa option: %s") s
+ in
+
+ let root_choice = ref `Ask in
+ let set_root_choice = function
+ | "ask" -> root_choice := `Ask
+ | "single" -> root_choice := `Single
+ | "first" -> root_choice := `First
+ | dev when string_prefix dev "/dev/" -> root_choice := `Dev dev
+ | s ->
+ error (f_"unknown --root option: %s") s
+ in
+
+ let ditto = " -\"-" in
+ let argspec = Arg.align [
+ "--debug-gc",Arg.Set debug_gc, " " ^ s_"Debug GC and memory allocations";
+ "-i", Arg.String set_input_mode, "libvirtxml|libvirt " ^ s_"Set input mode (default: libvirt)";
+ "-ic", Arg.Set_string input_conn, "uri " ^ s_"Libvirt URI";
+ "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
+ "--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable";
+ "-o", Arg.String set_output_mode, "libvirt|local|rhev " ^ s_"Set output mode (default: libvirt)";
+ "-oa", Arg.String set_output_alloc, "sparse|preallocated " ^ s_"Set output allocation mode";
+ "-oc", Arg.Set_string output_conn, "uri " ^ s_"Libvirt URI";
+ "-of", Arg.Set_string output_format, "raw|qcow2 " ^ s_"Set output format";
+ "-on", Arg.Set_string output_name, "name " ^ s_"Rename guest when converting";
+ "-os", Arg.Set_string output_storage, "storage " ^ s_"Set output storage location";
+ "-q", Arg.Set quiet, " " ^ s_"Quiet output";
+ "--quiet", Arg.Set quiet, ditto;
+ "--root", Arg.String set_root_choice,"ask|... " ^ s_"How to choose root filesystem";
+ "-v", Arg.Set verbose, " " ^ s_"Enable debugging messages";
+ "--verbose", Arg.Set verbose, ditto;
+ "-V", Arg.Unit display_version, " " ^ s_"Display version and exit";
+ "--version", Arg.Unit display_version, ditto;
+ "-x", Arg.Set trace, " " ^ s_"Enable tracing of libguestfs calls";
+ ] in
+ long_options := argspec;
+ let args = ref [] in
+ let anon_fun s = args := s :: !args in
+ let usage_msg =
+ sprintf (f_"\
+%s: convert a guest to use KVM
+
+ virt-v2v -ic esx://esx.example.com/ -os imported esx_guest
+
+ virt-v2v -ic esx://esx.example.com/ \
+ -o rhev -os rhev.nfs:/export_domain --network rhevm esx_guest
+
+ virt-v2v -i libvirtxml -o local -os /tmp guest-domain.xml
+
+There is a companion front-end called \"virt-p2v\" which comes as an
+ISO or CD image that can be booted on physical machines.
+
+A short summary of the options is given below. For detailed help please
+read the man page virt-v2v(1).
+")
+ prog in
+ Arg.parse argspec anon_fun usage_msg;
+
+ (* Dereference the arguments. *)
+ let args = List.rev !args in
+ let debug_gc = !debug_gc in
+ let input_conn = match !input_conn with "" -> None | s -> Some s in
+ let input_mode = !input_mode in
+ let machine_readable = !machine_readable in
+ let output_alloc = !output_alloc in
+ let output_conn = match !output_conn with "" -> None | s -> Some s in
+ let output_format = match !output_format with "" -> None | s -> Some s in
+ let output_mode = !output_mode in
+ let output_name = match !output_name with "" -> None | s -> Some s in
+ let output_storage = !output_storage in
+ let quiet = !quiet in
+ let root_choice = !root_choice in
+ let verbose = !verbose in
+ let trace = !trace in
+
+ (* No arguments and machine-readable mode? Print out some facts
+ * about what this binary supports.
+ *)
+ if args = [] && machine_readable then (
+ printf "virt-v2v\n";
+ printf "libguestfs-rewrite\n";
+ exit 0
+ );
+
+ (* Parsing of the argument(s) depends on the input mode. *)
+ let input =
+ match input_mode with
+ | `Libvirt ->
+ (* -i libvirt: Expecting a single argument which is the name
+ * of the libvirt guest.
+ *)
+ let guest =
+ match args with
+ | [guest] -> guest
+ | _ ->
+ error (f_"expecting a libvirt guest name on the command line") in
+ InputLibvirt (input_conn, guest)
+ | `LibvirtXML ->
+ (* -i libvirtxml: Expecting a filename (XML file). *)
+ let filename =
+ match args with
+ | [filename] -> filename
+ | _ ->
+ error (f_"expecting a libvirt XML file name on the command line") in
+ InputLibvirtXML filename in
+
+ (* Parse the output mode. *)
+ let output =
+ match output_mode with
+ | `Libvirt ->
+ if output_storage <> "" then
+ error (f_"-o libvirt: do not use the -os option");
+ OutputLibvirt output_conn
+ | `Local ->
+ if output_storage = "" then
+ error (f_"-o local: output directory was not specified, use '-os /dir'");
+ let dir_exists =
+ try Sys.is_directory output_storage with Sys_error _ -> false in
+ if not dir_exists then
+ error (f_"-os %s: output directory does not exist or is not a directory")
+ output_storage;
+ OutputLocal output_storage
+ | `RHEV ->
+ if output_storage = "" then
+ error (f_"-o local: output storage was not specified, use '-os'");
+ OutputRHEV output_storage in
+
+ input, output,
+ debug_gc, output_alloc, output_format, output_name,
+ quiet, root_choice, trace, verbose
diff --git a/v2v/convert_linux_common.ml b/v2v/convert_linux_common.ml
new file mode 100644
index 0000000..7c6e811
--- /dev/null
+++ b/v2v/convert_linux_common.ml
@@ -0,0 +1,131 @@
+(* 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.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+module StringMap = Map.Make (String)
+let keys map = StringMap.fold (fun k _ ks -> k :: ks) map []
+
+(* Wrappers around aug_init & aug_load which can dump out full Augeas
+ * parsing problems when debugging is enabled.
+ *)
+let rec augeas_init verbose g =
+ g#aug_init "/" 1;
+ if verbose then augeas_debug_errors g
+
+and augeas_reload verbose g =
+ g#aug_load ();
+ if verbose then augeas_debug_errors g
+
+and augeas_debug_errors g =
+ try
+ let errors = g#aug_match "/augeas/files//error" in
+ let errors = Array.to_list errors in
+ let map =
+ List.fold_left (
+ fun map error ->
+ let detail_paths = g#aug_match (error ^ "//*") in
+ let detail_paths = Array.to_list detail_paths in
+ List.fold_left (
+ fun map path ->
+ (* path is "/augeas/files/<filename>/error/<field>". Put
+ * <filename>, <field> and the value of this Augeas field
+ * into a map.
+ *)
+ let i = string_find path "/error/" in
+ assert (i >= 0);
+ let filename = String.sub path 13 (i-13) in
+ let field = String.sub path (i+7) (String.length path - (i+7)) in
+
+ let detail = g#aug_get path in
+
+ let fmap : string StringMap.t =
+ try StringMap.find filename map
+ with Not_found -> StringMap.empty in
+ let fmap = StringMap.add field detail fmap in
+ StringMap.add filename fmap map
+ ) map detail_paths
+ ) StringMap.empty errors in
+
+ let filenames = keys map in
+ let filenames = List.sort compare filenames in
+
+ List.iter (
+ fun filename ->
+ printf "augeas failed to parse %s:\n" filename;
+ let fmap = StringMap.find filename map in
+ (try
+ let msg = StringMap.find "message" fmap in
+ printf " error \"%s\"" msg
+ with Not_found -> ()
+ );
+ (try
+ let line = StringMap.find "line" fmap
+ and char = StringMap.find "char" fmap in
+ printf " at line %s char %s" line char
+ with Not_found -> ()
+ );
+ (try
+ let lens = StringMap.find "lens" fmap in
+ printf " in lens %s" lens
+ with Not_found -> ()
+ );
+ printf "\n"
+ ) filenames;
+
+ flush stdout
+ with
+ G.Error msg -> eprintf "%s: augeas: %s (ignored)\n" prog msg
+
+let install verbose g inspect packages =
+ assert false
+
+let remove verbose g inspect packages =
+ if packages <> [] then (
+ let root = inspect.i_root in
+ let package_format = g#inspect_get_package_format root in
+ match package_format with
+ | "rpm" ->
+ let cmd = [ "rpm"; "-e" ] @ packages in
+ let cmd = Array.of_list cmd in
+ ignore (g#command cmd);
+
+ (* Reload Augeas in case anything changed. *)
+ augeas_reload verbose g
+
+ | format ->
+ error (f_"don't know how to remove packages using %s: packages: %s")
+ format (String.concat " " packages)
+ )
+
+let file_owned verbose g inspect file =
+ let root = inspect.i_root in
+ let package_format = g#inspect_get_package_format root in
+ match package_format with
+ | "rpm" ->
+ let cmd = [| "rpm"; "-qf"; file |] in
+ (try ignore (g#command cmd); true with G.Error _ -> false)
+
+ | format ->
+ error (f_"don't know how to find package owner using %s") format
diff --git a/v2v/convert_linux_common.mli b/v2v/convert_linux_common.mli
new file mode 100644
index 0000000..5a6a440
--- /dev/null
+++ b/v2v/convert_linux_common.mli
@@ -0,0 +1,35 @@
+(* 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 Linux conversion code. *)
+
+val augeas_init : bool -> Guestfs.guestfs -> unit
+val augeas_reload : bool -> Guestfs.guestfs -> unit
+(** Wrappers around [g#aug_init] and [g#aug_load], which (if verbose)
+ provide additional debugging information about parsing problems
+ that augeas found. *)
+
+val install : bool -> Guestfs.guestfs -> Types.inspect -> string list -> unit
+(** Install package(s) from the list in the guest (or ensure they are
+ installed. *)
+
+val remove : bool -> Guestfs.guestfs -> Types.inspect -> string list -> unit
+(** Uninstall package(s). *)
+
+val file_owned : bool -> Guestfs.guestfs -> Types.inspect -> string -> bool
+(** Returns true if the file is owned by an installed package. *)
diff --git a/v2v/convert_linux_enterprise.ml b/v2v/convert_linux_enterprise.ml
new file mode 100644
index 0000000..8ec3ac3
--- /dev/null
+++ b/v2v/convert_linux_enterprise.ml
@@ -0,0 +1,185 @@
+(* 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.
+ *)
+
+(* Convert various RPM-based Linux enterprise distros. This module
+ * handles:
+ *
+ * - RHEL and derivatives like CentOS and ScientificLinux
+ * - SUSE
+ * - OpenSUSE and Fedora (not enterprisey, but similar enough to RHEL/SUSE)
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Utils
+open Types
+
+let rec convert verbose (g : Guestfs.guestfs) inspect =
+ let root = inspect.i_root in
+ let apps = inspect.i_apps
+ and typ = g#inspect_get_type root
+ and distro = g#inspect_get_distro root in
+
+ let (*is_rhel_family =
+ typ = "linux" &&
+ (distro = "rhel" || distro = "centos"
+ || distro = "scientificlinux" || distro = "redhat-based")
+
+ and*) is_suse_family =
+ typ = "linux" &&
+ (distro = "sles" || distro = "suse-based" || distro = "opensuse") in
+
+ let clean_rpmdb () =
+ (* Clean RPM database. *)
+ assert (g#inspect_get_package_format root = "rpm");
+ let dbfiles = g#glob_expand "/var/lib/rpm/__db.00?" in
+ let dbfiles = Array.to_list dbfiles in
+ List.iter g#rm_f dbfiles
+
+ and autorelabel () =
+ (* Only do autorelabel if load_policy binary exists. Actually
+ * loading the policy is problematic.
+ *)
+ 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 =
+ filter_map (
+ fun { G.app2_name = name } ->
+ if name = "kmod-xenpv" || string_prefix name "kmod-xenpv-" then
+ Some name
+ else
+ None
+ ) apps in
+ Convert_linux_common.remove verbose g inspect xenmods;
+
+ (* Undo related nastiness if kmod-xenpv was installed. *)
+ if xenmods <> [] then (
+ (* kmod-xenpv modules may have been manually copied to other kernels.
+ * Hunt them down and destroy them.
+ *)
+ let dirs = g#find "/lib/modules" in
+ let dirs = Array.to_list dirs in
+ let dirs = List.filter (fun s -> string_find s "/xenpv" >= 0) dirs in
+ let dirs = List.map ((^) "/lib/modules/") dirs in
+ let dirs = List.filter g#is_dir dirs in
+
+ (* Check it's not owned by an installed application. *)
+ let dirs = List.filter (
+ fun d -> not (Convert_linux_common.file_owned verbose g inspect d)
+ ) dirs in
+
+ (* Remove any unowned xenpv directories. *)
+ List.iter g#rm_rf dirs;
+
+ (* rc.local may contain an insmod or modprobe of the xen-vbd driver,
+ * added by an installation script.
+ *)
+ (try
+ let lines = g#read_lines "/etc/rc.local" in
+ let lines = Array.to_list lines in
+ let rex = Str.regexp "\\b\\(insmod|modprobe\\)\b.*\\bxen-vbd" in
+ let lines = List.map (
+ fun s ->
+ if Str.string_match rex s 0 then
+ "#" ^ s
+ else
+ s
+ ) lines in
+ let file = String.concat "\n" lines ^ "\n" in
+ g#write "/etc/rc.local" file
+ with
+ G.Error msg -> eprintf "%s: /etc/rc.local: %s (ignored)\n" prog msg
+ );
+ );
+
+ if is_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
+ let modified = ref false in
+ List.iter (
+ fun var ->
+ List.iter (
+ fun xen_mod ->
+ let expr =
+ sprintf "/file/etc/sysconfig/kernel/%s/value[. = '%s']"
+ var xen_mod in
+ let entries = g#aug_match expr in
+ let entries = Array.to_list entries in
+ if entries <> [] then (
+ List.iter (fun e -> ignore (g#aug_rm e)) entries;
+ modified := true
+ )
+ ) xen_modules
+ ) variables;
+ if !modified then g#aug_save ()
+ );
+
+ and unconfigure_vbox () =
+ ()
+
+ and unconfigure_vmware () =
+ ()
+
+ and unconfigure_citrix () =
+ ()
+
+ in
+
+ clean_rpmdb ();
+ autorelabel ();
+ Convert_linux_common.augeas_init verbose g;
+ let grub = get_grub () in
+ ignore grub (* XXX *);
+ unconfigure_xen ();
+ unconfigure_vbox ();
+ unconfigure_vmware ();
+ unconfigure_citrix ();
+
+
+
+
+
+
+
+ let guestcaps = {
+ gcaps_block_bus = "virtio" (* XXX *);
+ gcaps_net_bus = "virtio" (* XXX *);
+ (* XXX display *)
+ } in
+
+ guestcaps
diff --git a/v2v/convert_linux_enterprise.mli b/v2v/convert_linux_enterprise.mli
new file mode 100644
index 0000000..d1e60fe
--- /dev/null
+++ b/v2v/convert_linux_enterprise.mli
@@ -0,0 +1,19 @@
+(* 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.
+ *)
+
+val convert : bool -> Guestfs.guestfs -> Types.inspect -> Types.guestcaps
diff --git a/v2v/convert_linux_grub.ml b/v2v/convert_linux_grub.ml
new file mode 100644
index 0000000..2de8b5c
--- /dev/null
+++ b/v2v/convert_linux_grub.ml
@@ -0,0 +1,160 @@
+(* 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 Types
+
+type t = {
+ config_file : string; (* grub configuration file *)
+ g : Guestfs.guestfs; (* libguestfs handle *)
+ inspect : inspect; (* inspection data *)
+
+ (* Variant stuff for each version of grub. *)
+ grub : grub_variant;
+}
+and grub_variant = Grub1 of grub1_data | Grub2
+and grub1_data = {
+ grub_fs : string; (* grub filesystem prefix *)
+}
+
+(* 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;
+ Convert_linux_common.augeas_reload verbose g;
+ ) in
+
+ { config_file = config_file; g = g; inspect = inspect;
+ grub = Grub1 { grub_fs = 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. *)
+ Convert_linux_common.augeas_reload verbose g;
+
+ ignore (g#command [| "grub-install"; dev |])
+
+and 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 -> ()
+ );
+
+ { config_file = config_file; g = g; inspect = inspect;
+ grub = Grub2 }
+
+(* 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.
+ *)
+ Convert_linux_common.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" |])
+
+and 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
diff --git a/v2v/convert_linux_grub.mli b/v2v/convert_linux_grub.mli
new file mode 100644
index 0000000..54f8304
--- /dev/null
+++ b/v2v/convert_linux_grub.mli
@@ -0,0 +1,35 @@
+(* 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. *)
+
+type t
+
+val grub1 : bool -> Guestfs.guestfs -> Types.inspect -> t
+(** 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 -> t
+(** 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/convert_windows.ml b/v2v/convert_windows.ml
new file mode 100644
index 0000000..e5d1ea8
--- /dev/null
+++ b/v2v/convert_windows.ml
@@ -0,0 +1,22 @@
+(* 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.
+ *)
+
+(* Convert Windows guests. *)
+
+let convert verbose g inspect =
+ assert false
diff --git a/v2v/convert_windows.mli b/v2v/convert_windows.mli
new file mode 100644
index 0000000..d1e60fe
--- /dev/null
+++ b/v2v/convert_windows.mli
@@ -0,0 +1,19 @@
+(* 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.
+ *)
+
+val convert : bool -> Guestfs.guestfs -> Types.inspect -> Types.guestcaps
diff --git a/v2v/source_libvirt.ml b/v2v/source_libvirt.ml
new file mode 100644
index 0000000..bdea8d4
--- /dev/null
+++ b/v2v/source_libvirt.ml
@@ -0,0 +1,118 @@
+(* 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.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+let create_xml xml =
+ let doc = Xml.parse_memory xml in
+ let xpathctx = Xml.xpath_new_context doc in
+
+ let xpath_to_string expr default =
+ let obj = Xml.xpath_eval_expression xpathctx expr in
+ if Xml.xpathobj_nr_nodes obj < 1 then default
+ else (
+ let node = Xml.xpathobj_node doc obj 0 in
+ Xml.node_as_string node
+ ) in
+ let xpath_to_int expr default =
+ let obj = Xml.xpath_eval_expression xpathctx expr in
+ if Xml.xpathobj_nr_nodes obj < 1 then default
+ else (
+ let node = Xml.xpathobj_node doc obj 0 in
+ let str = Xml.node_as_string node in
+ try int_of_string str
+ with Failure "int_of_string" ->
+ error (f_"expecting XML expression to return an integer (expression: %s)")
+ expr
+ ) in
+
+ let dom_type = xpath_to_string "/domain/@type" "" in
+ let name = xpath_to_string "/domain/name/text()" "" in
+ let memory = xpath_to_int "/domain/memory/text()" 0 in
+ let memory = Int64.of_int memory *^ 1024L in
+ let vcpu = xpath_to_int "/domain/vcpu/text()" 0 in
+ let arch = xpath_to_string "/domain/os/type/@arch" "" in
+
+ let features =
+ let features = ref [] in
+ let obj = Xml.xpath_eval_expression xpathctx "/domain/features/*" in
+ let nr_nodes = Xml.xpathobj_nr_nodes obj in
+ for i = 0 to nr_nodes-1 do
+ let node = Xml.xpathobj_node doc obj i in
+ features := Xml.node_name node :: !features
+ done;
+ !features in
+
+ (* Non-removable disk devices. *)
+ let disks =
+ let disks = ref [] in
+ let obj =
+ Xml.xpath_eval_expression xpathctx
+ "/domain/devices/disk[@device='disk']" in
+ let nr_nodes = Xml.xpathobj_nr_nodes obj in
+ if nr_nodes < 1 then
+ error (f_"this guest has no non-removable disks");
+ for i = 0 to nr_nodes-1 do
+ let node = Xml.xpathobj_node doc obj i in
+ Xml.xpathctx_set_current_context xpathctx node;
+ let path = xpath_to_string "source/@file | source/@dev" "" in
+ if path <> "" then (
+ let format =
+ let format = xpath_to_string "driver/@type" "" in
+ if format <> "" then Some format else None in
+ disks := (path, format) :: !disks
+ )
+ done;
+ List.rev !disks in
+
+ (* XXX Much more metadata needs to be collected here:
+ * - graphics
+ * - cdroms
+ * - floppies
+ * - network interfaces
+ * See: lib/Sys/VirtConvert/Connection/LibVirt.pm
+ *)
+
+ {
+ s_dom_type = dom_type;
+ s_name = name;
+ s_memory = memory;
+ s_vcpu = vcpu;
+ s_arch = arch;
+ s_features = features;
+ s_disks = disks;
+ }
+
+let create_from_xml file =
+ let xml = read_whole_file file in
+ create_xml xml
+
+let create libvirt_uri guest =
+ let cmd =
+ match libvirt_uri with
+ | None -> sprintf "virsh dumpxml %s" (quote guest)
+ | Some uri -> sprintf "virsh -c %s dumpxml %s" (quote uri) (quote guest) in
+ let lines = external_command ~prog cmd in
+ let xml = String.concat "\n" lines in
+ create_xml xml
diff --git a/v2v/source_libvirt.mli b/v2v/source_libvirt.mli
new file mode 100644
index 0000000..1e3b1e1
--- /dev/null
+++ b/v2v/source_libvirt.mli
@@ -0,0 +1,27 @@
+(* 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.
+ *)
+
+(** [-i libvirt] and [-i libvirtxml] sources. *)
+
+val create : string option -> string -> Types.source
+(** [create libvirt_uri guest] reads the source metadata from the
+ named libvirt guest. *)
+
+val create_from_xml : string -> Types.source
+(** [create_from_xml filename] reads the source metadata from the
+ libvirt XML file. *)
diff --git a/v2v/target_local.ml b/v2v/target_local.ml
new file mode 100644
index 0000000..ed4e5e3
--- /dev/null
+++ b/v2v/target_local.ml
@@ -0,0 +1,86 @@
+(* 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.
+ *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+open Utils
+
+let initialize dir overlays =
+ List.map (
+ fun ov ->
+ let target_file = dir // "disk-" ^ ov.ov_sd in
+ { ov with ov_target_file = target_file; ov_target_file_tmp = target_file }
+ ) overlays
+
+let create_metadata dir source overlays guestcaps =
+ let name = source.s_name in
+ let file = dir // name ^ ".xml" in
+
+ let chan = open_out file in
+ let p fs = fprintf chan fs in
+
+ p "<domain type='%s'>\n" "kvm"; (* Always assume target is kvm? *)
+ p " <name>%s</name>\n" name;
+ let memory_k = source.s_memory /^ 1024L in
+ p " <memory unit='KiB'>%Ld</memory>\n" memory_k;
+ p " <currentMemory unit='KiB'>%Ld</currentMemory>\n" memory_k;
+ p " <vcpu>%d</vcpu>\n" source.s_vcpu;
+ p " <os>\n";
+ p " <type arch='%s'>hvm</type>\n" source.s_arch;
+ p " </os>\n";
+ p " <features>\n";
+ List.iter (p " <%s/>\n") source.s_features;
+ p " </features>\n";
+
+ p " <on_poweroff>destroy</on_poweroff>\n";
+ p " <on_reboot>restart</on_reboot>\n";
+ p " <on_crash>restart</on_crash>\n";
+ p " <devices>\n";
+
+ let block_prefix =
+ if guestcaps.gcaps_block_bus = "virtio" then "vd" else "hd" in
+ iteri (
+ fun i ov ->
+ p " <disk type='file' device='disk'>\n";
+ p " <driver name='qemu' type='%s' cache='none'/>\n"
+ ov.ov_target_format;
+ p " <source file='%s'/>\n" (xml_quote_attr ov.ov_target_file);
+ p " <target dev='%s%s' bus='%s'/>\n"
+ block_prefix (drive_name i) guestcaps.gcaps_block_bus;
+ p " </disk>\n";
+ ) overlays;
+
+ p " <input type='tablet' bus='usb'/>\n";
+ p " <input type='mouse' bus='ps2'/>\n";
+ p " <console type='pty'/>\n";
+
+ (* XXX Missing here from old virt-v2v:
+ <video/>
+ <graphics/>
+ cdroms and floppies
+ network interfaces
+ See: lib/Sys/VirtConvert/Connection/LibVirtTarget.pm
+ *)
+
+ p "</domain>\n";
+
+ close_out chan
diff --git a/v2v/target_local.mli b/v2v/target_local.mli
new file mode 100644
index 0000000..1833ecb
--- /dev/null
+++ b/v2v/target_local.mli
@@ -0,0 +1,21 @@
+(* 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.
+ *)
+
+val initialize : string -> Types.overlay list -> Types.overlay list
+
+val create_metadata : string -> Types.source -> Types.overlay list -> Types.guestcaps -> unit
diff --git a/v2v/types.ml b/v2v/types.ml
new file mode 100644
index 0000000..0f5ae86
--- /dev/null
+++ b/v2v/types.ml
@@ -0,0 +1,84 @@
+(* 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.
+ *)
+
+open Printf
+
+(* Types. See types.mli for documentation. *)
+
+type input =
+| InputLibvirt of string option * string
+| InputLibvirtXML of string
+
+type output =
+| OutputLibvirt of string option
+| OutputLocal of string
+| OutputRHEV of string
+
+type source = {
+ s_dom_type : string;
+ s_name : string;
+ s_memory : int64;
+ s_vcpu : int;
+ s_arch : string;
+ s_features : string list;
+ s_disks : source_disk list;
+}
+and source_disk = string * string option
+
+type overlay = {
+ ov_overlay : string;
+ ov_target_file : string;
+ ov_target_file_tmp : string;
+ ov_target_format : string;
+ ov_sd : string;
+ ov_virtual_size : int64;
+ ov_preallocation : string option;
+ ov_source_file : string;
+ ov_source_format : string option;
+}
+
+let string_of_overlay ov =
+ sprintf "\
+ov_overlay = %s
+ov_target_file = %s
+ov_target_file_tmp = %s
+ov_target_format = %s
+ov_sd = %s
+ov_virtual_size = %Ld
+ov_preallocation = %s
+ov_source_file = %s
+ov_source_format = %s
+"
+ ov.ov_overlay
+ ov.ov_target_file ov.ov_target_file_tmp
+ ov.ov_target_format
+ ov.ov_sd
+ ov.ov_virtual_size
+ (match ov.ov_preallocation with None -> "None" | Some s -> s)
+ ov.ov_source_file
+ (match ov.ov_source_format with None -> "None" | Some s -> s)
+
+type inspect = {
+ i_root : string;
+ i_apps : Guestfs.application2 list;
+}
+
+type guestcaps = {
+ gcaps_block_bus : string;
+ gcaps_net_bus : string;
+}
diff --git a/v2v/types.mli b/v2v/types.mli
new file mode 100644
index 0000000..e7e72e0
--- /dev/null
+++ b/v2v/types.mli
@@ -0,0 +1,77 @@
+(* 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.
+ *)
+
+(** Types. *)
+
+type input =
+| InputLibvirt of string option * string (* -i libvirt: -ic + guest name *)
+| InputLibvirtXML of string (* -i libvirtxml: XML file name *)
+(** The input arguments as specified on the command line. *)
+
+type output =
+| OutputLibvirt of string option (* -o libvirt: -oc *)
+| OutputLocal of string (* -o local: directory *)
+| OutputRHEV of string (* -o rhev: output storage *)
+(** The output arguments as specified on the command line. *)
+
+type source = {
+ s_dom_type : string; (** Source domain type, eg "kvm" *)
+ s_name : string; (** Guest name. *)
+ s_memory : int64; (** Memory size (bytes). *)
+ s_vcpu : int; (** Number of CPUs. *)
+ s_arch : string; (** Architecture. *)
+ s_features : string list; (** Machine features. *)
+ s_disks : source_disk list; (** Disk images. *)
+}
+(** The source: metadata, disk images. *)
+
+and source_disk = string * string option
+(** A source file is a qemu URI and a format. *)
+
+type overlay = {
+ ov_overlay : string; (** Local overlay file (qcow2 format). *)
+ ov_target_file : string; (** Destination file (real). *)
+ ov_target_file_tmp : string; (** Destination file (temporary). *)
+ ov_target_format : string; (** Destination format (eg. -of option). *)
+ ov_sd : string; (** sdX libguestfs name of disk. *)
+ ov_virtual_size : int64; (** Virtual disk size in bytes. *)
+ ov_preallocation : string option; (** ?preallocation option. *)
+
+ (* Note: the next two fields are for information only and must not
+ * be opened/copied/etc.
+ *)
+ ov_source_file : string; (** qemu URI for source file. *)
+ ov_source_format : string option; (** Source file format, if known. *)
+}
+(** Disk overlays and destination disks. *)
+
+val string_of_overlay : overlay -> string
+
+type inspect = {
+ i_root : string; (** Root device. *)
+ i_apps : Guestfs.application2 list; (** Packages installed. *)
+}
+(** Inspection information. Only the applications list is stored here
+ as that is the only one which is slow/inconvenient to fetch. *)
+
+type guestcaps = {
+ gcaps_block_bus : string; (** "virtio", "ide", possibly others *)
+ gcaps_net_bus : string; (** "virtio", "e1000", possibly others *)
+ (* XXX acpi, display *)
+}
+(** Guest capabilities after conversion. eg. Was virtio found or installed? *)
diff --git a/v2v/utils-c.c b/v2v/utils-c.c
new file mode 100644
index 0000000..f6a5d74
--- /dev/null
+++ b/v2v/utils-c.c
@@ -0,0 +1,43 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <caml/alloc.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+
+value
+v2v_utils_drive_name (value indexv)
+{
+ CAMLparam1 (indexv);
+ CAMLlocal1 (namev);
+ char name[64];
+
+ guestfs___drive_name (Int_val (indexv), name);
+ namev = caml_copy_string (name);
+
+ CAMLreturn (namev);
+}
diff --git a/v2v/utils.ml b/v2v/utils.ml
new file mode 100644
index 0000000..6155f9a
--- /dev/null
+++ b/v2v/utils.ml
@@ -0,0 +1,44 @@
+(* 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.
+ *)
+
+(* Utilities used in virt-v2v only. *)
+
+open Printf
+
+open Common_gettext.Gettext
+open Common_utils
+
+open Types
+
+let prog = Filename.basename Sys.executable_name
+let error ?exit_code fs = error ~prog ?exit_code fs
+
+let quote = Filename.quote
+
+(* Quote XML <element attr='...'> content. Note you must use single
+ * quotes around the attribute.
+ *)
+let xml_quote_attr str =
+ let str = Common_utils.replace_str str "&" "&" in
+ let str = Common_utils.replace_str str "'" "'" in
+ let str = Common_utils.replace_str str "<" "<" in
+ let str = Common_utils.replace_str str ">" ">" in
+ str
+
+external drive_name : int -> string = "v2v_utils_drive_name"
+
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
new file mode 100644
index 0000000..4b62e05
--- /dev/null
+++ b/v2v/v2v.ml
@@ -0,0 +1,344 @@
+(* 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.
+ *)
+
+open Unix
+open Printf
+
+open Common_gettext.Gettext
+
+module G = Guestfs
+
+open Common_utils
+open Types
+open Utils
+
+let () = Random.self_init ()
+
+let rec main () =
+ (* Handle the command line. *)
+ let input, output,
+ debug_gc, output_alloc, output_format, output_name,
+ quiet, root_choice, trace, verbose =
+ Cmdline.parse_cmdline () in
+
+ let msg fs = make_message_function ~quiet fs in
+
+ let source =
+ match input with
+ | InputLibvirt (libvirt_uri, guest) ->
+ Source_libvirt.create libvirt_uri guest
+ | InputLibvirtXML filename ->
+ Source_libvirt.create_from_xml filename in
+
+ (* 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
+ * discarded blocks are stored as zero clusters, this should allow us
+ * to fstrim/blkdiscard and avoid copying significant parts of the
+ * data over the wire.
+ *)
+ msg (f_"Creating an overlay to protect the source from being modified");
+ let overlays =
+ List.map (
+ fun (qemu_uri, format) ->
+ let overlay = Filename.temp_file "v2vovl" ".qcow2" in
+ unlink_on_exit overlay;
+
+ let options =
+ "compat=1.1,lazy_refcounts=on" ^
+ (match format with None -> ""
+ | Some fmt -> ",backing_fmt=" ^ fmt) in
+ let cmd =
+ sprintf "qemu-img create -q -f qcow2 -b %s -o %s %s"
+ (quote qemu_uri) (quote options) overlay in
+ if Sys.command cmd <> 0 then
+ error (f_"qemu-img command failed, see earlier errors");
+ overlay, qemu_uri, format
+ ) source.s_disks in
+
+ (* Open the guestfs handle. *)
+ msg (f_"Opening the overlay");
+ let g = new G.guestfs () in
+ g#set_trace trace;
+ g#set_verbose verbose;
+ List.iter (
+ fun (overlay, _, _) ->
+ g#add_drive_opts overlay
+ ~format:"qcow2" ~cachemode:"unsafe" ~discard:"besteffort"
+ ) overlays;
+
+ g#launch ();
+
+ (* Work out where we will write the final output. Do this early
+ * just so we can display errors to the user before doing too much
+ * work.
+ *)
+ let overlays =
+ initialize_target g output output_alloc output_format overlays in
+
+ (* Inspection - this also mounts up the filesystems. *)
+ msg (f_"Inspecting the overlay");
+ let inspect = inspect_source g root_choice in
+
+ (* Conversion. *)
+ let guestcaps =
+ let root = inspect.i_root in
+
+ (match g#inspect_get_product_name root with
+ | "unknown" ->
+ msg (f_"Converting the guest to run on KVM")
+ | prod ->
+ msg (f_"Converting %s to run on KVM") prod
+ );
+
+ match g#inspect_get_type root with
+ | "linux" ->
+ (match g#inspect_get_distro root with
+ | "fedora"
+ | "rhel" | "centos" | "scientificlinux" | "redhat-based"
+ | "sles" | "suse-based" | "opensuse" ->
+ Convert_linux_enterprise.convert verbose g inspect
+
+ | distro ->
+ error (f_"virt-v2v is unable to convert this guest type (linux/distro=%s)") distro
+ );
+
+ | "windows" -> Convert_windows.convert verbose g inspect
+
+ | typ ->
+ error (f_"virt-v2v is unable to convert this guest type (type=%s)") typ in
+
+ (* Trim the filesystems to reduce transfer size. *)
+ msg (f_"Trimming filesystems to reduce amount of data to copy");
+ let () =
+ let mps = g#mountpoints () in
+ List.iter (
+ fun (_, mp) ->
+ try g#fstrim mp
+ with G.Error msg -> eprintf "%s: %s (ignored)\n" mp msg
+ ) mps in
+
+ msg (f_"Closing the overlay");
+ g#umount_all ();
+ g#shutdown ();
+ g#close ();
+
+ (* Copy the source to the output. *)
+ let delete_target_on_exit = ref true in
+ at_exit (fun () ->
+ if !delete_target_on_exit then (
+ List.iter (
+ fun ov -> try Unix.unlink ov.ov_target_file_tmp with _ -> ()
+ ) overlays
+ )
+ );
+ let nr_overlays = List.length overlays in
+ iteri (
+ 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);
+
+ (* It turns out that libguestfs's disk creation code is
+ * considerably more flexible and easier to use than qemu-img, so
+ * create the disk explicitly using libguestfs then pass the
+ * 'qemu-img convert -n' option so qemu reuses the disk.
+ *)
+ let preallocation = ov.ov_preallocation in
+ let compat =
+ match ov.ov_target_format with "qcow2" -> Some "1.1" | _ -> None in
+ (new G.guestfs ())#disk_create ov.ov_target_file_tmp
+ ov.ov_target_format ov.ov_virtual_size ?preallocation ?compat;
+
+ let cmd =
+ sprintf "qemu-img convert -n -f qcow2 -O %s %s %s"
+ (quote ov.ov_target_format) (quote ov.ov_overlay)
+ (quote ov.ov_target_file_tmp) in
+ if verbose then printf "%s\n%!" cmd;
+ if Sys.command cmd <> 0 then
+ error (f_"qemu-img command failed, see earlier errors");
+ ) overlays;
+
+ (* Create output metadata. *)
+ msg (f_"Creating output metadata");
+ let () =
+ (* Are we going to rename the guest? *)
+ 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.create_metadata dir renamed_source overlays guestcaps
+ | OutputRHEV os -> assert false in
+
+ (* If we wrote to a temporary file, rename to the real file. *)
+ List.iter (
+ fun ov ->
+ if ov.ov_target_file_tmp <> ov.ov_target_file then
+ rename ov.ov_target_file_tmp ov.ov_target_file
+ ) overlays;
+
+ delete_target_on_exit := false;
+
+ msg (f_"Finishing off");
+
+ if debug_gc then
+ Gc.compact ()
+
+and initialize_target g output output_alloc output_format overlays =
+ let overlays =
+ mapi (
+ fun i (overlay, qemu_uri, backing_format) ->
+ (* Grab the virtual size of each disk. *)
+ let sd = "sd" ^ drive_name i in
+ let dev = "/dev/" ^ sd in
+ let vsize = g#blockdev_getsize64 dev in
+
+ (* What output format should we use? *)
+ let format =
+ match output_format, backing_format with
+ | Some format, _ -> format (* -of overrides everything *)
+ | None, Some format -> format (* same as backing format *)
+ | None, None ->
+ error (f_"disk %s (%s) has no defined format, you have to either define the original format in the source metadata, or use the '-of' option to force the output format") sd qemu_uri in
+
+ (* What output preallocation mode should we use? *)
+ let preallocation =
+ match format, output_alloc with
+ | "raw", `Sparse -> Some "sparse"
+ | "raw", `Preallocated -> Some "full"
+ | "qcow2", `Sparse -> Some "off" (* ? *)
+ | "qcow2", `Preallocated -> Some "metadata"
+ | _ -> None (* ignore -oa flag for other formats *) in
+
+ { ov_overlay = overlay;
+ ov_target_file = ""; ov_target_file_tmp = "";
+ ov_target_format = format;
+ ov_sd = sd; ov_virtual_size = vsize; ov_preallocation = preallocation;
+ ov_source_file = qemu_uri; ov_source_format = backing_format; }
+ ) overlays in
+ let overlays =
+ match output with
+ | OutputLibvirt oc -> assert false
+ | OutputLocal dir -> Target_local.initialize dir overlays
+ | OutputRHEV os -> assert false in
+ overlays
+
+and inspect_source g root_choice =
+ let roots = g#inspect_os () in
+ let roots = Array.to_list roots in
+
+ let root =
+ match roots with
+ | [] ->
+ error (f_"no root device found in this operating system image.");
+ | [root] -> root
+ | roots ->
+ match root_choice with
+ | `Ask ->
+ (* List out the roots and ask the user to choose. *)
+ printf "\n***\n";
+ printf (f_"dual- or multi-boot operating system detected. Choose the root filesystem\nthat contains the main operating system from the list below:\n");
+ printf "\n";
+ iteri (
+ fun i root ->
+ let prod = g#inspect_get_product_name root in
+ match prod with
+ | "unknown" -> printf " [%d] %s\n" i root
+ | prod -> printf " [%d] %s (%s)\n" i root prod
+ ) roots;
+ printf "\n";
+ let i = ref 0 in
+ let n = List.length roots in
+ while !i < 1 || !i > n do
+ printf (f_"Enter number between 1 and %d: ") n;
+ (try i := int_of_string (read_line ())
+ with
+ | End_of_file -> error (f_"connection closed")
+ | Failure "int_of_string" -> ()
+ )
+ done;
+ List.nth roots (!i - 1)
+
+ | `Single ->
+ error (f_"multi-boot operating systems are not supported by virt-v2v. Use the --root option to change how virt-v2v handles this.")
+
+ | `First ->
+ List.hd roots
+
+ | `Dev dev ->
+ if List.mem dev roots then dev
+ else
+ error (f_"root device %s not found. Roots found were: %s")
+ dev (String.concat " " roots) in
+
+ (* Reject this OS if it doesn't look like an installed image. *)
+ let () =
+ let fmt = g#inspect_get_format root in
+ if fmt <> "installed" then
+ error (f_"libguestfs thinks this is not an installed operating system (it might be, for example, an installer disk or live CD). If this is wrong, it is probably a bug in libguestfs. root=%s fmt=%s") root fmt in
+
+ (* Mount up the filesystems. *)
+ let mps = g#inspect_get_mountpoints root in
+ let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
+ let mps = List.sort cmp mps in
+ List.iter (
+ fun (mp, dev) ->
+ try g#mount dev mp
+ with G.Error msg -> eprintf "%s (ignored)\n" msg
+ ) mps;
+
+ (* Get list of applications/packages installed. *)
+ let apps = g#inspect_list_applications2 root in
+ let apps = Array.to_list apps in
+
+ { i_root = root; i_apps = apps; }
+
+let () =
+ try main ()
+ with
+ | Unix.Unix_error (code, fname, "") -> (* from a syscall *)
+ eprintf (f_"%s: error: %s: %s\n") prog fname (Unix.error_message code);
+ exit 1
+ | Unix.Unix_error (code, fname, param) -> (* from a syscall *)
+ eprintf (f_"%s: error: %s: %s: %s\n") prog fname (Unix.error_message code)
+ param;
+ exit 1
+ | Sys_error msg -> (* from a syscall *)
+ eprintf (f_"%s: error: %s\n") prog msg;
+ exit 1
+ | G.Error msg -> (* from libguestfs *)
+ eprintf (f_"%s: libguestfs error: %s\n") prog msg;
+ exit 1
+ | Failure msg -> (* from failwith/failwithf *)
+ eprintf (f_"%s: failure: %s\n") prog msg;
+ exit 1
+ | Invalid_argument msg -> (* probably should never happen *)
+ eprintf (f_"%s: internal error: invalid argument: %s\n") prog msg;
+ exit 1
+ | Assert_failure (file, line, char) -> (* should never happen *)
+ eprintf (f_"%s: internal error: assertion failed at %s, line %d, char %d\n") prog file line char;
+ exit 1
+ | Not_found -> (* should never happen *)
+ eprintf (f_"%s: internal error: Not_found exception was thrown\n") prog;
+ exit 1
+ | exn -> (* something not matched above *)
+ eprintf (f_"%s: exception: %s\n") prog (Printexc.to_string exn);
+ exit 1
diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
new file mode 100644
index 0000000..138e73b
--- /dev/null
+++ b/v2v/virt-v2v.pod
@@ -0,0 +1,301 @@
+=head1 NAME
+
+virt-v2v - Convert a guest to use KVM
+
+=head1 SYNOPSIS
+
+ virt-v2v -ic esx://esx.example.com/ -os imported esx_guest
+
+ virt-v2v -ic esx://esx.example.com/ \
+ -o rhev -os rhev.nfs:/export_domain --network rhevm esx_guest
+
+ virt-v2v -i libvirtxml -o local -os /tmp guest-domain.xml
+
+=head1 DESCRIPTION
+
+Virt-v2v converts guests from a foreign hypervisor to run on KVM,
+managed by libvirt or Red Hat Enterprise Virtualisation (RHEV) version
+2.2 or later. It can currently convert Red Hat Enterprise Linux and
+Windows guests running on Xen and VMware ESX.
+
+There is also a companion front-end called "virt-p2v" which comes as an
+ISO or CD image that can be booted on physical machines.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Display help.
+
+=item B<--debug-gc>
+
+Debug garbage collection and memory allocation. This is only useful
+when debugging memory problems in virt-v2v or the OCaml libguestfs
+bindings.
+
+=item B<-i libvirt>
+
+Set the input method to I<libvirt>. This is the default.
+
+In this mode you have to specify a libvirt guest name on the command
+line. You may also specify a libvirt connection URI (see I<-ic>).
+
+=item B<-i libvirtxml>
+
+Set the input method to I<libvirtxml>.
+
+In this mode you have to pass a libvirt XML file on the command line.
+This file is read in order to get metadata about the source guest
+(such as its name, amount of memory), and also to locate the input
+disks.
+
+=item B<-ic> libvirtURI
+
+Specify a libvirt connection URI to use when reading the guest. This
+is only used when S<I<-i libvirt>>.
+
+Only local libvirt connections and ESX connections can be used.
+Remote libvirt connections will not work in general.
+
+=item B<--machine-readable>
+
+This option is used to make the output more machine friendly
+when being parsed by other programs. See
+L</MACHINE READABLE OUTPUT> below.
+
+=item B<-o libvirt>
+
+Set the output method to I<libvirt>. This is the default.
+
+In this mode, the converted guest is created as a libvirt guest. You
+may also specify a libvirt connection URI (see I<-oc>).
+
+=item B<-o local>
+
+Set the output method to I<local>.
+
+In this mode, the converted guest is written to a local directory
+specified by I<-os /dir> (the directory must exist). The converted
+guest's disks are written as:
+
+ /dir/disk-sda
+ /dir/disk-sdb
+ [etc]
+
+and a libvirt XML file is created containing guest metadata
+(C</dir/name.xml>, where C<name> is the guest name).
+
+=item B<-o rhev>
+
+Set the output method to I<rhev>.
+
+The converted guest is written to a RHEV Export Storage Domain. The
+I<-os> parameter must also be used to specify the location of the
+Export Storage Domain. Note this does not actually import the guest
+into RHEV. You have to do that manually later using the UI.
+
+=item B<-oa sparse>
+
+=item B<-oa preallocated>
+
+Set the output file allocation mode. The default is C<sparse>.
+
+=item B<-oc> libvirtURI
+
+Specify a libvirt connection to use when writing the converted guest.
+This is only used when S<I<-o libvirt>>.
+
+Only local libvirt connections can be used. Remote libvirt
+connections will not work.
+
+=item B<-of> format
+
+When converting the guest, convert the disks to the given format.
+
+If not specified, then the input format is used.
+
+=item B<-on> name
+
+Rename the guest when converting it. If this option is not used then
+the output name is the same as the input name.
+
+=item B<-os> storage
+
+The location of the storage for the converted guest.
+
+For I<-o libvirt>, this is a libvirt pool (see S<C<virsh pool-list>>).
+
+For I<-o local>, this is a directory name. The directory must exist.
+
+For I<-o rhev>, this is an NFS path of the form
+C<E<lt>hostE<gt>:E<lt>pathE<gt>>, eg:
+
+ rhev-storage.example.com:/rhev/export
+
+The NFS export must be mountable and writable by the user and host
+running virt-v2v, since the virt-v2v program has to actually mount it
+when it runs.
+
+=item B<-q>
+
+=item B<--quiet>
+
+This disables progress bars and other unnecessary output.
+
+=item B<--root ask>
+
+=item B<--root single>
+
+=item B<--root first>
+
+=item B<--root> /dev/sdX
+
+=item B<--root> /dev/VG/LV
+
+Choose the root filesystem to be converted.
+
+In the case where the virtual machine is dual-boot or multi-boot, or
+where the VM has other filesystems that look like operating systems,
+this option can be used to select the root filesystem (a.k.a. C<C:>
+drive or C</>) of the operating system that is to be converted. The
+Windows Recovery Console, certain attached DVD drives, and bugs in
+libguestfs inspection heuristics, can make a guest look like a
+multi-boot operating system.
+
+The default in virt-v2v E<le> 0.7.1 was S<I<--root single>>, which
+causes virt-v2v to die if a multi-boot operating system is found.
+
+Since virt-v2v E<ge> 0.7.2 the default is now S<I<--root ask>>: If the
+VM is found to be multi-boot, then virt-v2v will stop and list the
+possible root filesystems and ask the user which to use. This
+requires that virt-v2v is run interactively.
+
+S<I<--root first>> means to choose the first root device in the case
+of a multi-boot operating system. Since this is a heuristic, it may
+sometimes choose the wrong one.
+
+You can also name a specific root device, eg. S<I<--root /dev/sda2>>
+would mean to use the second partition on the first hard drive. If
+the named root device does not exist or was not detected as a root
+device, then virt-v2v will fail.
+
+Note that there is a bug in grub which prevents it from successfully
+booting a multiboot system if VirtIO is enabled. Grub is only able to
+boot an operating system from the first VirtIO disk. Specifically,
+C</boot> must be on the first VirtIO disk, and it cannot chainload an
+OS which is not in the first VirtIO disk.
+
+=item B<-v>
+
+=item B<--verbose>
+
+Enable verbose messages for debugging.
+
+=item B<-V>
+
+=item B<--version>
+
+Display version number and exit.
+
+=item B<-x>
+
+Enable tracing of libguestfs API calls.
+
+=back
+
+=head1 MACHINE READABLE OUTPUT
+
+The I<--machine-readable> option can be used to make the output more
+machine friendly, which is useful when calling virt-v2v from
+other programs, GUIs etc.
+
+There are two ways to use this option.
+
+Firstly use the option on its own to query the capabilities of the
+virt-v2v binary. Typical output looks like this:
+
+ $ virt-v2v --machine-readable
+ virt-v2v
+ libguestfs-rewrite
+
+A list of features is printed, one per line, and the program exits
+with status 0.
+
+Secondly use the option in conjunction with other options to make the
+regular program output more machine friendly.
+
+At the moment this means:
+
+=over 4
+
+=item 1.
+
+Progress bar messages can be parsed from stdout by looking for this
+regular expression:
+
+ ^[0-9]+/[0-9]+$
+
+=item 2.
+
+The calling program should treat messages sent to stdout (except for
+progress bar messages) as status messages. They can be logged and/or
+displayed to the user.
+
+=item 3.
+
+The calling program should treat messages sent to stderr as error
+messages. In addition, virt-v2v exits with a non-zero status
+code if there was a fatal error.
+
+=back
+
+Virt-v2v E<le> 0.9.1 did not support the I<--machine-readable>
+option at all. The option was added when virt-v2v was rewritten in 2014.
+
+=head1 ENVIRONMENT VARIABLES
+
+=over 4
+
+=item TMPDIR
+
+Location of the temporary directory used for the potentially large
+temporary overlay file.
+
+You should ensure there is enough free space in the worst case for a
+full copy of the source disk (I<virtual> size), or else set C<$TMPDIR>
+to point to another directory that has enough space.
+
+This defaults to C</tmp>.
+
+Note that if C<$TMPDIR> is a tmpfs (eg. if C</tmp> is on tmpfs, or if
+you use C<TMPDIR=/dev/shm>), tmpfs defaults to a maximum size of
+I<half> of physical RAM. If virt-v2v exceeds this, it will hang.
+The solution is either to use a real disk, or to increase the maximum
+size of the tmpfs mountpoint, eg:
+
+ mount -o remount,size=10G /tmp
+
+=back
+
+For other environment variables, see L<guestfs(3)/ENVIRONMENT VARIABLES>.
+
+=head1 SEE ALSO
+
+L<virt-df(1)>,
+L<virt-filesystems(1)>,
+L<guestfs(3)>,
+L<guestfish(1)>,
+L<qemu-img(1)>,
+L<http://libguestfs.org/>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones L<http://people.redhat.com/~rjones/>
+
+Matthew Booth
+
+=head1 COPYRIGHT
+
+Copyright (C) 2009-2014 Red Hat Inc.
diff --git a/v2v/xml-c.c b/v2v/xml-c.c
new file mode 100644
index 0000000..9b79c6b
--- /dev/null
+++ b/v2v/xml-c.c
@@ -0,0 +1,240 @@
+/* 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.
+ */
+
+/* Mini interface to libxml2 for parsing libvirt XML. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <caml/alloc.h>
+#include <caml/custom.h>
+#include <caml/fail.h>
+#include <caml/memory.h>
+#include <caml/mlvalues.h>
+
+#include <libxml/xpath.h>
+
+#include "guestfs.h"
+#include "guestfs-internal-frontend.h"
+
+/* xmlDocPtr type */
+#define Doc_val(v) (*((xmlDocPtr *)Data_custom_val(v)))
+
+static void
+doc_finalize (value docv)
+{
+ xmlDocPtr doc = Doc_val (docv);
+
+ if (doc)
+ xmlFreeDoc (doc);
+}
+
+static struct custom_operations doc_custom_operations = {
+ (char *) "doc_custom_operations",
+ doc_finalize,
+ custom_compare_default,
+ custom_hash_default,
+ custom_serialize_default,
+ custom_deserialize_default
+};
+
+/* xmlXPathContextPtr type */
+#define Xpathctx_val(v) (*((xmlXPathContextPtr *)Data_custom_val(v)))
+
+static void
+xpathctx_finalize (value xpathctxv)
+{
+ xmlXPathContextPtr xpathctx = Xpathctx_val (xpathctxv);
+
+ if (xpathctx)
+ xmlXPathFreeContext (xpathctx);
+}
+
+static struct custom_operations xpathctx_custom_operations = {
+ (char *) "xpathctx_custom_operations",
+ xpathctx_finalize,
+ custom_compare_default,
+ custom_hash_default,
+ custom_serialize_default,
+ custom_deserialize_default
+};
+
+/* xmlXPathObjectPtr type */
+#define Xpathobj_val(v) (*((xmlXPathObjectPtr *)Data_custom_val(v)))
+
+static void
+xpathobj_finalize (value xpathobjv)
+{
+ xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
+
+ if (xpathobj)
+ xmlXPathFreeObject (xpathobj);
+}
+
+static struct custom_operations xpathobj_custom_operations = {
+ (char *) "xpathobj_custom_operations",
+ xpathobj_finalize,
+ custom_compare_default,
+ custom_hash_default,
+ custom_serialize_default,
+ custom_deserialize_default
+};
+
+value
+v2v_xml_parse_memory (value xmlv)
+{
+ CAMLparam1 (xmlv);
+ CAMLlocal1 (docv);
+ xmlDocPtr doc;
+
+ doc = xmlParseMemory (String_val (xmlv), caml_string_length (xmlv));
+ if (doc == NULL)
+ caml_invalid_argument ("parse_memory: unable to parse XML from libvirt");
+
+ docv = caml_alloc_custom (&doc_custom_operations, sizeof (xmlDocPtr), 0, 1);
+ Doc_val (docv) = doc;
+
+ CAMLreturn (docv);
+}
+
+value
+v2v_xml_xpath_new_context (value docv)
+{
+ CAMLparam1 (docv);
+ CAMLlocal1 (xpathctxv);
+ xmlDocPtr doc;
+ xmlXPathContextPtr xpathctx;
+
+ doc = Doc_val (docv);
+ xpathctx = xmlXPathNewContext (doc);
+ if (xpathctx == NULL)
+ caml_invalid_argument ("xpath_new_context: unable to create xmlXPathNewContext");
+
+ xpathctxv = caml_alloc_custom (&xpathctx_custom_operations,
+ sizeof (xmlXPathContextPtr), 0, 1);
+ Xpathctx_val (xpathctxv) = xpathctx;
+
+ CAMLreturn (xpathctxv);
+}
+
+value
+v2v_xml_xpath_eval_expression (value xpathctxv, value exprv)
+{
+ CAMLparam2 (xpathctxv, exprv);
+ CAMLlocal1 (xpathobjv);
+ xmlXPathContextPtr xpathctx;
+ xmlXPathObjectPtr xpathobj;
+
+ xpathctx = Xpathctx_val (xpathctxv);
+ xpathobj = xmlXPathEvalExpression (BAD_CAST String_val (exprv), xpathctx);
+ if (xpathobj == NULL)
+ caml_invalid_argument ("xpath_eval_expression: unable to evaluate XPath expression");
+
+ xpathobjv = caml_alloc_custom (&xpathobj_custom_operations,
+ sizeof (xmlXPathObjectPtr), 0, 1);
+ Xpathobj_val (xpathobjv) = xpathobj;
+
+ CAMLreturn (xpathobjv);
+}
+
+value
+v2v_xml_xpathobj_nr_nodes (value xpathobjv)
+{
+ CAMLparam1 (xpathobjv);
+ xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
+
+ CAMLreturn (Val_int (xpathobj->nodesetval->nodeNr));
+}
+
+value
+v2v_xml_xpathobj_get_node_ptr (value xpathobjv, value iv)
+{
+ CAMLparam2 (xpathobjv, iv);
+ xmlXPathObjectPtr xpathobj = Xpathobj_val (xpathobjv);
+ int i = Int_val (iv);
+
+ /* Because xmlNodePtrs are owned by the document, we don't want to
+ * wrap this up with a finalizer, so just pass the pointer straight
+ * back to OCaml as a value. OCaml will ignore it because it's
+ * outside the heap, and just pass it back to us when needed. This
+ * relies on the xmlDocPtr not being freed, but we pair the node
+ * pointer with the doc in the OCaml layer so the GC will not free
+ * one without freeing the other.
+ */
+ CAMLreturn ((value) xpathobj->nodesetval->nodeTab[i]);
+}
+
+value
+v2v_xml_xpathctx_set_node_ptr (value xpathctxv, value nodev)
+{
+ CAMLparam2 (xpathctxv, nodev);
+ xmlXPathContextPtr xpathctx = Xpathctx_val (xpathctxv);
+ xmlNodePtr node = (xmlNodePtr) nodev;
+
+ xpathctx->node = node;
+
+ CAMLreturn (Val_unit);
+}
+
+value
+v2v_xml_node_ptr_name (value nodev)
+{
+ CAMLparam1 (nodev);
+ xmlNodePtr node = (xmlNodePtr) nodev;
+
+ switch (node->type) {
+ case XML_ATTRIBUTE_NODE:
+ case XML_ELEMENT_NODE:
+ CAMLreturn (caml_copy_string ((char *) node->name));
+
+ default:
+ caml_invalid_argument ("node_name: don't know how to get the name of this node");
+ }
+}
+
+value
+v2v_xml_node_ptr_as_string (value docv, value nodev)
+{
+ CAMLparam2 (docv, nodev);
+ xmlDocPtr doc = Doc_val (docv);
+ xmlNodePtr node = (xmlNodePtr) nodev;
+ CLEANUP_FREE char *str = NULL;
+
+ switch (node->type) {
+ case XML_TEXT_NODE:
+ case XML_COMMENT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_PI_NODE:
+ CAMLreturn (caml_copy_string ((char *) node->content));
+
+ case XML_ATTRIBUTE_NODE:
+ case XML_ELEMENT_NODE:
+ str = (char *) xmlNodeListGetString (doc, node->children, 1);
+
+ if (str == NULL)
+ caml_invalid_argument ("node_as_string: xmlNodeListGetString cannot convert node to string");
+
+ CAMLreturn (caml_copy_string (str));
+
+ default:
+ caml_invalid_argument ("node_as_string: don't know how to convert this node to a string");
+ }
+}
diff --git a/v2v/xml.ml b/v2v/xml.ml
new file mode 100644
index 0000000..5cd75c1
--- /dev/null
+++ b/v2v/xml.ml
@@ -0,0 +1,50 @@
+(* 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.
+ *)
+
+(* Mini interface to libxml2 for parsing libvirt XML. *)
+
+type doc
+type node_ptr
+type xpathctx
+type xpathobj
+
+(* Since node is owned by doc, we have to make that explicit to the
+ * garbage collector.
+ *)
+type node = doc * node_ptr
+
+external parse_memory : string -> doc = "v2v_xml_parse_memory"
+external xpath_new_context : doc -> xpathctx = "v2v_xml_xpath_new_context"
+external xpath_eval_expression : xpathctx -> string -> xpathobj = "v2v_xml_xpath_eval_expression"
+
+external xpathobj_nr_nodes : xpathobj -> int = "v2v_xml_xpathobj_nr_nodes"
+external xpathobj_get_node_ptr : xpathobj -> int -> node_ptr = "v2v_xml_xpathobj_get_node_ptr"
+let xpathobj_node doc xpathobj i =
+ let n = xpathobj_get_node_ptr xpathobj i in
+ (doc, n)
+
+external xpathctx_set_node_ptr : xpathctx -> node_ptr -> unit = "v2v_xml_xpathctx_set_node_ptr"
+let xpathctx_set_current_context xpathctx (_, node) =
+ xpathctx_set_node_ptr xpathctx node
+
+external node_ptr_name : node_ptr -> string = "v2v_xml_node_ptr_name"
+let node_name (_, node) = node_ptr_name node
+
+external node_ptr_as_string : doc -> node_ptr -> string = "v2v_xml_node_ptr_as_string"
+let node_as_string (doc, node) =
+ node_ptr_as_string doc node
diff --git a/v2v/xml.mli b/v2v/xml.mli
new file mode 100644
index 0000000..c4363ad
--- /dev/null
+++ b/v2v/xml.mli
@@ -0,0 +1,57 @@
+(* 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.
+ *)
+
+(** Mini interface to libxml2 for parsing libvirt XML. *)
+
+type doc (** xmlDocPtr *)
+type node (** xmlNodePtr *)
+type xpathctx (** xmlXPathContextPtr *)
+type xpathobj (** xmlXPathObjectPtr *)
+
+val parse_memory : string -> doc
+(** xmlParseMemory *)
+val xpath_new_context : doc -> xpathctx
+(** xmlXPathNewContext *)
+val xpath_eval_expression : xpathctx -> string -> xpathobj
+(** xmlXPathEvalExpression *)
+
+val xpathobj_nr_nodes : xpathobj -> int
+(** Get the number of nodes in the node set of the xmlXPathObjectPtr. *)
+val xpathobj_node : doc -> xpathobj -> int -> node
+(** Get the number of nodes in the node set of the xmlXPathObjectPtr. *)
+
+val xpathctx_set_current_context : xpathctx -> node -> unit
+(** Set the current context of an xmlXPathContextPtr to the node.
+ Basically the same as the following C code:
+
+ {v
+ xpathctx->node = node
+ v}
+
+ It means the next expression you evaluate within this context will
+ start at this node, when evaluating relative paths
+ (eg. [./@attr]).
+*)
+
+val node_name : node -> string
+(** Get the name of the node. Note that only things like elements and
+ attributes have names. Other types of nodes will return an
+ error. *)
+
+val node_as_string : node -> string
+(** Converter to turn a node into a string *)
--
1.8.5.3
10 years, 7 months
[PATCH] build: Remove code coverage and code profiling options.
by Richard W.M. Jones
This reverts commit 5a2e320ec9390b2146feea6d7b3b8c36a34d0a90.
---
.gitignore | 4 ----
align/Makefile.am | 1 -
builder/Makefile.am | 2 --
cat/Makefile.am | 3 ---
configure.ac | 24 ------------------------
customize/Makefile.am | 2 --
df/Makefile.am | 1 -
diff/Makefile.am | 1 -
edit/Makefile.am | 1 -
erlang/Makefile.am | 3 +--
examples/Makefile.am | 24 ++++++++----------------
fish/Makefile.am | 1 -
format/Makefile.am | 1 -
fuse/Makefile.am | 7 ++-----
inspector/Makefile.am | 1 -
make-fs/Makefile.am | 1 -
mllib/Makefile.am | 2 --
rescue/Makefile.am | 1 -
resize/Makefile.am | 2 --
src/Makefile.am | 4 +---
sysprep/Makefile.am | 2 --
test-tool/Makefile.am | 3 +--
tests/c-api/Makefile.am | 40 +++++++++++++---------------------------
tests/charsets/Makefile.am | 3 +--
tests/events/Makefile.am | 1 -
tests/mount-local/Makefile.am | 1 -
tests/mountable/Makefile.am | 3 +--
tests/parallel/Makefile.am | 3 +--
tests/regressions/Makefile.am | 12 ++++--------
29 files changed, 33 insertions(+), 121 deletions(-)
diff --git a/.gitignore b/.gitignore
index 3e6a084..4d47d23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,9 +9,6 @@
*.cmxa
*.diff
*.eml
-*.gcda
-*.gcno
-*.gcov
*.hi
*.jar
*.la
@@ -26,7 +23,6 @@ bindtests.tmp
cscope.out
.deps
.gdb_history
-gmon.out
.libs
Makefile
Makefile.in
diff --git a/align/Makefile.am b/align/Makefile.am
index b243823..4ecbf7e 100644
--- a/align/Makefile.am
+++ b/align/Makefile.am
@@ -58,7 +58,6 @@ virt_alignment_scan_CPPFLAGS = \
virt_alignment_scan_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBVIRT_CFLAGS)
diff --git a/builder/Makefile.am b/builder/Makefile.am
index 851e3a6..7d399d4 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -165,7 +165,6 @@ virt-builder: $(OBJECTS)
$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
mlguestfs.cmxa -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
else
virt-builder: $(OBJECTS)
@@ -173,7 +172,6 @@ virt-builder: $(OBJECTS)
mlguestfs.cma -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
-custom \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
endif
diff --git a/cat/Makefile.am b/cat/Makefile.am
index 2db4997..ac045aa 100644
--- a/cat/Makefile.am
+++ b/cat/Makefile.am
@@ -51,7 +51,6 @@ virt_cat_CPPFLAGS = \
virt_cat_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS)
virt_cat_LDADD = \
@@ -74,7 +73,6 @@ virt_filesystems_CPPFLAGS = \
virt_filesystems_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS)
virt_filesystems_LDADD = \
@@ -99,7 +97,6 @@ virt_ls_CPPFLAGS = \
virt_ls_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS)
virt_ls_LDADD = \
diff --git a/configure.ac b/configure.ac
index f48a8d6..f3e8556 100644
--- a/configure.ac
+++ b/configure.ac
@@ -998,30 +998,6 @@ AS_IF([test "x$VALGRIND" != "xno"],[
AC_SUBST([VG])
AM_SUBST_NOTMAKE([VG])
-dnl Enable profiling?
-AC_ARG_ENABLE([code-profiling],
- AS_HELP_STRING([--enable-code-profiling], [enable code profiling]),
- [],
- [enable_code_profiling=no])
-AS_IF([test "x$enable_code_profiling" != "xno"],[
- GPROF_CFLAGS="-pg"
- AC_SUBST([GPROF_CFLAGS])
-])
-
-dnl Enable code coverage?
-AC_ARG_ENABLE([code-coverage],
- AS_HELP_STRING([--enable-code-coverage], [enable code coverage]),
- [],
- [enable_code_coverage=no])
-AS_IF([test "x$enable_code_coverage" != "xno"],[
- GCOV_CFLAGS="-fprofile-arcs -ftest-coverage"
- AC_SUBST([GCOV_CFLAGS])
- dnl This is a hack to make OCaml programs work when they
- dnl link to C code that is compiled with gcov flags.
- OCAML_GCOV_LDFLAGS="-cclib -lgcov"
- AC_SUBST([OCAML_GCOV_LDFLAGS])
-])
-
dnl Check for OCaml (optional, for OCaml bindings and OCaml tools).
OCAMLC=no
OCAMLFIND=no
diff --git a/customize/Makefile.am b/customize/Makefile.am
index ae1e007..80fceb3 100644
--- a/customize/Makefile.am
+++ b/customize/Makefile.am
@@ -122,14 +122,12 @@ if HAVE_OCAMLOPT
$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
mlguestfs.cmxa -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
else
$(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
mlguestfs.cma -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
-custom \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
endif
diff --git a/df/Makefile.am b/df/Makefile.am
index 38a628c..29e0bf5 100644
--- a/df/Makefile.am
+++ b/df/Makefile.am
@@ -61,7 +61,6 @@ virt_df_CPPFLAGS = \
virt_df_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBVIRT_CFLAGS)
diff --git a/diff/Makefile.am b/diff/Makefile.am
index 5b38e21..3c2c211 100644
--- a/diff/Makefile.am
+++ b/diff/Makefile.am
@@ -49,7 +49,6 @@ virt_diff_CPPFLAGS = \
virt_diff_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS)
virt_diff_LDADD = \
diff --git a/edit/Makefile.am b/edit/Makefile.am
index dbaad6c..1d51095 100644
--- a/edit/Makefile.am
+++ b/edit/Makefile.am
@@ -48,7 +48,6 @@ virt_edit_CPPFLAGS = \
virt_edit_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS)
diff --git a/erlang/Makefile.am b/erlang/Makefile.am
index 7ac24f2..c68641c 100644
--- a/erlang/Makefile.am
+++ b/erlang/Makefile.am
@@ -61,8 +61,7 @@ erl_guestfs_CPPFLAGS = \
-I$(ERLANG_LIB_DIR_erl_interface)/include
erl_guestfs_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
erl_guestfs_LDADD = \
$(ERLANG_LIB_DIR_erl_interface)/lib/liberl_interface.a \
diff --git a/examples/Makefile.am b/examples/Makefile.am
index c2606bd..e150a58 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -59,8 +59,7 @@ copy_over_CPPFLAGS = \
copy_over_CFLAGS = \
$(LIBVIRT_CFLAGS) \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
copy_over_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(LIBVIRT_LIBS)
@@ -72,8 +71,7 @@ libvirt_auth_CPPFLAGS = \
libvirt_auth_CFLAGS = \
$(LIBVIRT_CFLAGS) \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
libvirt_auth_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(LIBVIRT_LIBS)
@@ -84,8 +82,7 @@ create_disk_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src
create_disk_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
create_disk_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -94,8 +91,7 @@ debug_logging_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src
debug_logging_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
debug_logging_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -104,8 +100,7 @@ display_icon_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src
display_icon_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
display_icon_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -114,8 +109,7 @@ inspect_vm_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src
inspect_vm_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
inspect_vm_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -128,8 +122,7 @@ mount_local_CFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src \
$(FUSE_CFLAGS) \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
mount_local_LDADD = \
$(FUSE_LIBS) \
$(top_builddir)/src/libguestfs.la
@@ -141,8 +134,7 @@ virt_dhcp_address_CPPFLAGS = \
-DGUESTFS_WARN_DEPRECATED=1 \
-I$(top_srcdir)/src -I$(top_builddir)/src
virt_dhcp_address_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
virt_dhcp_address_LDADD = \
$(top_builddir)/src/libguestfs.la
endif
diff --git a/fish/Makefile.am b/fish/Makefile.am
index c39c968..ad984ec 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -133,7 +133,6 @@ guestfish_CPPFLAGS = \
guestfish_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS)
diff --git a/format/Makefile.am b/format/Makefile.am
index c93edc9..178c391 100644
--- a/format/Makefile.am
+++ b/format/Makefile.am
@@ -47,7 +47,6 @@ virt_format_CPPFLAGS = \
virt_format_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBVIRT_CFLAGS)
diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 2797e51..3fd64a2 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -61,7 +61,6 @@ guestmount_CPPFLAGS = \
guestmount_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(FUSE_CFLAGS)
@@ -86,8 +85,7 @@ guestunmount_CPPFLAGS = \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
guestunmount_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
guestunmount_LDADD = \
$(top_builddir)/src/libutils.la \
@@ -151,8 +149,7 @@ test_guestunmount_fd_CPPFLAGS = \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib
test_guestunmount_fd_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_guestunmount_fd_LDADD = \
$(top_builddir)/src/libutils.la \
diff --git a/inspector/Makefile.am b/inspector/Makefile.am
index 8738abc..86e0cd7 100644
--- a/inspector/Makefile.am
+++ b/inspector/Makefile.am
@@ -75,7 +75,6 @@ virt_inspector_CPPFLAGS = \
virt_inspector_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBCONFIG_CFLAGS)
diff --git a/make-fs/Makefile.am b/make-fs/Makefile.am
index d318468..03e30ba 100644
--- a/make-fs/Makefile.am
+++ b/make-fs/Makefile.am
@@ -44,7 +44,6 @@ virt_make_fs_CPPFLAGS = \
virt_make_fs_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBXML2_CFLAGS)
virt_make_fs_LDADD = \
diff --git a/mllib/Makefile.am b/mllib/Makefile.am
index fe215f8..72a032c 100644
--- a/mllib/Makefile.am
+++ b/mllib/Makefile.am
@@ -101,14 +101,12 @@ if HAVE_OCAMLOPT
$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
mlguestfs.cmxa -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
else
$(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
mlguestfs.cma -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
-custom \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
endif
diff --git a/rescue/Makefile.am b/rescue/Makefile.am
index c2a9b9e..6a5e175 100644
--- a/rescue/Makefile.am
+++ b/rescue/Makefile.am
@@ -49,7 +49,6 @@ virt_rescue_CPPFLAGS = \
virt_rescue_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBCONFIG_CFLAGS) \
$(LIBXML2_CFLAGS)
diff --git a/resize/Makefile.am b/resize/Makefile.am
index 67cb8c9..4b049ab 100644
--- a/resize/Makefile.am
+++ b/resize/Makefile.am
@@ -80,7 +80,6 @@ virt-resize: $(OBJECTS)
$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
mlguestfs.cmxa -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
else
virt-resize: $(OBJECTS)
@@ -88,7 +87,6 @@ virt-resize: $(OBJECTS)
mlguestfs.cma -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
-custom \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
endif
diff --git a/src/Makefile.am b/src/Makefile.am
index e861467..3d06203 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -139,7 +139,6 @@ libguestfs_la_CPPFLAGS = \
libguestfs_la_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(GCC_VISIBILITY_HIDDEN) \
$(PCRE_CFLAGS) \
$(LIBVIRT_CFLAGS) \
@@ -262,8 +261,7 @@ test_utils_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
-I$(top_srcdir)/src -I.
test_utils_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_utils_LDADD = \
libguestfs_la-guid.lo \
libutils.la \
diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am
index f555d6b..cc411cc 100644
--- a/sysprep/Makefile.am
+++ b/sysprep/Makefile.am
@@ -138,7 +138,6 @@ virt-sysprep: $(OBJECTS)
$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
mlguestfs.cmxa -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
else
virt-sysprep: $(OBJECTS)
@@ -146,7 +145,6 @@ virt-sysprep: $(OBJECTS)
mlguestfs.cma -linkpkg $^ \
-cclib '$(OCAMLCLIBS)' \
-custom \
- $(OCAML_GCOV_LDFLAGS) \
-o $@
endif
diff --git a/test-tool/Makefile.am b/test-tool/Makefile.am
index 21e411d..c0e958c 100644
--- a/test-tool/Makefile.am
+++ b/test-tool/Makefile.am
@@ -33,8 +33,7 @@ libguestfs_test_tool_CPPFLAGS = \
-DLOCALEBASEDIR=\""$(datadir)/locale"\"
libguestfs_test_tool_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
libguestfs_test_tool_LDADD = \
$(top_builddir)/src/libguestfs.la \
diff --git a/tests/c-api/Makefile.am b/tests/c-api/Makefile.am
index 3df00b1..6ea22e9 100644
--- a/tests/c-api/Makefile.am
+++ b/tests/c-api/Makefile.am
@@ -83,7 +83,6 @@ tests_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
tests_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(PCRE_CFLAGS)
tests_LDADD = \
$(PCRE_LIBS) \
@@ -108,8 +107,7 @@ test_just_header_SOURCES = test-just-header.c
test_just_header_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_just_header_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_just_header_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -118,8 +116,7 @@ test_just_header_cxx_SOURCES = test-just-header-cxx.cpp
test_just_header_cxx_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_just_header_cxx_CXXFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_just_header_cxx_LDADD = \
$(top_builddir)/src/libguestfs.la
endif
@@ -128,8 +125,7 @@ test_create_handle_SOURCES = test-create-handle.c
test_create_handle_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_create_handle_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_create_handle_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -137,8 +133,7 @@ test_config_SOURCES = test-config.c
test_config_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_config_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_config_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -146,8 +141,7 @@ test_add_drive_opts_SOURCES = test-add-drive-opts.c
test_add_drive_opts_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_add_drive_opts_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_add_drive_opts_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -156,8 +150,7 @@ test_last_errno_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_last_errno_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_last_errno_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
@@ -166,8 +159,7 @@ test_backend_settings_SOURCES = test-backend-settings.c
test_backend_settings_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_backend_settings_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_backend_settings_LDADD = \
$(top_builddir)/src/libutils_la-utils.lo \
$(top_builddir)/src/libguestfs.la
@@ -176,8 +168,7 @@ test_private_data_SOURCES = test-private-data.c
test_private_data_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_private_data_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_private_data_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -187,8 +178,7 @@ test_user_cancel_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_user_cancel_CFLAGS = \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_user_cancel_LDADD = \
$(top_builddir)/src/libguestfs.la -lm \
$(top_builddir)/gnulib/lib/libgnu.la
@@ -199,8 +189,7 @@ test_debug_to_file_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib \
-I$(top_builddir)/gnulib/lib
test_debug_to_file_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_debug_to_file_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
@@ -211,8 +200,7 @@ test_environment_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib \
-I$(top_builddir)/gnulib/lib
test_environment_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_environment_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
@@ -223,8 +211,7 @@ test_event_string_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib \
-I$(top_builddir)/gnulib/lib
test_event_string_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_event_string_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
@@ -235,8 +222,7 @@ test_event_string_LDADD = \
# -I$(top_srcdir)/src -I$(top_builddir)/src -I$(top_srcdir)/gnulib/lib
#test_add_libvirt_dom_CFLAGS = \
# $(LIBVIRT_CFLAGS) \
-# $(WARN_CFLAGS) $(WERROR_CFLAGS) \
-# $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+# $(WARN_CFLAGS) $(WERROR_CFLAGS)
#test_add_libvirt_dom_LDADD = \
# $(top_builddir)/src/libguestfs.la $(LIBVIRT_LIBS) \
# $(LTLIBTHREAD) $(top_builddir)/gnulib/lib/libgnu.la
diff --git a/tests/charsets/Makefile.am b/tests/charsets/Makefile.am
index 5a94255..b7ec703 100644
--- a/tests/charsets/Makefile.am
+++ b/tests/charsets/Makefile.am
@@ -28,8 +28,7 @@ test_charset_fidelity_SOURCES = test-charset-fidelity.c
test_charset_fidelity_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_charset_fidelity_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_charset_fidelity_LDADD = \
$(top_builddir)/src/libutils.la \
$(top_builddir)/src/libguestfs.la \
diff --git a/tests/events/Makefile.am b/tests/events/Makefile.am
index 9751edc..9f31e9e 100644
--- a/tests/events/Makefile.am
+++ b/tests/events/Makefile.am
@@ -37,7 +37,6 @@ test_libvirt_auth_callbacks_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_libvirt_auth_callbacks_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(LIBVIRT_CFLAGS)
test_libvirt_auth_callbacks_LDADD = \
$(top_builddir)/src/libutils.la \
diff --git a/tests/mount-local/Makefile.am b/tests/mount-local/Makefile.am
index 3506cac..17cfa73 100644
--- a/tests/mount-local/Makefile.am
+++ b/tests/mount-local/Makefile.am
@@ -37,7 +37,6 @@ test_parallel_mount_local_CPPFLAGS = \
test_parallel_mount_local_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS) \
$(FUSE_CFLAGS)
test_parallel_mount_local_LDADD = \
$(FUSE_LIBS) \
diff --git a/tests/mountable/Makefile.am b/tests/mountable/Makefile.am
index f7824f5..0e2cedd 100644
--- a/tests/mountable/Makefile.am
+++ b/tests/mountable/Makefile.am
@@ -32,8 +32,7 @@ test_internal_parse_mountable_CPPFLAGS = \
-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_internal_parse_mountable_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_internal_parse_mountable_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
diff --git a/tests/parallel/Makefile.am b/tests/parallel/Makefile.am
index f4e0e7c..be63256 100644
--- a/tests/parallel/Makefile.am
+++ b/tests/parallel/Makefile.am
@@ -32,8 +32,7 @@ test_parallel_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
test_parallel_CFLAGS = \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
test_parallel_LDADD = \
$(top_builddir)/src/libguestfs.la \
$(top_builddir)/gnulib/lib/libgnu.la
diff --git a/tests/regressions/Makefile.am b/tests/regressions/Makefile.am
index 8016e2f..ac7da56 100644
--- a/tests/regressions/Makefile.am
+++ b/tests/regressions/Makefile.am
@@ -88,8 +88,7 @@ rhbz501893_SOURCES = rhbz501893.c
rhbz501893_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
rhbz501893_CFLAGS = \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
rhbz501893_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -98,8 +97,7 @@ rhbz790721_CPPFLAGS = \
-I$(top_srcdir)/src -I$(top_builddir)/src
rhbz790721_CFLAGS = \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
rhbz790721_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -109,8 +107,7 @@ rhbz914931_CPPFLAGS = \
-DGUESTFS_PRIVATE=1
rhbz914931_CFLAGS = \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
rhbz914931_LDADD = \
$(top_builddir)/src/libguestfs.la
@@ -120,8 +117,7 @@ rhbz1055452_CPPFLAGS = \
-DGUESTFS_PRIVATE=1
rhbz1055452_CFLAGS = \
-pthread \
- $(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(GPROF_CFLAGS) $(GCOV_CFLAGS)
+ $(WARN_CFLAGS) $(WERROR_CFLAGS)
rhbz1055452_LDADD = \
$(top_builddir)/src/libguestfs.la
--
1.8.5.3
10 years, 7 months
[PATCH] sparsify: Use automake to build and link virt-sparsify binary.
by Richard W.M. Jones
There are two observations which make this possible: (1) virt-sparsify
contains at least one C unit, so automake thinks it is compiling a C
program. (2) Automake lets us add a *_LINK rule to override linking.
We list the C sources of virt-sparsify as virt_sparsify_SOURCES, so
automake thinks it is building a C program as normal.
We override virt_sparsify_LINK to make it actually link an OCaml
program.
We add virt_sparsify_DEPENDENCIES listing the OCaml objects so that
they get built before linking.
We need a small linker script (link.sh) which adds some options at the
end of the linker command line which are impossible to add using pure
automake.
Inspired by the same idea in supermin:
https://github.com/libguestfs/supermin/blob/master/src/Makefile.am
---
.gitignore | 1 +
configure.ac | 2 +
sparsify/Makefile.am | 104 ++++++++++++++++++++++-----------------------------
sparsify/link.sh.in | 22 +++++++++++
4 files changed, 69 insertions(+), 60 deletions(-)
create mode 100644 sparsify/link.sh.in
diff --git a/.gitignore b/.gitignore
index dc8aaf8..3e6a084 100644
--- a/.gitignore
+++ b/.gitignore
@@ -414,6 +414,7 @@ Makefile.in
/ruby/Rakefile
/run
/sparsify/.depend
+/sparsify/link.sh
/sparsify/stamp-virt-sparsify.pod
/sparsify/virt-sparsify
/sparsify/virt-sparsify.1
diff --git a/configure.ac b/configure.ac
index 8abdc90..f48a8d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1607,6 +1607,8 @@ AC_CONFIG_FILES([podwrapper.pl],
[chmod +x,-w podwrapper.pl])
AC_CONFIG_FILES([run],
[chmod +x,-w run])
+AC_CONFIG_FILES([sparsify/link.sh],
+ [chmod +x,-w sparsify/link.sh])
AC_CONFIG_FILES([Makefile
align/Makefile
diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am
index 5e1b382..bcb95a2 100644
--- a/sparsify/Makefile.am
+++ b/sparsify/Makefile.am
@@ -1,5 +1,5 @@
# libguestfs virt-sparsify tool
-# Copyright (C) 2011 Red Hat Inc.
+# Copyright (C) 2011-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
@@ -18,52 +18,50 @@
include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
- $(SOURCES) \
+ $(SOURCES_ML) $(SOURCES_C) \
virt-sparsify.pod \
test-virt-sparsify.sh \
test-virt-sparsify-in-place.sh
CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-sparsify
-# Alphabetical order.
-SOURCES = \
+SOURCES_ML = \
cmdline.ml \
copying.ml \
in_place.ml \
- sparsify.ml \
+ sparsify.ml
+
+SOURCES_C = \
+ $(top_builddir)/fish/progress.c \
+ $(top_builddir)/mllib/tty-c.c \
+ $(top_builddir)/mllib/progress-c.c \
statvfs-c.c
if HAVE_OCAML
-# Note this list must be in dependency order.
-deps = \
- $(top_builddir)/fish/guestfish-progress.o \
- $(top_builddir)/mllib/tty-c.o \
- $(top_builddir)/mllib/progress-c.o \
- $(top_builddir)/mllib/common_gettext.cmx \
- $(top_builddir)/mllib/common_utils.cmx \
- $(top_builddir)/mllib/tTY.cmx \
- $(top_builddir)/mllib/progress.cmx \
- $(top_builddir)/mllib/config.cmx \
- statvfs-c.o \
- cmdline.cmx \
- copying.cmx \
- in_place.cmx \
- sparsify.cmx
+bin_PROGRAMS = virt-sparsify
-if HAVE_OCAMLOPT
-OBJECTS = $(deps)
-else
-OBJECTS = $(patsubst %.cmx,%.cmo,$(deps))
-endif
+virt_sparsify_SOURCES = $(SOURCES_C)
+virt_sparsify_CFLAGS = \
+ -I. \
+ -I$(top_builddir) \
+ -I$(shell $(OCAMLC) -where) \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/fish
-bin_SCRIPTS = virt-sparsify
+BOBJECTS = \
+ $(top_builddir)/mllib/common_gettext.cmo \
+ $(top_builddir)/mllib/common_utils.cmo \
+ $(top_builddir)/mllib/tTY.cmo \
+ $(top_builddir)/mllib/progress.cmo \
+ $(top_builddir)/mllib/config.cmo \
+ $(SOURCES_ML:.ml=.cmo)
+XOBJECTS = $(BOBJECTS:.cmo=.cmx)
# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
# option to be passed to gcc, so we don't try linking against an
# installed copy of libguestfs.
-OCAMLPACKAGES = \
- -package str,unix \
+OCAMLPACKAGES = -package str,unix \
-I $(top_builddir)/src/.libs \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/mllib
@@ -71,45 +69,31 @@ if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
endif
-OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES)
-OCAMLOPTFLAGS = $(OCAMLCFLAGS)
+OCAMLFLAGS = -g -warn-error CDEFLMPSUVYZX
-if HAVE_OCAMLOPT
-virt-sparsify: $(OBJECTS)
- $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
- mlguestfs.cmxa -linkpkg $^ \
- -cclib -lncurses \
- $(OCAML_GCOV_LDFLAGS) \
- -o $@
+if !HAVE_OCAMLOPT
+OBJECTS = $(BOBJECTS)
+BEST = c
+OCAMLFLAGS += -custom
+OCAMLPACKAGES += mlguestfs.cma
else
-virt-sparsify: $(OBJECTS)
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
- mlguestfs.cma -linkpkg $^ \
- -cclib -lncurses \
- -custom \
- $(OCAML_GCOV_LDFLAGS) \
- -o $@
+OBJECTS = $(XOBJECTS)
+BEST = opt
+OCAMLPACKAGES += mlguestfs.cmxa
endif
+virt_sparsify_DEPENDENCIES = $(OBJECTS)
+
+virt_sparsify_LINK = \
+ ./link.sh \
+ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OBJECTS) -o $@
+
.mli.cmi:
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmx:
- $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
-
-# automake will decide we don't need C support in this file. Really
-# we do, so we have to provide it ourselves.
-
-DEFAULT_INCLUDES = \
- -I. \
- -I$(top_builddir) \
- -I$(shell $(OCAMLC) -where) \
- -I$(top_srcdir)/src \
- -I$(top_srcdir)/fish
-
-.c.o:
- $(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+ $(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
# Manual pages and HTML files for the website.
diff --git a/sparsify/link.sh.in b/sparsify/link.sh.in
new file mode 100644
index 0000000..50bcc1f
--- /dev/null
+++ b/sparsify/link.sh.in
@@ -0,0 +1,22 @@
+# libguestfs Makefile.am
+# @configure_input@
+# (C) Copyright 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Hack automake to link binary properly. There is no other way to add
+# the -cclib parameter to the end of the command line.
+
+exec "$@" -linkpkg -cclib '-lncurses'
--
1.8.5.3
10 years, 7 months
[PATCH] customize: add the chmod command
by Pino Toscano
Add the chmod customize command to change the permissions of files.
---
builder/cmdline.ml | 2 +-
customize/customize_run.ml | 8 ++++++++
customize/test-virt-customize.sh | 1 +
generator/customize.ml | 12 ++++++++++++
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/builder/cmdline.ml b/builder/cmdline.ml
index 3a620fe..45c87fc 100644
--- a/builder/cmdline.ml
+++ b/builder/cmdline.ml
@@ -315,7 +315,7 @@ read the man page virt-builder(1).
| `Delete _ | `Edit _ | `FirstbootCommand _ | `FirstbootPackages _
| `FirstbootScript _ | `Hostname _ | `Link _ | `Mkdir _
| `Password _ | `RootPassword _ | `Scrub _ | `Timezone _ | `Upload _
- | `Write _ -> false
+ | `Write _ | `Chmod _ -> false
) ops.ops in
if requires_execute_on_guest then (
eprintf (f_"%s: sorry, cannot run commands on a guest with a different architecture\n")
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 8a1df32..4d83e90 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -168,6 +168,14 @@ exec >>%s 2>&1
(* Perform the remaining customizations in command-line order. *)
List.iter (
function
+ | `Chmod (mode, path) ->
+ msg (f_"Changing permissions of %s to %s") path mode;
+ (* If the mode string is octal, add the OCaml prefix for octal values
+ * so it is properly converted as octal integer.
+ *)
+ let mode = if string_prefix mode "0" then "0o" ^ mode else mode in
+ g#chmod (int_of_string mode) path
+
| `Command cmd ->
msg (f_"Running: %s") cmd;
do_run ~display:cmd cmd
diff --git a/customize/test-virt-customize.sh b/customize/test-virt-customize.sh
index be61796..623e6a2 100755
--- a/customize/test-virt-customize.sh
+++ b/customize/test-virt-customize.sh
@@ -29,6 +29,7 @@ for f in ../tests/guests/{debian,fedora,ubuntu}.img; do
$VG ./virt-customize -n -a $f \
--no-network \
--write /etc/motd:HELLO \
+ --chmod 0600:/etc/motd \
--delete /etc/motd
fi
done
diff --git a/generator/customize.ml b/generator/customize.ml
index 0b0580a..2c991ea 100644
--- a/generator/customize.ml
+++ b/generator/customize.ml
@@ -44,6 +44,18 @@ and op_type =
| UserPasswordSelector of string (* user:selector *)
let ops = [
+ { op_name = "chmod";
+ op_type = StringPair "PERMISSIONS:FILE";
+ op_discrim = "`Chmod";
+ op_shortdesc = "Change the permissions of a file";
+ op_pod_longdesc = "\
+Change the permissions of C<FILE> to C<PERMISSIONS>.
+
+I<Note>: C<PERMISSIONS> by default would be decimal, unless you prefix
+it with C<0> to get octal, ie. use C<0700> not C<700>.
+
+The mode actually set is affected by the umask.";
+ };
{ op_name = "delete";
op_type = String "PATH";
op_discrim = "`Delete";
--
1.9.0
10 years, 7 months
[PATCH v2 NOT TO BE APPLIED 1/2] mllib: utils: Add mapi function.
by Richard W.M. Jones
This is List.mapi from the stdlib. RHEL 6 did not have this function.
---
mllib/common_utils.ml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml
index 094ef10..3b15868 100644
--- a/mllib/common_utils.ml
+++ b/mllib/common_utils.ml
@@ -174,6 +174,14 @@ let iteri f xs =
in
loop 0 xs
+let rec mapi i f =
+ function
+ | [] -> []
+ | a::l ->
+ let r = f i a in
+ r :: mapi (i + 1) f l
+let mapi f l = mapi 0 f l
+
(* Timestamped progress messages, used for ordinary messages when not
* --quiet.
*)
--
1.8.5.3
10 years, 7 months
[PATCH] appliance: Avoid touching appliance/supermin.d directory.
by Richard W.M. Jones
This code is subtle, to say the least.
When using 'supermin --build --if-newer', supermin will check if
appliance/supermin.d is newer than tmp/.guestfs-UID/appliance.d, and
only rebuild the full appliance if so.
So we need to avoid touching appliance/supermin.d unless there's an
actual change. Unfortunately simply by creating and then deleting
temporary files under appliance/supermin.d we were touching
appliance/supermin.d resulting in a full appliance rebuild after every
'make'.
Supermin 4 actually visited every file in the supermin appliance and
then every file in the full appliance and computed a checksum from
them, which was slower over all but didn't suffer from this problem.
Note the above only matters for developers building and running from
the build directory (ie. using ./run commands). It doesn't affect
libguestfs users.
Rich.
10 years, 7 months