Updated: November 5, 2012
No, this is not another generic howto on using virt-clone. While virt-clone is a rather useful tool for creating duplicates of your virtual machines, in its current configuration, it will only assign unique ID and MAC address to your cloned system, forcing you to perform additional tweaks and customizations once the the clone boots. This means you might have to meddle quite a bit, which is not what you want.
All right, I will show you a different way of creating identical copies of your virtual machines in KVM technology, with unique per-host information so that any number of duplicates become individual hosts on your network. In other words, install once and then create as many instances of the guest as you need, each with its own hostname, MAC address, IP address and such. Fully scriptable and all that. So please follow me.
The less efficient way
Let's briefly discuss virt-clone for a moment. It's not a bad utility, but its use is not standard across distributions. Some ship both the GUI component, as part of the Virtual Machine Manager, others also offer the command line tool. In both cases, the clones will only be assigned new unique ID and MAC address, but no other information. The configuration files will be stored under /etc/libvirt/qemu.
Here's an example:
Now, we do not want this. Not perfect.
The cloning + tools of the trade
Now, the right way. You will need very few tools to achieve the desired result; in fact, just one tool, and it's called kpartx, a utility that can create device maps from partition tables. Specifically here, you can use it to create partition mappings for your guest machines by querying the virtual disks. We will demonstrate using Linux, but most UNIX-based systems will work.
So what we need to do is read the partition table from the virtual disk. First, we must create a copy of the virtual disk, as each machine will have its own. This is the one slow step of the clone procedure, and it will depend on how big your files are and how slow the disks. In general, you will need a few minutes to copy a typical 20GB disk file.
cp <old disk file> <new disk file>
Now, the partition table:
kpartx -a <virtual disk file>
This will generate some output. In fact, you will see a separate mapper for each individual partition contained inside the virtual machine. For instance, if you have / and /home, you will have two mappers.
kpartx -av /kvm/disk.raw
add map loop0p1 (253:0): 0 4206592 linear /dev/loop0 2048
add map loop0p2 (253:1): 0 79677440 linear /dev/loop0 4208640
Now, it's the matter of mounting the relevant device and making per-host changes:
mount /dev/mapper/<relevant partition loopback> /mountpoint
mount /dev/mapper/loop0p1 /mnt
Unique host changes
Now your virtual machine most likely requires the following changes:
And depending whether you're using Debian or RedHat/SUSE, network configurations, although these might not be necessary if you're using DHCP. However, if you are using static IP addresses, this is a must:
Other changes might be necessary, but there are the basic ones. Once you save the changes, umount. Your next step is to edit the KVM configuration file for the new clone. The XML files are normally kept in /etc/kvm/vm or /etc/libvirt/qemu directories, if the machines were autocreated using Virtual Machine Manager.
XML file changes
First, create a copy of the template configuration.
You will now need to edit the unique ID, name and MAC address of your domain. Like before, you will have to apply some kind of uniqueness logic, probably using grep, awk and inline search & replace with sed, plus a healthy dose of regular expressions when required, so that you can fully script your procedure. Naturally, you will also need to point the hard disk directive to the correct file.
As an example, here's the set of commands you might need:
sed -i -e 's/\<uuid\>.*/\<\/uuid\>/uuid\>dedoimedo\<\/uuid/'
And with grep to make sure it works:
sed -i -e 's/\<uuid\>.*/\<\/uuid\>/uuid\>dedoimedo\<\/uuid/'
file.xml. | grep dedoimedo
Putting it all together
Therefore, a complete clone script would be - I'm giving a typical would be RedHat example, you can make your own adjustments. Likewise, some parts of the script will require your own logic, like deciding how to parse partitions output. Moreover, you might need some extra work in parsing the output of XML files and stripping opening and closing brackets, quotation marks and other characters.
# suspend template OS while cloning
virsh suspend <domain>
cp <old disk> <new disk>
virsh resume <domain>
kpartx -a <new disk>
# some logic to read relevant partitions
mount <desired partition> <mount point>
# some logic to parse contents of host-unique files
sed -i -e 's/old hostname line/new hostname line/' /etc/HOSTNAME
sed -i -e 's/old hostname line/new hostname line/' /etc/hosts
sed -i -e 's/old IP config/new IP config/' /etc/sysconfig/network/ifcfg-eth0
umount <mount point>
cp /etc/kvm/vm/old.xml /etc/kvm/vm/new.xml
# some logic to create new uuid, name, mac, etc
# some logic to parse XML files correctly
sed -i -e 's/old uuid/new uuid/' /etc/kvm/vm/new.xml
sed -i -e 's/old name/new name/' /etc/kvm/vm/new.xml
sed -i -e 's/old mac/new mac/' /etc/kvm/vm/new.xml
sed -i -e 's/old disk/new disk/' /etc/kvm/vm/new.xml
virsh create /etc/kvm/vm/new.xml
And we're done. Boot and enjoy!
The future most likely: virt-sysprep
This entire tutorial becomes useless if you have virt-sysprep available on your box, which probably means you are using one of the later editions of your favorite operating system. However, in a business environment, this is most likely not the case, so the tool will not be available to most system administrators. If you do get the chance to use it, it offers some really handy improvements to the basic clone tool. Quoting the original documentation:
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 modifies the guest or disk image in place. The guest must be shut down. If you want to preserve the existing contents of the guest, you must copy or clone the disk first.
We WILL discuss this handy tool separately in another tutorial.
For more on KVM fun:
KVM + VirtualBox living in harmony
KVM bridged network tutorial
And here's how to clone ESXi machines - similar in concept
Another dandy resource of virtual machine disk image tools - libguestfs
This is a very simple and elegant tutorial. I think you will find it extremely useful as it complements the mostly manual cloning procedures with other tools. You get a set of commands that you can easily place into a single BASH script, and then, Bob's your uncle.
On a more serious note, you did learn a bit more about KVM configurations and file locations, a very rudimentary use of virt-clone, how to mount virtual machine disks and edit data in relevant partitions using partx, including network and host configurations, and how to assign unique fields to your virtual domain. And there's libguestfs, too. Plus some other highly useful guides. All in all, not bad for five minutes of work.
Finally, virt-sysprep makes cloning so much easier, however, the manual method, while a little more complicated, is foolproof. You can do anything you want using it, and you're not limited to an existing subset of command-line switches and options. It will always work, and it can always be fully scripted. Splendid.
Well, I guess that would be all.