Clone Xen virtual machine script

I wrote the following script to make identical clones of a Xen virtual machine template. The script will copy the disk image and edit the necessary files of the guest operating system such as /etc/hosts, /etc/sysconfig/network and /etc/sysconfig/network-scripts/ifcfg-eth0. It will replace the hostname and will generate a new MAC address both for the guest OS ifcfg-eth0 file and the guest configuration file which is located under /etc/xen on the host.

Usage:

./xenclone <disk images dir> <disk name> <clone name>
#!/bin/bash
############################################################################
# Copyright (C) 2009  Panagiotis Kritikakos <pkritika@epcc.ed.ac.uk>       #
#                                                                          #
#    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 3 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, see <http://www.gnu.org/licenses/>. #
############################################################################
if [ $UID != "0" ]; then
  echo " You must be root to run the script or run it with sudo"
  exit 1;
fi
if [ $# -lt 3 ]; then
  echo " Usage: ./xenclone <disk images dir> <disk name> <clone name>"
  echo " The script assumes the guest being clone is a Red Hat based system"
  exit 1;
fi
DISKPATH=$1
DISK=$2
CLONE=$3
MOUNTDIR=`mktemp -d`
if [ ! -e $DISKPATH/$DISK.img ]; then
  echo " Primary disk image can't be found."
  exit 1;
fi
clear

TEMPF1=`mktemp`
TEMPF2=`mktemp`
TEMPF3=`mktemp`
TEMPHOSTS=`mktemp`
TEMPNETWORK=`mktemp`
TEMPIFCFG=`mktemp`

echo "Copying ${DISK} to ${CLONE}..."
dd if=$DISKPATH/$DISK.img of=$DISKPATH/$CLONE.img

echo "Mapping the image..."
loopPart=`kpartx -l $DISKPATH/$CLONE.img | awk {'print $1'}`
kpartx -a $DISKPATH/$CLONE.img

echo "Mounting the image..."
mount /dev/mapper/$loopPart $MOUNTDIR

echo "Editing files and creating configuration file for ${CLONE}..."
sed "s/$DISK/$CLONE/g" < $MOUNTDIR/etc/hosts > $TEMPHOSTS
cp -f $TEMPHOSTS $MOUNTDIR/etc/hosts
sed "s/$DISK/$CLONE/g" < $MOUNTDIR/etc/sysconfig/network > $TEMPNETWORK
cp -f $TEMPNETWORK $MOUNTDIR/etc/sysconfig/network

sed "s/$DISK/$CLONE/g" < /etc/xen/$DISK > $TEMPF1
olduuid=`grep uuid $TEMPF1 | awk {'print $3'} |  sed s/'"'*'"'//g`
newuuid=`uuidgen`
sed "s/$olduuid/$newuuid/g" < $TEMPF1 > $TEMPF2
oldmac=`grep mac $TEMPF2 | sed s/vif.*mac=//g | sed s/,.*']'//g`
newmac=`echo $RANDOM | openssl md5 | sed 's/\(..\)/\1:/g' | cut -b1-17`
oldhwaddr=`grep HWADDR $MOUNTDIR/etc/sysconfig/network-scripts/ifcfg-eth0
\ | sed s/HWADDR.*=//g`
sed "s/$oldmac/$newmac/g" < $TEMPF2 > $TEMPF3
cp -f $TEMPF3 /etc/xen/$CLONE
sed "s/$oldhwaddr/$newmac/g" < $MOUNTDIR/etc/sysconfig/network-scripts/ifcfg-eth0
\ > $TEMPIFCFG
cp -f $TEMPIFCFG $MOUNTDIR/etc/sysconfig/network-scripts/ifcfg-eth0

echo "Removing temporary files..."
rm -f $TEMPF1 $TEMPF2 $TEMPF3 $TEMPHOSTS $TEMPNETWORK $TEMPIFCFG

echo "Unmounting the image..."
umount /dev/mapper/$loopPart

echo "Unmapping the image..."
kpartx -d $DISKPATH/$CLONE.img

echo "Cloning of ${DISK} to ${CLONE} finished."
Advertisement

13 thoughts on “Clone Xen virtual machine script

  1. Michael Iatrou

    It’s really great the fact that bash provides us with a simple way to automate mundane, repetitive and error prone processes.

    Since you ‘ve gone into trouble to prepend GPL to your script, which drives me to assume that you don’t consider it a quick hack, you may want to make a few changes, for completeness, security and elegance. Few ideas to start with:

    * Make sure to inform the user that you assume a certain Linux distribution family. You aren’t going to find /etc/sysconfig on a Slackware or a Debian (and many, many others).

    * Check if user has the correct permissions to execute all the script included commands (man 1 id)

    * Use “getopts” to get the needed options: position depended options tend to be erroneous.

    * Use mktemp(1) to create temporary files.

    * Whenever something goes wrong, provide an error indicating exit status (instead of the implied, everything-is-fine 0.)

    * $FOO=foo; echo ${FOO}bar

  2. panoskrt

    Thanks for the well pointed suggestions Michael. I’ve implemented some of those and updated the script.
    As you’ve pointed out, the script is not targeted for wide Linux use. The reason for that is that in the environment is being used all the guests are running Red Hat based distributions.

    And yes, it’s great that there’s the ability of combining various UNIX/Linux tools to make your life easier and more.. secure 🙂

  3. mcswiggity

    The problem he’s having is likely related to this:

    [root@vm2 vm]# kpartx -l /vm/gen1
    loop0p1 : 0 208782 /dev/loop0 63
    loop0p2 : 0 2104515 /dev/loop0 208845
    loop0p3 : 0 39616290 /dev/loop0 2313360

    You’re assuming there’s only one line of output coming back.

  4. panoskrt

    That’s right. One more input parameter can be added, which will be $4 in the current version of the script, and then you’ll need something like this:

    partition=$4
    loopPart=`kpartx -l $DISKPATH/$CLONE.img | grep p${partition} | awk {‘print $1’}`

    This assumes that you know which is the root partition…

  5. Pingback: Preparativi per i primi test con Oracle 11gR2 « Oracle and other

  6. eap

    Hello
    I found your script useful, but I noticed a problem with the MAC address creator. It looks like this could result in multicast addresses being generated, as there is no protection from using a “1” in the last bit of the first octet.
    I’m currently using this python script, which also uses the official Xen OUI – this would make it easier to indentify a virtual vs. physical machine if there was a problem on the network. I found the script on the web, but do not know the author.

    #! /usr/bin/python
    # macgen.py script generates a MAC address for Xen guests
    #
    import random
    mac = [ 0x00, 0x16, 0x3e,
    random.randint(0x00, 0x7f),
    random.randint(0x00, 0xff),
    random.randint(0x00, 0xff) ]
    print ‘:’.join(map(lambda x: “%02x” % x, mac))

    Thanks
    -e

  7. eap

    Here are some more comments:

    You could much get better performance on the “dd” copy by specifying a larger blocksize, say “bs=1M” or something like this.

    You also assume a regular file for disk, but people should probably being using a LVM volume, i.e. “/dev/VolGroup00/lvxen1”.

    I also added some logic to increment the VNC display number in the guest config file (i.e. vncdisplay=xx).

  8. panoskrt

    Thanks for these comments.
    The assumption of a regular file for a disk image was made only because that’s what I was using at the time I needed the script. Thanks again!

  9. No I don’t. I think you’d need something more than a script for live cloning, probably one of the tools that supports such operations, rather than a hacky bash script.

  10. Where did you actually acquire the recommendations to create ““Clone
    Xen virtual machine script | : | : vortex of false deceit : | :” eatwellbehealthy ?

    Thanks for the post ,Jenni

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s