I often need to quickly revert virtual machines used for testing to a known good, vanilla state without doing anything by hand. QEMU provides a great set of tools to help. Here’s a simple tool to wrap all of it together, giving you a pristine, “gold” copy that you can quickly revert to after changes.
What Does it Do?
This tool doesn’t do anything that special but it saves me a lot of time from having to run anything by hand ever again to reset my environments. There are lots of ways to solve this problem but this one works for me. Below are some highlights:
- Uses a qcow2 backing file to revert VM’s quickly back to a vanilla, pristine state.
- Ensure static, iterative VM network addressing
- Use libguestfs to inject SSH keys and other configurations
- virt-manager or virt-install
- an EL-based hypervisor
You can start with any VM image so long as it’s a qcow2. For these examples we’re going to be using CentOS7.
- Install a VM locally or on a Libvirt Hypervisor
- Shutdown the VM
- Delete the VM (save the image)
- Rename your saved VM
cd /var/lib/libvirt/images/ mv /var/lib/libvirt/images/centos7.qcow2 /var/lib/libvirt/images/centos7-base.qcow2
- Create a number of VM qcow2 images using the above image as a backing file.
qemu-img create -b `pwd`/centos7-base.qcow2 -f qcow2 host-01.qcow2 qemu-img create -b `pwd`/centos7-base.qcow2 -f qcow2 host-02.qcow2 qemu-img create -b `pwd`/centos7-base.qcow2 -f qcow2 host-03.qcow2
Build Test Fleet
Now you’ll need to create as many test/development VMs as you think you’ll need. You can always create more later but we’ll start with three. Use the import existing disk image option within virt-manager or the appropriate flags if you’re using virt-install on the CLI.
Download the vm-reset Script
Obtain the vm-reset script from Github, the repository is located here.
Prep the Tool
You’ll want to inject your own public SSH keys at the very least, substituting the id_rsa.pub public key name below to yours if it differs. If you forget this part it will print it out for you as a warning.
sed -i "s,\(.*echo.*\)ssh-rsa MYPUBKEY\(.*authorized_keys$\),\1$(cat ~/.ssh/id_rsa.pub)\2,g" ./vm-reset.sh
Optional: You’ll also want to edit the hostnames listed in the iterative array if you used different hostnames, replacing host-01 and friends with whatever you fancy.
guests=( ["host-01"]="81" ["host-02"]="82" ["host-03"]="83" )
Run the Thing
That’s it, now you can quickly and easily reset your test/development VM’s with one sudo command.
Occasionally you’ll get a VM in a non-bootable state, usually in grub rescure. Force it off and restart.
You might also seldomly see phantom guestfs temporary VM’s running, force them off and they will disappear.
If there’s other functionality that is useful file an issue about it on github or comment below. Big props to Kambiz Aghaiepour for his collaboration on this and Dan Radez for the inspiration.
Why not use virt-builder, virt-sysprep, virt-customize and friends?
Howdy Yaniv, that’s a great suggestion. Perhaps we could reduce some (or mostly all) of the shell code with these tools, but it’s pretty fast as-is only taking a few seconds to revert to a qcow2 snapshot. For this particular usage the pristine VM images we want to revert to are static in nature and would not change – we mainly use this to test Ansible code and automated application deployments so that’s the needed post deployment mechanism that would drive any transformation after the baseline OS is in place.