Skip to content

Instantly share code, notes, and snippets.

@jedisct1
Created January 25, 2019 20:10
Show Gist options
  • Save jedisct1/62f836ca4f140b79be19707e2dff781e to your computer and use it in GitHub Desktop.
Save jedisct1/62f836ca4f140b79be19707e2dff781e to your computer and use it in GitHub Desktop.
#!/bin/bash
#
cd /local/backups || exit 1
export PATH=/usr/local/sbin:/usr/local/bin:$PATH
BACKUPDEST="$1"
DOMAIN="$2"
MAXBACKUPS="$3"
PASSWD="/* change this, obviously */"
if [ -z "$BACKUPDEST" -o -z "$DOMAIN" ]; then
echo "Usage: ./vm-backup <backup-folder> <domain> [max-backups]"
exit 1
fi
if [ -z "$MAXBACKUPS" ]; then
MAXBACKUPS=5
fi
BACKUPDOMAIN="$BACKUPDEST/$DOMAIN"
#
# Cleanup older backups.
#
echo "Cleaning older backups for $DOMAIN"
LIST=$(ls -r1 "$BACKUPDOMAIN" | grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]+$')
i=1
for b in $LIST; do
if [ $i -gt "$MAXBACKUPS" ]; then
echo "Removing old backup $BACKUPDOMAIN/$b"
rm -rf "$BACKUPDOMAIN/$b"
fi
i=$[$i+1]
done
# Generate the backup path
#
BACKUPDATE=`date "+%Y-%m-%d.%H%M%S"`
BACKUP="$BACKUPDOMAIN/$BACKUPDATE"
mkdir -p "$BACKUP"
echo "Beginning backup for $DOMAIN"
#
# Get the list of targets (disks) and the image paths.
#
TARGETS=$(virsh domblklist "$DOMAIN" --details | grep -e '^ *file' | grep -v 'cdrom' | grep -v 'floppy' | awk '{print $3}')
IMAGES=$(virsh domblklist "$DOMAIN" --details | grep -e '^ *file' | grep -v 'cdrom' | grep -v 'floppy' | awk '{print $4}')
#
# Create the snapshot.
#
DISKSPEC=""
for t in $TARGETS; do
DISKSPEC="$DISKSPEC --diskspec $t,snapshot=external"
done
virsh snapshot-create-as --domain "$DOMAIN" --name backup --no-metadata \
--atomic --disk-only $DISKSPEC >/dev/null
if [ $? -ne 0 ]; then
echo "Failed to create snapshot for $DOMAIN"
exit 1
fi
#
# Copy disk images
#
for t in $IMAGES; do
NAME=$(basename "$t")
nice ionice zstd -12 -v -c "$t" | nice encpipe -e -p "$PASSWD" -o "$BACKUP"/"$NAME".zst.encpipe
done
#
# Merge changes back.
#
BACKUPIMAGES=`virsh domblklist "$DOMAIN" --details | grep -e '^ *file' | awk '{print $4}'`
for t in $TARGETS; do
virsh blockcommit "$DOMAIN" "$t" --active --pivot >/dev/null
if [ $? -ne 0 ]; then
echo "Could not merge changes for disk $t of $DOMAIN. VM may be in invalid state."
exit 1
fi
done
#
# Resume VM
#
virsh resume "$DOMAIN" 2> /dev/null
#
# Cleanup left over backup images.
#
for t in $BACKUPIMAGES; do
rm -f "$t"
done
#
# Dump the configuration information.
#
virsh dumpxml "$DOMAIN" >"$BACKUP/$DOMAIN.xml"
echo "Finished backup"
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment