[Pkg-libvirt-commits] [libguestfs] 23/61: Add virt-customize standalone tool.

Hilko Bengen bengen at moszumanska.debian.org
Sat Mar 29 14:36:23 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch experimental
in repository libguestfs.

commit 2b208d84db080659badbb70044497aae040592e7
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Tue Mar 25 10:46:08 2014 +0000

    Add virt-customize standalone tool.
    
    This includes some simple tests and a manual page.
---
 .gitignore                       |   3 +
 Makefile.am                      |   1 +
 builder/virt-builder.pod         |   1 +
 customize/Makefile.am            |  41 ++++++--
 customize/main.ml                | 222 +++++++++++++++++++++++++++++++++++++++
 customize/test-virt-customize.sh |  32 ++++++
 customize/virt-customize.pod     | 156 +++++++++++++++++++++++++++
 fish/guestfish.pod               |   1 +
 po-docs/ja/Makefile.am           |   9 ++
 po-docs/podfiles                 |   3 +
 po-docs/uk/Makefile.am           |   9 ++
 src/guestfs.pod                  |   3 +-
 sysprep/virt-sysprep.pod         |   1 +
 13 files changed, 474 insertions(+), 8 deletions(-)

diff --git a/.gitignore b/.gitignore
index a93eb95..0231a04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,7 +95,9 @@ Makefile.in
 /customize/customize_cmdline.mli
 /customize/customize-options.pod
 /customize/customize-synopsis.pod
+/customize/stamp-virt-customize.pod
 /customize/virt-customize
+/customize/virt-customize.1
 /daemon/actions.h
 /daemon/errnostring.c
 /daemon/errnostring-gperf.c
@@ -236,6 +238,7 @@ Makefile.in
 /html/virt-cat.1.html
 /html/virt-copy-in.1.html
 /html/virt-copy-out.1.html
+/html/virt-customize.1.html
 /html/virt-df.1.html
 /html/virt-diff.1.html
 /html/virt-edit.1.html
diff --git a/Makefile.am b/Makefile.am
index 5b8a82e..ce0f9ad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -239,6 +239,7 @@ HTMLFILES = \
 	html/virt-cat.1.html \
 	html/virt-copy-in.1.html \
 	html/virt-copy-out.1.html \
+	html/virt-customize.1.html \
 	html/virt-df.1.html \
 	html/virt-diff.1.html \
 	html/virt-edit.1.html \
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index 2429f66..c6e66ff 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -1590,6 +1590,7 @@ L<guestfs(3)>,
 L<guestfish(1)>,
 L<guestmount(1)>,
 L<virt-copy-out(1)>,
+L<virt-customize(1)>,
 L<virt-install(1)>,
 L<virt-rescue(1)>,
 L<virt-resize(1)>,
diff --git a/customize/Makefile.am b/customize/Makefile.am
index 889fe1c..2747add 100644
--- a/customize/Makefile.am
+++ b/customize/Makefile.am
@@ -18,9 +18,14 @@
 include $(top_srcdir)/subdir-rules.mk
 
 EXTRA_DIST = \
-	$(SOURCES)
+	$(SOURCES) \
+	test-virt-customize.sh \
+	virt-customize.pod
 
-CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o
+CLEANFILES = \
+	*~ *.cmi *.cmo *.cmx *.cmxa *.o \
+	stamp-virt-customize.pod \
+	virt-customize virt-customize.1
 
 generator_built = \
 	customize_cmdline.mli \
@@ -41,6 +46,7 @@ SOURCES = \
 	firstboot.mli \
 	hostname.ml \
 	hostname.mli \
+	main.ml \
 	password.ml \
 	password.mli \
 	perl_edit.ml \
@@ -55,8 +61,12 @@ SOURCES = \
 if HAVE_OCAML
 
 deps = \
+	$(top_builddir)/fish/guestfish-uri.o \
 	$(top_builddir)/mllib/common_gettext.cmx \
 	$(top_builddir)/mllib/common_utils.cmx \
+	$(top_builddir)/mllib/config.cmx \
+	$(top_builddir)/mllib/uri-c.o \
+	$(top_builddir)/mllib/uRI.cmx \
 	crypt-c.o
 
 if HAVE_OCAMLOPT
@@ -76,7 +86,8 @@ ocaml_modules = \
 	random_seed \
 	timezone \
 	customize_cmdline \
-	customize_run
+	customize_run \
+	main
 
 if HAVE_OCAMLOPT
 OBJECTS += $(patsubst %,%.cmx,$(ocaml_modules))
