diff options
Diffstat (limited to 'clone/virt-sysprep.in')
-rw-r--r-- | clone/virt-sysprep.in | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/clone/virt-sysprep.in b/clone/virt-sysprep.in new file mode 100644 index 00000000..b73acfb8 --- /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 |