From: Richard W.M. Jones Date: Fri, 7 Oct 2011 18:22:11 +0000 (+0100) Subject: New tool: virt-sysprep: system preparation for guests. X-Git-Tag: 1.13.19~1 X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=commitdiff_plain;h=1e35941f62bddafd6b88270b22b3afe4a5d37baa New tool: virt-sysprep: system preparation for guests. --- diff --git a/.gitignore b/.gitignore index 4f1438f..8980fd0 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,9 @@ cat/virt-ls cat/virt-ls.1 ChangeLog *.class +clone/stamp-virt-sysprep.pod +clone/virt-sysprep +clone/virt-sysprep.1 *.cma *.cmi *.cmo @@ -151,6 +154,7 @@ html/virt-make-fs.1.html html/virt-rescue.1.html html/virt-resize.1.html html/virt-sparsify.1.html +html/virt-sysprep.1.html html/virt-tar.1.html html/virt-tar-in.1.html html/virt-tar-out.1.html diff --git a/Makefile.am b/Makefile.am index 308a1f3..3d44c76 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,9 @@ SUBDIRS += fish # virt-tools in C. SUBDIRS += align cat df edit inspector rescue +# virt-tools in shell. +SUBDIRS += clone + # Language bindings. if HAVE_PERL SUBDIRS += perl perl/examples @@ -160,6 +163,7 @@ HTMLFILES = \ html/virt-rescue.1.html \ html/virt-resize.1.html \ html/virt-sparsify.1.html \ + html/virt-sysprep.1.html \ html/virt-tar.1.html \ html/virt-tar-in.1.html \ html/virt-tar-out.1.html \ diff --git a/clone/Makefile.am b/clone/Makefile.am new file mode 100644 index 0000000..20e1d52 --- /dev/null +++ b/clone/Makefile.am @@ -0,0 +1,51 @@ +# libguestfs cloning tools +# Copyright (C) 2011 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. + +include $(top_srcdir)/subdir-rules.mk + +EXTRA_DIST = \ + test-virt-sysprep.sh \ + virt-sysprep.pod + +CLEANFILES = stamp-virt-sysprep.pod + +bin_SCRIPTS = virt-sysprep + +# Manual pages and HTML files for the website. +man_MANS = virt-sysprep.1 +noinst_DATA = $(top_builddir)/html/virt-sysprep.1.html + +virt-sysprep.1 $(top_builddir)/html/virt-sysprep.1.html: stamp-virt-sysprep.pod + +stamp-virt-sysprep.pod: virt-sysprep.pod + $(top_builddir)/podwrapper.sh \ + --man virt-sysprep.1 \ + --html $(top_builddir)/html/virt-sysprep.1.html \ + $< + touch $@ + +# Tests. + +random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null) + +TESTS_ENVIRONMENT = \ + MALLOC_PERTURB_=$(random_val) \ + LD_LIBRARY_PATH=$(top_builddir)/src/.libs \ + LIBGUESTFS_PATH=$(top_builddir)/appliance \ + TMPDIR=$(top_builddir) + +TESTS = test-virt-sysprep.sh diff --git a/clone/test-virt-sysprep.sh b/clone/test-virt-sysprep.sh new file mode 100755 index 0000000..897afb7 --- /dev/null +++ b/clone/test-virt-sysprep.sh @@ -0,0 +1,35 @@ +#!/bin/bash - +# libguestfs virt-sysprep test script +# Copyright (C) 2011 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. + +export LANG=C +set -e + +rm -f test.img guestfish + +qemu-img create -f qcow2 -o backing_file=../images/fedora.img test.img + +cat <<'EOF' > guestfish +#!/bin/sh - +../run ../fish/guestfish "$@" +EOF +chmod +x guestfish +PATH=.:$PATH + +./virt-sysprep -a test.img + +rm -f test.img guestfish diff --git a/clone/virt-sysprep.in b/clone/virt-sysprep.in new file mode 100644 index 0000000..b73acfb --- /dev/null +++ b/clone/virt-sysprep.in @@ -0,0 +1,289 @@ +#!/bin/bash - +# @configure_input@ +# libguestfs virt-sysprep tool +# Copyright (C) 2011 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. + +unset CDPATH +program="virt-sysprep" +version="@PACKAGE_VERSION@" + +TEMP=`getopt \ + -o a:c:d:vVx \ + --long help,add:,connect:,domain:,enable:,format::,hostname:,list-operations,verbose,version \ + -n $program -- "$@"` +if [ $? != 0 ]; then + echo "$program: problem parsing the command line arguments" + exit 1 +fi +eval set -- "$TEMP" + +# This array accumulates the arguments we pass through to guestfish. +declare -a guestfish +guestfish[0]="guestfish" +guestfish[1]="--rw" +guestfish[2]="--listen" +guestfish[3]="-i" +i=4 + +verbose= +add_params=0 +enable= +hostname_param=localhost.localdomain + +usage () +{ + echo "Usage:" + echo " $program [--options] -d domname" + echo " $program [--options] -a disk.img [-a disk.img ...]" + echo + echo "Read $program(1) man page for more information." + echo + echo "NOTE: $program modifies the guest or disk image *in place*." + exit $1 +} + +while true; do + case "$1" in + -a|--add) + guestfish[i++]="-a" + guestfish[i++]="$2" + ((add_params++)) + shift 2;; + -c|--connect) + guestfish[i++]="-c" + guestfish[i++]="$2" + shift 2;; + -d|--domain) + guestfish[i++]="-d" + guestfish[i++]="$2" + ((add_params++)) + shift 2;; + --enable) + if [ -n "$enable" ]; then + echo "error: --enable option can only be given once" + exit 1 + fi + enable="$2" + shift 2;; + --format) + if [ -n "$2" ]; then + guestfish[i++]="--format=$2" + else + guestfish[i++]="--format" + fi + shift 2;; + --help) + usage 0;; + --hostname) + hostname_param="$2" + shift 2;; + --list-operations) + enable=list + shift;; + -v|--verbose) + guestfish[i++]="-v" + verbose=yes + shift;; + -V|--version) + echo "$program $version" + exit 0;; + -x) + guestfish[i++]="-x" + shift;; + --) + shift + break;; + *) + echo "Internal error!" + exit 1;; + esac +done + +# Different sysprep operations that can be enabled. Default is to +# enable all of these, although some of them are only done on certain +# guest types (see details below). +if [ -z "$enable" ]; then + hostname=yes + net_hwaddr=yes + ssh_hostkeys=yes + udev_persistent_net=yes +elif [ "$enable" = "list" ]; then + echo "hostname" + echo "net-hwaddr" + echo "ssh-hostkeys" + echo "udev-persistent-net" + exit 0 +else + for opt in $(echo "$enable" | sed 's/,/ /g'); do + case "$opt" in + hostname) hostname=yes ;; + net-hwaddr) net_hwaddr=yes ;; + ssh-hostkeys) ssh_hostkeys=yes ;; + udev-persistent-net) udev_persistent_net=yes ;; + *) + echo "error: unknown --enable feature: $opt" + exit 1 + esac + done +fi + +# Make sure there were no extra parameters on the command line. +if [ $# -gt 0 ]; then + echo "error: $program: extra parameters on the command line" + echo + usage 1 +fi + +# Did the user specify at least one -a or -d option? +if [ $add_params -eq 0 ]; then + echo "error: $program: you need at least one -a or -d option" + echo + usage 1 +fi + +# end of command line parsing +#---------------------------------------------------------------------- + +set -e + +if [ "$verbose" = "yes" ]; then + echo command: "${guestfish[@]}" +fi + +# Create a temporary directory for general purpose use during operations. +tmpdir="$(mktemp -d)" + +# Call guestfish. +GUESTFISH_PID= +eval $("${guestfish[@]}") +if [ -z "$GUESTFISH_PID" ]; then + echo "$program: guestfish didn't start up, see error messages above" + exit 1 +fi + +cleanup () +{ + kill $GUESTFISH_PID >/dev/null 2>&1 ||: + rm -rf "$tmpdir" ||: +} +trap cleanup EXIT + +# Launch back-end, inspect for operating systems, and get the guest +# root disk. +root=$(guestfish --remote inspect-get-roots) + +if [ "$root" = "" ]; then + echo "$program: no operating system was found on this disk" + exit 1 +fi + +if [ "$verbose" = "yes" ]; then + echo root: "$root" +fi + +# Get the guest type. +type="$(guestfish --remote -- -inspect-get-type $root)" + +if [ "$type" = "linux" ]; then + distro="$(guestfish --remote -- -inspect-get-distro $root)" +fi + +if [ "$type" = "windows" ]; then + systemroot="$(guestfish --remote -- -inspect-get-windows-systemroot $root)" +fi + +#---------------------------------------------------------------------- +# Useful functions. + +# erase_line filename regex +# +# Erase line(s) in a file that match the given regex. +erase_line () +{ + guestfish --remote -- download "$1" "$tmpdir/file" + sed "/$2/d" < "$tmpdir/file" > "$tmpdir/file.1" + guestfish --remote -- upload "$tmpdir/file.1" "$1" +} + +# rm_files wildcard +# +# Remove files. Doesn't fail if no files exist. Note the wildcard +# parameter cannot contain spaces or characters that need special +# quoting. +rm_files () +{ + files=$(guestfish --remote -- glob-expand "$1") + for f in $files; do + guestfish --remote -- rm "$f" + done +} + +# rm_file filename +# +# Remove a single file. No error if the file doesn't exist or is not +# a file. +rm_file () +{ + t=$(guestfish --remote -- is-file "$1") + if [ "$t" = "true" ]; then + guestfish --remote -- rm "$1" + fi +} + +#---------------------------------------------------------------------- +# The sysprep operations. + +if [ "$hostname" = "yes" ]; then + case "$type/$distro" in + linux/fedora) + guestfish --remote -- \ + download /etc/sysconfig/network "$tmpdir/network" + echo "HOSTNAME=$hostname_param" > "$tmpdir/network.1" + sed '/^HOSTNAME=/d' < "$tmpdir/network" >> "$tmpdir/network.1" + guestfish --remote -- \ + upload "$tmpdir/network.1" /etc/sysconfig/network ;; + linux/debian|linux/ubuntu) + guestfish --remote -- write /etc/hostname "$hostname_param" + esac +fi + +if [ "$net_hwaddr" = "yes" ]; then + case "$type/$distro" in + linux/fedora) + # XXX these filenames can have spaces and untrusted chars in them! + files=$(guestfish --remote -- glob-expand '/etc/sysconfig/network-scripts/ifcfg-*') + for f in $files; do + erase_line "$f" "^HWADDR=" + done + esac +fi + +if [ "$ssh_hostkeys" = "yes" -a "$type" != "windows" ]; then + rm_files "/etc/ssh/*_host_*" +fi + +if [ "$udev_persistent_net" = "yes" -a "$type" = "linux" ]; then + rm_file /etc/udev/rules.d/70-persistent-net.rules +fi + +# Clean up and close down. + +guestfish --remote umount-all +guestfish --remote sync +guestfish --remote exit + +exit 0 diff --git a/clone/virt-sysprep.pod b/clone/virt-sysprep.pod new file mode 100755 index 0000000..cc8e44f --- /dev/null +++ b/clone/virt-sysprep.pod @@ -0,0 +1,404 @@ +=encoding utf8 + +=head1 NAME + +virt-sysprep - Reset or unconfigure a virtual machine so clones can be made + +=head1 SYNOPSIS + + virt-sysprep [--options] -d domname + + virt-sysprep [--options] -a disk.img [-a disk.img ...] + +=head1 DESCRIPTION + +Virt-sysprep "resets" or "unconfigures" a virtual machine so that +clones can be made from it. Steps in this process include removing +SSH host keys, removing persistent network MAC configuration, and +removing user accounts. Each step can be enabled or disabled as +required. + +Virt-sysprep is a simple shell script, allowing easy inspection or +customization by the system administrator. + +Virt-sysprep modifies the guest or disk image I. The guest +must be shut down. If you want to preserve the existing contents of +the guest, you I. +See L below. + +"Sysprep" stands for "system preparation" tool. The name comes from +the Microsoft program C which is used to unconfigure +Windows machines in preparation for cloning them. Having said that, +virt-sysprep does I currently work on Microsoft Windows guests. +We plan to support Windows sysprepping in a future version, and we +already have code to do it. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Display brief help. + +=item B<-a> file + +=item B<--add> file + +Add I 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<-c> URI + +=item B<--connect> URI + +If using libvirt, connect to the given I. 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<--enable=...> + +Choose which sysprep operations to perform. Give a comma-separated +list of operations, for example: + + --enable=ssh-hostkeys,udev-persistent-net + +would enable ONLY C and C operations. + +If the I<--enable> option is not given, then we default to trying all +possible sysprep operations. But some sysprep operations are skipped +for some guest types. + +Use I<--list-operations> to list operations supported by a particular +version of virt-sysprep. + +See L below for a list and an explanation of each +operation. + +=item B<--format=raw|qcow2|..> + +=item B<--format> + +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> with no argument +switches back to auto-detection for subsequent I<-a> options. + +For example: + + virt-sysprep --format=raw -a disk.img + +forces raw format (no auto-detection) for C. + + virt-sysprep --format=raw -a disk.img --format -a another.img + +forces raw format (no auto-detection) for C and reverts to +auto-detection for C. + +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<--hostname> newhostname + +Change the hostname. See the L operation below. +If not given, defaults to C. + +=item B<--list-operations> + +List the operations supported by the virt-sysprep program. + +=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 OPERATIONS + +If the I<--enable> option is I given, then all sysprep operations +in the list below are enabled, although some are skipped depending on +the type of guest. + +Operations can be individually enabled using the I<--enable> option. +Use a comma-separated list, for example: + + virt-sysprep --enable=ssh-hostkeys,udev-persistent-net [etc..] + +To list the operations supported by the current version of +virt-sysprep, use I<--list-operations>. + +=head2 hostname + +This changes the hostname of the guest to the value given in the +I<--hostname> parameter. + +If the I<--hostname> parameter is not given, then the hostname is +changed to C. + +=head2 net-hwaddr + +Remove HWADDR (hard-coded MAC address) configuration. For Fedora and +Red Hat Enterprise Linux, this is removed from C files. + +=head2 ssh-hostkeys + +This erases the SSH host keys in the guest. + +The SSH host keys are regenerated (differently) next time the guest is +booted. + +If, after cloning, the guest gets the same IP address, ssh will give +you a stark warning about the host key changing: + + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! + +=head2 udev-persistent-net + +This erases udev persistent net rules which map the guest's existing +MAC address to a fixed ethernet device (eg. eth0). + +After a guest is cloned, the MAC address usually changes. Since the +old MAC address occupies the old name (eg. eth0), this means the fresh +MAC address is assigned to a new name (eg. eth1) and this is usually +undesirable. Erasing the udev persistent net rules avoids this. + +=head1 COPYING AND CLONING + +Virt-sysprep can be used as part of a process of cloning guests, or to +prepare a template from which guests can be cloned. There are many +different ways to achieve this using the virt tools, and this section +is just an introduction. + +A virtual machine (when switched off) consists of two parts: + +=over 4 + +=item I + +The configuration or description of the guest. eg. The libvirt +XML (see C), the running configuration of the guest, +or another external format like OVF. + +Some configuration items that might need to be changed: + +=over 4 + +=item * + +name + +=item * + +UUID + +=item * + +path to block device(s) + +=item * + +network card MAC address + +=back + +=item I + +One or more hard disk images, themselves containing files, +directories, applications, kernels, configuration, etc. + +Some things inside the block devices that might need to be changed: + +=over 4 + +=item * + +hostname and other net configuration + +=item * + +UUID + +=item * + +SSH host keys + +=item * + +Windows unique security ID (SID) + +=item * + +Puppet registration + +=back + +=back + +=head2 COPYING THE BLOCK DEVICE + +Starting with an original guest, you probably wish to copy the guest +block device and its configuration to make a template. Then once you +are happy with the template, you will want to make many clones from +it. + + virt-sysprep + | + v + original guest --------> template ----------> + \------> cloned + \-----> guests + \----> + +You can, of course, just copy the block device on the host using +L or L. + + dd dd + original guest --------> template ----------> + \------> cloned + \-----> guests + \----> + +There are some smarter (and faster) ways too: + +=over 4 + +=item * + + snapshot + template ----------> + \------> cloned + \-----> guests + \----> + +Use the block device as a backing file and create a snapshot on top +for each guest. The advantage is that you don't need to copy the +block device (very fast) and only changes are stored (less storage +required). + +Note that writing to the backing file once you have created guests on +top of it is not possible: you will corrupt the guests. + +Tools that can do this include: +L (with the I option), +L (I<--snapshot> option). Some filesystems (such as +btrfs) and most Network Attached Storage devices can also create cheap +snapshots from files or LUNs. + +=item * + +Get your NAS to snapshot and/or duplicate the LUN. + +=item * + +Prepare your template using L. See below. + +=back + +=head2 VIRT-CLONE + +A separate tool, L, can be used to duplicate the block +device and/or modify the external libvirt configuration of a guest. +It will reset the name, UUID and MAC address of the guest in the +libvirt XML. + +L does not use libguestfs and cannot look inside the +disk image. This was the original motivation to write virt-sysprep. + +=head2 SPARSIFY + + virt-sparsify + original guest --------> template + +L can be used to make the cloning template smaller, +making it easier to compress and/or faster to copy. + +Notice that since virt-sparsify also copies the image, you can use it +to make the initial copy (instead of C
). + +=head2 RESIZE + + virt-resize + template ----------> + \------> cloned + \-----> guests + \----> + +If you want to give people cloned guests, but let them pick the size +of the guest themselves (eg. depending on how much they are prepared +to pay for disk space), then instead of copying the template, you can +run L. Virt-resize performs a copy and resize, and +thus is ideal for cloning guests from a template. + +=head1 SHELL QUOTING + +Libvirt guest names can contain arbitrary characters, some of which +have meaning to the shell such as C<#> and space. You may need to +quote or escape these characters on the command line. See the shell +manual page L for details. + +=head1 EXIT STATUS + +This program returns 0 on success, or 1 if there was an error. + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L. + +=head1 AUTHOR + +Richard W.M. Jones L + +=head1 COPYRIGHT + +Copyright (C) 2011 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. diff --git a/configure.ac b/configure.ac index ec02ff1..a2ea880 100644 --- a/configure.ac +++ b/configure.ac @@ -936,6 +936,8 @@ AC_SUBST([LIBTOOL]) dnl Produce output files. AC_CONFIG_HEADERS([config.h]) dnl http://www.mail-archive.com/automake@gnu.org/msg10204.html +AC_CONFIG_FILES([clone/virt-sysprep], + [chmod +x clone/virt-sysprep]) AC_CONFIG_FILES([podwrapper.sh], [chmod +x podwrapper.sh]) AC_CONFIG_FILES([run], @@ -946,6 +948,7 @@ AC_CONFIG_FILES([Makefile capitests/Makefile cat/Makefile caution/Makefile + clone/Makefile csharp/Makefile daemon/Makefile debian/changelog diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 696d3b3..022e03e 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -1283,6 +1283,7 @@ L, L, L, L, +L, L, L, L, diff --git a/po-docs/ja/Makefile.am b/po-docs/ja/Makefile.am index d03fdb3..552d4fb 100644 --- a/po-docs/ja/Makefile.am +++ b/po-docs/ja/Makefile.am @@ -42,7 +42,8 @@ MANPAGES = \ virt-ls.1 \ virt-rescue.1 \ virt-resize.1 \ - virt-sparsify.1 + virt-sparsify.1 \ + virt-sysprep.1 # Ship the POD files and the translated manpages in the tarball. This # just simplifies building from the tarball, at a small cost in extra diff --git a/po-docs/podfiles b/po-docs/podfiles index 48732e7..c4e4d6b 100644 --- a/po-docs/podfiles +++ b/po-docs/podfiles @@ -2,6 +2,7 @@ ../cat/virt-cat.pod ../cat/virt-filesystems.pod ../cat/virt-ls.pod +../clone/virt-sysprep.pod ../df/virt-df.pod ../edit/virt-edit.pod ../erlang/examples/guestfs-erlang.pod diff --git a/po-docs/uk/Makefile.am b/po-docs/uk/Makefile.am index d03fdb3..552d4fb 100644 --- a/po-docs/uk/Makefile.am +++ b/po-docs/uk/Makefile.am @@ -42,7 +42,8 @@ MANPAGES = \ virt-ls.1 \ virt-rescue.1 \ virt-resize.1 \ - virt-sparsify.1 + virt-sparsify.1 \ + virt-sysprep.1 # Ship the POD files and the translated manpages in the tarball. This # just simplifies building from the tarball, at a small cost in extra diff --git a/src/guestfs.pod b/src/guestfs.pod index 25ca56d..1a5abc6 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -2845,6 +2845,11 @@ and documentation. Safety and liveness tests of components that libguestfs depends upon (not of libguestfs itself). Mainly this is for qemu and the kernel. +=item C + +Tools for cloning virtual machines. Currently contains +L command and documentation. + =item C Outside contributions, experimental parts. @@ -3202,6 +3207,7 @@ L, L, L, L, +L, L, L, L,