@@ -84,9 +95,7 @@ else
 OBJECTS += $(patsubst %,%.cmo,$(ocaml_modules))
 endif
 
-# XXX virt-customize isn't a complete tool yet, so currently this is
-# just a dummy target binary.
-noinst_SCRIPTS = virt-customize
+bin_SCRIPTS = virt-customize
 
 # -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
@@ -144,11 +153,29 @@ DEFAULT_INCLUDES = \
 .c.o:
 	$(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
 
+# Manual pages and HTML files for the website.
+man_MANS = virt-customize.1
+noinst_DATA = $(top_builddir)/html/virt-customize.1.html
+
+virt-customize.1 $(top_builddir)/html/virt-customize.1.html: stamp-virt-customize.pod
+
+stamp-virt-customize.pod: virt-customize.pod $(top_srcdir)/customize/customize-synopsis.pod $(top_srcdir)/customize/customize-options.pod
+	$(PODWRAPPER) \
+	  --man virt-customize.1 \
+	  --html $(top_builddir)/html/virt-customize.1.html \
+	  --insert $(top_srcdir)/customize/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
+	  --insert $(top_srcdir)/customize/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
+	  --license GPLv2+ \
+	  $<
+	touch $@
+
 # Tests.
 
 TESTS_ENVIRONMENT = $(top_builddir)/run --test
 
-TESTS =
+if ENABLE_APPLIANCE
+TESTS = test-virt-customize.sh
+endif
 
 check-valgrind:
 	$(MAKE) VG="$(top_builddir)/run @VG@" check
diff --git a/customize/main.ml b/customize/main.ml
new file mode 100644
index 0000000..74ecb8e
--- /dev/null
+++ b/customize/main.ml
@@ -0,0 +1,222 @@
+(* virt-customize
+ * Copyright (C) 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 Common_gettext.Gettext
+open Common_utils
+
+open Printf
+
+module G = Guestfs
+
+let () = Random.self_init ()
+
+let prog = Filename.basename Sys.executable_name
+
+let main () =
+  let debug_gc = ref false in
+  let domain = ref None in
+  let dryrun = ref false in
+  let files = ref [] in
+  let format = ref "auto" in
+  let quiet = ref false in
+  let libvirturi = ref "" in
+  let trace = ref false in
+  let verbose = ref false in
+
+  let display_version () =
+    printf "virt-customize %s\n" Config.package_version;
+    exit 0
+  and add_file arg =
+    let uri =
+      try URI.parse_uri arg
+      with Invalid_argument "URI.parse_uri" ->
+        eprintf "Error parsing URI '%s'. Look for error messages printed above.\n" arg;
+        exit 1 in
+    let format = match !format with "auto" -> None | fmt -> Some fmt in
+    files := (uri, format) :: !files
+  and set_domain dom =
+    if !domain <> None then (
+      eprintf (f_"%s: --domain option can only be given once\n") prog;
+      exit 1
+    );
+    domain := Some dom
+  in
+
+  let argspec = [
+    "-a",        Arg.String add_file,       s_"file" ^ " " ^ s_"Add disk image file";
+    "--add",     Arg.String add_file,       s_"file" ^ " " ^ s_"Add disk image file";
+    "-c",        Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI";
+    "--connect", Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI";
+    "--debug-gc", Arg.Set debug_gc,         " " ^ s_"Debug GC and memory allocations (internal)";
+    "-d",        Arg.String set_domain,     s_"domain" ^ " " ^ s_"Set libvirt guest name";
+    "--domain",  Arg.String set_domain,     s_"domain" ^ " " ^ s_"Set libvirt guest name";
+    "-n",        Arg.Set dryrun,            " " ^ s_"Perform a dry run";
+    "--dryrun",  Arg.Set dryrun,            " " ^ s_"Perform a dry run";
+    "--dry-run", Arg.Set dryrun,            " " ^ s_"Perform a dry run";
+    "--format",  Arg.Set_string format,     s_"format" ^ " " ^ s_"Set format (default: auto)";
+    "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
+    "-q",        Arg.Set quiet,             " " ^ s_"Don't print log messages";
+    "--quiet",   Arg.Set quiet,             " " ^ s_"Don't print log messages";
+    "-v",        Arg.Set verbose,           " " ^ s_"Enable debugging messages";
+    "--verbose", Arg.Set verbose,           " " ^ s_"Enable debugging messages";
+    "-V",        Arg.Unit display_version,  " " ^ s_"Display version and exit";
+    "--version", Arg.Unit display_version,  " " ^ s_"Display version and exit";
+    "-x",        Arg.Set trace,             " " ^ s_"Enable tracing of libguestfs calls";
+  ] in
+  let customize_argspec, get_customize_ops =
+    Customize_cmdline.argspec ~prog () in
+  let customize_argspec =
+    List.map (fun (spec, _, _) -> spec) customize_argspec in
+  let argspec = argspec @ customize_argspec in
+  let argspec =
+    let cmp (arg1, _, _) (arg2, _, _) =
+      let arg1 = skip_dashes arg1 and arg2 = skip_dashes arg2 in
+      compare (String.lowercase arg1) (String.lowercase arg2)
+    in
+    List.sort cmp argspec in
+  let argspec = Arg.align argspec in
+  long_options := argspec;
+
+  let anon_fun _ = raise (Arg.Bad (s_"extra parameter on the command line")) in
+  let usage_msg =
+    sprintf (f_"\
+%s: customize a virtual machine
+
+ virt-customize [--options] -d domname
+
+ virt-customize [--options] -a disk.img [-a disk.img ...]
+
+A short summary of the options is given below.  For detailed help please
+read the man page virt-customize(1).
+")
+      prog in
+  Arg.parse argspec anon_fun usage_msg;
+
+  (* Check -a and -d options. *)
+  let files = !files in
+  let domain = !domain in
+  let libvirturi = match !libvirturi with "" -> None | s -> Some s in
+  let add =
+    match files, domain with
+    | [], None ->
+      eprintf (f_"%s: you must give either -a or -d options\n") prog;
+      eprintf (f_"Read virt-customize(1) man page for further information.\n");
+      exit 1
+    | [], Some dom ->
+      fun (g : Guestfs.guestfs) readonly ->
+        let allowuuid = true in
+        let readonlydisk = "ignore" (* ignore CDs, data drives *) in
+        let discard = if readonly then None else Some "besteffort" in
+        ignore (g#add_domain
+                  ~readonly ?discard
+                  ?libvirturi ~allowuuid ~readonlydisk
+                  dom)
+    | _, Some _ ->
+      eprintf (f_"%s: you cannot give -a and -d options together\n") prog;
+      eprintf (f_"Read virt-customize(1) man page for further information.\n");
+      exit 1
+    | files, None ->
+      fun g readonly ->
+        List.iter (
+          fun (uri, format) ->
+            let { URI.path = path; protocol = protocol;
+                  server = server; username = username } = uri in
+            let discard = if readonly then None else Some "besteffort" in
+            g#add_drive
+              ~readonly ?discard
+              ?format ~protocol ?server ?username
+              path
+        ) files
+  in
+
+  (* Dereference the rest of the args. *)
+  let debug_gc = !debug_gc in
+  let dryrun = !dryrun in
+  let quiet = !quiet in
+  let trace = !trace in
+  let verbose = !verbose in
+
+  let ops = get_customize_ops () in
+
+  let msg fs = make_message_function ~quiet fs in
+
+  msg (f_"Examining the guest ...");
+
+  (* Connect to libguestfs. *)
+  let g = new G.guestfs () in
+  if trace then g#set_trace true;
+  if verbose then g#set_verbose true;
+  add g dryrun;
+  g#launch ();
+
+  (* Inspection. *)
+  (match Array.to_list (g#inspect_os ()) with
+  | [] ->
+    eprintf (f_"%s: no operating systems were found in the guest image\n") prog;
+    exit 1
+  | roots ->
+    List.iter (
+      fun root ->
+        (* Mount up the disks, like guestfish -i.
+         * See [ocaml/examples/inspect_vm.ml].
+         *)
+        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 Guestfs.Error msg -> eprintf (f_"%s (ignored)\n") msg
+        ) mps;
+
+        (* Do the customization. *)
+        Customize_run.run ~prog ~debug:verbose ~quiet g root ops;
+
+        g#umount_all ();
+    ) roots;
+  );
+
+  g#shutdown ();
+  g#close ();
+
+  if debug_gc then
+    Gc.compact ()
+
+(* Finished. *)
+let () =
+  (try main ()
+   with
+   | Failure msg ->                     (* from failwith/failwithf *)
+     eprintf (f_"%s: %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 ->
+     eprintf (f_"%s: exception: %s\n") prog (Printexc.to_string exn);
+     exit 1
+  );
+
+  exit 0
diff --git a/customize/test-virt-customize.sh b/customize/test-virt-customize.sh
new file mode 100755
index 0000000..877e8d3
--- /dev/null
+++ b/customize/test-virt-customize.sh
@@ -0,0 +1,32 @@
+#!/bin/bash -
+# libguestfs virt-customize test script
+# Copyright (C) 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.
+
+export LANG=C
+set -e
+
+# virt-customize with the -n option doesn't modify the guest.  It ought
+# to be able to customize any of our Linux-like test guests.
+
+for f in ../tests/guests/{debian,fedora,ubuntu}.img; do
+    # Ignore zero-sized windows.img if ntfs-3g is not installed.
+    if [ -s "$f" ]; then
+	$VG ./virt-customize -n -a $f \
+            --write /etc/motd:HELLO \
+            --delete /etc/motd
+    fi
+done
diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod
new file mode 100644
index 0000000..9c7f0fd
--- /dev/null
+++ b/customize/virt-customize.pod
@@ -0,0 +1,156 @@
+=head1 NAME
+
+virt-customize - Customize a virtual machine
+
+=head1 SYNOPSIS
+
+ virt-customize [--options] -d domname
+__CUSTOMIZE_SYNOPSIS__
+
+ virt-customize [--options] -a disk.img [-a disk.img ...]
+__CUSTOMIZE_SYNOPSIS__
+
+=head1 DESCRIPTION
+
+Virt-customize can customize a virtual machine (disk image) by
+installing packages, editing configuration files, and so on.
+
+Virt-customize modifies the guest or disk image I<in place>.  The
+guest must be shut down.  If you want to preserve the existing
+contents of the guest, I<you must snapshot, copy or clone the disk first>.
+
+You do I<not> need to run virt-customize as root.  In fact we'd
+generally recommend that you don't.
+
+Related tools include: L<virt-sysprep(1)> and L<virt-builder(1)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--help>
+
+Display brief help.
+
+=item B<-a> file
+
+=item B<--add> file
+
+Add I<file> which should be a disk image from a virtual machine.
+
+The format of the disk image is auto-detected.  To override this and
+force a particular format use the I<--format> option.
+
+=item B<-a> URI
+
+=item B<--add> URI
+
+Add a remote disk.  The URI format is compatible with guestfish.
+See L<guestfish(1)/ADDING REMOTE STORAGE>.
+
+=item B<-c> URI
+
+=item B<--connect> URI
+
+If using libvirt, connect to the given I<URI>.  If omitted, then we
+connect to the default libvirt hypervisor.
+
+If you specify guest block devices directly (I<-a>), then libvirt is
+not used at all.
+
+=item B<-d> guest
+
+=item B<--domain> guest
+
+Add all the disks from the named libvirt guest.  Domain UUIDs can be
+used instead of names.
+
+=item B<-n>
+
+=item B<--dry-run>
+
+Perform a read-only "dry run" on the guest.  This runs the sysprep
+operation, but throws away any changes to the disk at the end.
+
+=item B<--format> raw|qcow2|..
+
+=item B<--format> auto
+
+The default for the I<-a> option is to auto-detect the format of the
+disk image.  Using this forces the disk format for I<-a> options which
+follow on the command line.  Using I<--format auto> switches back to
+auto-detection for subsequent I<-a> options.
+
+For example:
+
+ virt-customize --format raw -a disk.img
+
+forces raw format (no auto-detection) for C<disk.img>.
+
+ virt-customize --format raw -a disk.img --format auto -a another.img
+
+forces raw format (no auto-detection) for C<disk.img> and reverts to
+auto-detection for C<another.img>.
+
+If you have untrusted raw-format guest disk images, you should use
+this option to specify the disk format.  This avoids a possible
+security problem with malicious guests (CVE-2010-3851).
+
+=item B<-q>
+
+=item B<--quiet>
+
+Don't print log messages.
+
+To enable detailed logging of individual file operations, use I<-x>.
+
+=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
+
+=head2 Customization options
+
+__CUSTOMIZE_OPTIONS__
+
+=head1 EXIT STATUS
+
+This program returns 0 on success, or 1 if there was an error.
+
+=head1 SEE ALSO
+
+L<guestfs(3)>,
+L<guestfish(1)>,
+L<virt-builder(1)>,
+L<virt-clone(1)>,
+L<virt-rescue(1)>,
+L<virt-resize(1)>,
+L<virt-sparsify(1)>,
+L<virt-sysprep(1)>,
+L<virsh(1)>,
+L<lvcreate(8)>,
+L<qemu-img(1)>,
+L<scrub(1)>,
+L<http://libguestfs.org/>,
+L<http://libvirt.org/>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones L<http://people.redhat.com/~rjones/>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2011-2014 Red Hat Inc.
diff --git a/fish/guestfish.pod b/fish/guestfish.pod
index a53ef92..25279fb 100644
--- a/fish/guestfish.pod
+++ b/fish/guestfish.pod
@@ -1607,6 +1607,7 @@ L<virt-builder(1)>,
 L<virt-cat(1)>,
 L<virt-copy-in(1)>,
 L<virt-copy-out(1)>,
+L<virt-customize(1)>,
 L<virt-df(1)>,
 L<virt-diff(1)>,
 L<virt-edit(1)>,
diff --git a/po-docs/ja/Makefile.am b/po-docs/ja/Makefile.am
index f17be96..0b9df84 100644
--- a/po-docs/ja/Makefile.am
+++ b/po-docs/ja/Makefile.am
@@ -116,6 +116,15 @@ virt-builder.1: virt-builder.pod customize-synopsis.pod customize-options.pod
 	  --insert $(srcdir)/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
 	  $<
 
+virt-customize.1: virt-customize.pod customize-synopsis.pod customize-options.pod
+	$(PODWRAPPER) \
+	  --no-strict-checks \
+	  --man $@ \
+	  --license GPLv2+ \
+	  --insert $(srcdir)/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
+	  --insert $(srcdir)/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
+	  $<
+
 virt-sysprep.1: virt-sysprep.pod sysprep-extra-options.pod sysprep-operations.pod
 	$(PODWRAPPER) \
 	  --no-strict-checks \
diff --git a/po-docs/podfiles b/po-docs/podfiles
index d863554..2094601 100644
--- a/po-docs/podfiles
+++ b/po-docs/podfiles
@@ -5,6 +5,9 @@
 ../cat/virt-cat.pod
 ../cat/virt-filesystems.pod
 ../cat/virt-ls.pod
+../customize/customize-options.pod
+../customize/customize-synopsis.pod
+../customize/virt-customize.pod
 ../daemon/guestfsd.pod
 ../df/virt-df.pod
 ../diff/virt-diff.pod
diff --git a/po-docs/uk/Makefile.am b/po-docs/uk/Makefile.am
index f17be96..0b9df84 100644
--- a/po-docs/uk/Makefile.am
+++ b/po-docs/uk/Makefile.am
@@ -116,6 +116,15 @@ virt-builder.1: virt-builder.pod customize-synopsis.pod customize-options.pod
 	  --insert $(srcdir)/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
 	  $<
 
+virt-customize.1: virt-customize.pod customize-synopsis.pod customize-options.pod
+	$(PODWRAPPER) \
+	  --no-strict-checks \
+	  --man $@ \
+	  --license GPLv2+ \
+	  --insert $(srcdir)/customize-synopsis.pod:__CUSTOMIZE_SYNOPSIS__ \
+	  --insert $(srcdir)/customize-options.pod:__CUSTOMIZE_OPTIONS__ \
+	  $<
+
 virt-sysprep.1: virt-sysprep.pod sysprep-extra-options.pod sysprep-operations.pod
 	$(PODWRAPPER) \
 	  --no-strict-checks \
diff --git a/src/guestfs.pod b/src/guestfs.pod
index e6e91f4..a81cc6d 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -4274,7 +4274,7 @@ Outside contributions, experimental parts.
 
 =item C<customize>
 
-virt-customize mini-library.
+L<virt-customize(1)> command and documentation.
 
 =item C<daemon>
 
@@ -4735,6 +4735,7 @@ L<virt-builder(1)>,
 L<virt-cat(1)>,
 L<virt-copy-in(1)>,
 L<virt-copy-out(1)>,
+L<virt-customize(1)>,
 L<virt-df(1)>,
 L<virt-diff(1)>,
 L<virt-edit(1)>,
diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod
index aa570a5..b59c796 100644
--- a/sysprep/virt-sysprep.pod
+++ b/sysprep/virt-sysprep.pod
@@ -528,6 +528,7 @@ L<guestfs(3)>,
 L<guestfish(1)>,
 L<virt-builder(1)>,
 L<virt-clone(1)>,
+L<virt-customize(1)>,
 L<virt-rescue(1)>,
 L<virt-resize(1)>,
 L<virt-sparsify(1)>,

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list