With newer versions of libvirt, it is possible to create complete live backups of virtual machines. The system involves the following steps:
The script presented in the code section uses parallel xz
in order to speed-up the compression of files while copying the storage to the backup directory.
As it currently is written, the script just needs to be run. Alternatively, you may want to copy the script to the corresponding cron directories in order to have periodic backups. Note that the script should not be run more often than once per day - mainly because backups do take a long time (the script does have protections in place to not run concurrently and corrupt files).
The script will create directories under the configured backup directory for all domain names and then inside those directories the backups will be created following the year-month-day format.
#!/bin/sh ########################################################################### ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ## ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## ## rights of fair usage, the disclaimer and warranty conditions. ## ########################################################################### # Live backup script for libvirt/qemu virtual machines using blockcommit. # # The script is designed to query all the active libvirt domains, create # # a snap overlay, copy over the image or the block device to a file and # # finally merge the overlay with the image - all these operations are # # performed without needing to suspend or shut down the virtual machine. # # # # Requirements: # # * pxz (parallel xz) # # # # Setup: Configure the script in the configuration section and then run # # the script - the script is designed to be run from cron. # ########################################################################### ########################################################################### # CONFIGURATION # ########################################################################### # This absolute path to a directory where the machines will be stored. BACKUP_DIRECTORY=/mnt/archie/Backups/VMS # A temporary directory to hold the temporary snapshots. SNAP_DIRECTORY=/var/lib/libvirt/snapshots # A space-separated list of domains to exclude from backup. EXCLUDE_DOMAINS="corrade.internal" ########################################################################### # INTERNALS # ########################################################################### # Get active domains. DOMAINS=`virsh -c qemu:///system list | grep -o '[0-9]* [a-z]*.*running' | awk '{print $2}'` # Generate a timestamp. TIMESTAMP=`date +%Y%m%d` # Acquire lock. if mkdir /var/lock/virsh-backup; then for DOMAIN in $DOMAINS; do # Check if this domain has been excluded. for EXCLUDE in $EXCLUDE_DOMAINS; do if [ "$DOMAIN" = "$EXCLUDE" ]; then DOMAIN="" fi done if [ -z "$DOMAIN" ]; then continue; fi # Get block devices. VIRT_BLOCK_DEVICE=`virsh domblklist "$DOMAIN" | grep '/' | head -1 | awk '{print $1}'` HOST_BLOCK_DEVICE=`virsh domblklist "$DOMAIN" | grep '/' | head -1 | awk '{print $2}'` if [ -z "$VIRT_BLOCK_DEVICE" ]; then echo "Block device not found for domain "$DOMAIN continue; fi if [ ! -d "$SNAP_DIRECTORY" ]; then mkdir -p "$SNAP_DIRECTORY" fi # Create snapshot virsh snapshot-create-as \ --domain "$DOMAIN" "$DOMAIN-snap-$TIMESTAMP" \ --diskspec "$VIRT_BLOCK_DEVICE",file="$SNAP_DIRECTORY/$DOMAIN-snap-$TIMESTAMP" \ --disk-only \ --atomic \ --no-metadata \ --quiesce >/dev/null 2>&1 if [ "$?" -ne "0" ]; then echo "Failed snapshoting domain "$DOMAIN continue; fi if [ ! -f "$SNAP_DIRECTORY/$DOMAIN-snap-$TIMESTAMP" ]; then echo "Snapshot file for domain "$DOMAIN" does not exit" continue; fi if [ ! -d "$BACKUP_DIRECTORY/$DOMAIN" ]; then mkdir -p "$BACKUP_DIRECTORY/$DOMAIN" fi dd if="$HOST_BLOCK_DEVICE" \ conv=noerror status=none \ bs=1M | pxz -0 > "$BACKUP_DIRECTORY/$DOMAIN/$TIMESTAMP.img.xz" virsh blockcommit "$DOMAIN" "$VIRT_BLOCK_DEVICE" \ --active \ --pivot >/dev/null 2>&1 if [ "$?" -ne "0" ]; then echo "Could not commit back snapshot for domain "$DOMAIN continue; fi rm "$SNAP_DIRECTORY/$DOMAIN-snap-$TIMESTAMP" done # Release lock. rm -rf /var/lock/virsh-backup fi