Skip to content

Instantly share code, notes, and snippets.

@migae21
Last active May 13, 2019 11:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save migae21/f94f8f3bef00cc9f254403b5c51ce151 to your computer and use it in GitHub Desktop.
Save migae21/f94f8f3bef00cc9f254403b5c51ce151 to your computer and use it in GitHub Desktop.
My Way to backup my Virtual machines under Linux/KVM
#!/bin/bash
unset TRY_RUN
#Uncomment the following line to get a TRY RUN (no actions taken just output)
#TRY_RUN="TRUE"
cmd_eval ()
{ if [ ! -z "$TRY_RUN" ]; then
echo "$*"
return 0
else
eval "$*"
if [ $? -ne 0 ]; then
loging "Failed to execute $*"
loging "exiting"
return 1
fi
return 0
fi }
unset DEBUG
#Uncomment the following line to get debuging ouput
DEBUG="TRUE"
#Use this function to echo text
debugecho ()
{ if [ ! -z "$DEBUG" ]; then echo "$*"; fi }
if [ ! -z "$DEBUG" ]; then
RSYNC_OPTION="-avhW --inplace --chmod u=rw,g=rw,o=r --progress"
else
RSYNC_OPTION="-ahW --inplace --chmod u=rw,g=rw,o=r"
fi
# Optional add S to options
LOGENTRYNAME=backup_virtual_machines
unset SYSTEMD_LOGING
{ if [ ! -z "$TRY_RUN" ]; then
unset SYSTEMD_LOGING
else
SYSTEMD_LOGING="TRUE"
fi }
#scriptname for systemd loging
loging ()
{ if [ ! -z "$SYSTEMD_LOGING" ]; then systemd-cat -t "$LOGENTRYNAME" echo "$*"; fi }
SCRIPTNAME=backup_virtual_machines
#scriptname for systemd logging
#connect to the right kvm Instance
export LIBVIRT_DEFAULT_URI='qemu:///system'
#debian default connect virsh to qemu:///session for non-root
#Path to the Backup
BACKUPPATH="/srv/backup/virtual_machines/autobackup/"
# List domains
DOMAINS=$(virsh list --all | tail -n +3 | awk '{print $2}')
debugecho "DOMAINS: $DOMAINS"
# Loop over the DOMAINS
for DOMAIN in $DOMAINS; do
debugecho "### STARTING with Domain: $DOMAIN ###"
# Generate the backup folder URI - this is something you should
# change/check
BACKUPFOLDER="$BACKUPPATH$DOMAIN/"
mkdir -p $BACKUPFOLDER
# Get the target disk
TARGETS=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $3}')
# Get the image page
IMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
#only for running Domains
STATE=$(virsh dominfo $DOMAIN | grep "State" | cut -d " " -f 11)
if [ "$STATE" = "running" ]; then
debugecho "$Domain is running"
debugecho "Starting backup for running $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')"
loging "Starting backup for running $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')"
# Create the snapshot/disk specification
DISKSPEC=""
for TARGET in $TARGETS; do
DISKSPEC="$DISKSPEC --diskspec $TARGET,snapshot=external"
done
cmd_eval "virsh snapshot-create-as --domain $DOMAIN --name "backupSNAP-$DOMAIN" --no-metadata --atomic --disk-only $DISKSPEC 1>/dev/null 2>&1"
if [ $? -ne 0 ]; then
debugecho "Failed to create snapshot for $DOMAIN --> exiting"
loging "Failed to create snapshot for $DOMAIN --> exiting"
exit 1
fi
debugecho "Snapshot for $DOMAIN created"
# Copy disk image
for IMAGE in $IMAGES; do
STARTZEIT=$(date "+%s")
NAME=$(basename $IMAGE)
# cp $IMAGE $BACKUPFOLDER/$NAMEqem
# pv $IMAGE > $BACKUPFOLDER/$NAME
cmd_eval "rsync $RSYNC_OPTION $IMAGE $BACKUPFOLDER/$NAME"
if [ $? -ne 0 ]; then
loging "Failed to copy snapshot for $DOMAIN --> exiting"
exit 1
fi
ENDZEIT=$(date "+%s")
debugecho "Backup done: $IMAGE to $BACKUPFOLDER/$NAME in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
loging "Backup done: $IMAGE to $BACKUPFOLDER/$NAME in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
done
# Merge changes back
BACKUPIMAGES=$(virsh domblklist $DOMAIN --details | grep disk | awk '{print $4}')
STARTZEIT=$(date "+%s")
for TARGET in $TARGETS; do
cmd_eval "virsh blockcommit $DOMAIN $TARGET --active --pivot 1>/dev/null 2>&1"
if [ $? -ne 0 ]; then
loging "Failed to revert snapshot for $DOMAIN --> exiting"
exit 1
fi
done
ENDZEIT=$(date "+%s")
debugecho "Reverting Snapshot done for $IMAGE in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
loging "Reverting Snapshot done for $IMAGE in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
# Cleanup left over backups
for BACKUP in $BACKUPIMAGES; do
if [[ $BACKUP =~ .*backupSNAP.* ]]
then
cmd_eval "rm -f $BACKUP"
else
loging "Filename $DOMAIN snapshot doesent include scurity token --> exiting"
exit 1
fi
done
# Dump the configuration information.
cmd_eval "virsh dumpxml $DOMAIN > $BACKUPFOLDER/$DOMAIN.xml 1>/dev/null 2>&1"
else
debugecho "$Domain is not running"
loging "Starting copy for not running $DOMAIN on $(date +'%d-%m-%Y %H:%M:%S')"
# For not running Domains just copy the disks
# no snnapshot and merge needed
# Copy disk image
for IMAGE in $IMAGES; do
STARTZEIT=$(date "+%s")
NAME=$(basename $IMAGE)
# cp $IMAGE $BACKUPFOLDER/$NAMEqem
# pv $IMAGE > $BACKUPFOLDER/$NAME
cmd_eval "rsync $RSYNC_OPTION $IMAGE $BACKUPFOLDER/$NAME"
if [ $? -ne 0 ]; then
loging "Failed to copy $IMAGE for $DOMAIN --> exiting"
exit 1
fi
ENDZEIT=$(date "+%s")
debugecho "Backup done: $IMAGE to $BACKUPFOLDER/$NAME in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
loging "Backup done: $IMAGE to $BACKUPFOLDER/$NAME in: "$(( $ENDZEIT - $STARTZEIT ))" sekunden"
done
cmd_eval "virsh dumpxml $DOMAIN > $BACKUPFOLDER/$DOMAIN.xml 1>/dev/null 2>&1"
fi
debugecho "### Finished backup of $DOMAIN at $(date +'%d-%m-%Y %H:%M:%S') ###"
loging "### Finished backup of $DOMAIN at $(date +'%d-%m-%Y %H:%M:%S') ###"
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment