libvirt-zsh-backup/libvirt-zsh-backup.sh

129 lines
3.1 KiB
Bash

#!/bin/bash
helpFunction()
{
echo ""
echo "Usage: $0 -v VmName -t TargetHost -d TargetDataset -l LIMIT"
echo -e "\t-v Name of the vm to backup"
echo -e "\t-t Backup target host name"
echo -e "\t-s VM source zfs dataset"
echo -e "\t-d Backup target zfs dataset"
echo -e "\t-l Limit Bandwith"
exit 1 # Exit script after printing help
}
while getopts "v:t:s:d:l:" opt
do
case "$opt" in
v ) VM="$OPTARG" ;;
t ) DESTHOST="$OPTARG" ;;
s ) SRCZFS="$OPTARG" ;;
d ) DESTZFS="$OPTARG" ;;
l ) LIMIT="$OPTARG" ;;
? ) helpFunction ;; # Print helpFunction in case parameter is non-existent
esac
done
# Print helpFunction in case parameters are empty
if [ -z "$VM" ] || [ -z "$DESTHOST" ] || [ -z "$DESTZFS" ] || [ -z "$SRCZFS" ] || [ -z "$LIMIT" ]
then
echo "Some or all of the parameters are empty";
helpFunction
fi
DATE=$(date "+%Y%m%d%H%M")
DATE30=$(date -d "-30day" "+%Y%m%d")
SNAPNAME="backup_$DATE"
abortFunction()
{
zfs set backup:success="false" $SRCZFS
zfs set backup:failed="$DATE" $SRCZFS
exit 1
}
VMDISKS=$(virsh domblklist $VM | egrep -o vd.)
DISKSPEC=""
for disk in $VMDISKS
do
DISKSPEC+="--diskspec $disk,file=/srv/snapshots/$VM/$VM-$disk-$SNAPNAME.qcow2,snapshot=external "
done
# create snapshot dataset
zfs create tank/snapshots/$VM
# create virsh xml-dump of vm
virsh dumpxml $VM > /srv/vms/$VM/vm-$VM.xml
virsh snapshot-create-as --domain $VM --name $SNAPNAME --quiesce --atomic --disk-only $DISKSPEC >/dev/null 2>&1
if [ $? -ne 0 ]
then
virsh snapshot-create-as --domain $VM --name $SNAPNAME --disk-only $DISKSPEC >/dev/null 2>&1
if [ $? -ne 0 ]
then
echo "VM snapshot creation failed" >&2
abortFunction
else
echo "Snapshot created without --quiesce"
fi
fi
zfs snapshot "$SRCZFS"@"$SNAPNAME"
if [ $? -ne 0 ]
then
echo "ZFS snapshot creation failed" >&2
abortFunction
fi
for disk in $VMDISKS
do
virsh blockcommit $VM $disk --pivot --active >/dev/null
done
VMDISKS=$(virsh domblklist $VM | egrep vd.)
for disk in $VMDISKS
do
if [[ $disk == *"snapshot"* ]]
then
echo "Snapshot deletion failed for $disk" >&2
abortFunction
fi
done
virsh snapshot-delete $VM $SNAPNAME --metadata
SUCCESS=$(zfs get backup:success -H -o value $SRCZFS)
if [[ $SUCCESS == "true" ]]
then
LASTBACKUP=$(zfs get backup:date -H -o value $SRCZFS)
LASTSNAP="backup_$LASTBACKUP"
echo "Sending incremental snapshot from $LASTSNAP"
zfs send -R -i "$SRCZFS"@"$LASTSNAP" "$SRCZFS"@"$SNAPNAME" | pv -L $LIMIT | ssh $DESTHOST sudo zfs recv -F $DESTZFS
else
echo "Sending full snapshot"
zfs send -R "$SRCZFS"@"$SNAPNAME" | pv -L $LIMIT | ssh $DESTHOST sudo zfs recv -F $DESTZFS
fi
if [ $? -eq 0 ]
then
zfs set backup:success="true" $SRCZFS
zfs set backup:date="$DATE" $SRCZFS
zfs destroy "$SRCZFS"@"$LASTSNAP"
else
abortFunction
fi
zfs destroy tank/snapshots/$VM
# cleanup old backups
OLDSNAPS=$(ssh $DESTHOST zfs list -r -t snapshot -o name $DESTZFS 2>/dev/null | grep $DATE30)
if [ ${#OLDSNAPS} -gt 0 ]
then
for oldsnap in $OLDSNAPS
do
ssh $DESTHOST sudo zfs destroy $oldsnap
done
else
echo "No old snapshots to cleanup"
fi