95 lines
2.3 KiB
Django/Jinja
Executable file
95 lines
2.3 KiB
Django/Jinja
Executable file
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
(
|
|
set -euo pipefail
|
|
flock -x -w 10 200 || exit 1
|
|
|
|
export LVM_SUPPRESS_FD_WARNINGS=1
|
|
DOMAIN=${1:?VM name musst be passed!}
|
|
DOMAIN_MOUNTBASE="/var/backup-client/vm-mountpoint"
|
|
|
|
function unfreeze_vm {
|
|
virsh resume "$DOMAIN" > /dev/null || true
|
|
}
|
|
|
|
function delete_snapshots {
|
|
cleanup_vmmount > /dev/null 2>&1
|
|
for i in $DISKS; do
|
|
extract_lvm
|
|
SNAPSHOT="/dev/$VG/backup-$DEVICE"
|
|
lvremove -f "$SNAPSHOT" > /dev/null 2>&1 || true
|
|
done
|
|
}
|
|
|
|
function cleanup_vmmount {
|
|
umount -l $DOMAIN_MOUNTBASE/* || true
|
|
rmdir ${DOMAIN_MOUNTBASE:?}/* || true
|
|
rm "$DOMAIN_MOUNTBASE/config.xml" || true
|
|
}
|
|
|
|
function extract_lvm {
|
|
DISK=`echo $i | awk -F, '{print $1}'`
|
|
DEVICE=`echo $i | awk -F, '{print $2}'`
|
|
VG=`lvs --noheadings -o vg_name "$DISK" | tr -d ' '`
|
|
LV=`lvs --noheadings -o lv_name "$DISK" | tr -d ' '`
|
|
}
|
|
|
|
function backup_vm {
|
|
# get a list of disks
|
|
DISKS=`virsh domblklist "$DOMAIN" --details \
|
|
| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' \
|
|
| grep ^block \
|
|
| grep -v swap \
|
|
| awk '{printf "%s,%s ",$4, $3}'`
|
|
echo "backing up $DOMAIN: $DISKS"
|
|
|
|
trap "unfreeze_vm || true; delete_snapshots" INT TERM EXIT
|
|
|
|
# in case an earlier script crashed we have to clear snapshots
|
|
delete_snapshots
|
|
|
|
# freez vm
|
|
virsh suspend "$DOMAIN" > /dev/null || true
|
|
|
|
# create disk snapshots
|
|
for i in $DISKS; do
|
|
extract_lvm
|
|
lvcreate -L16G -s -n "backup-$DEVICE" "$DISK" > /dev/null
|
|
done
|
|
|
|
# dump vm config
|
|
virsh dumpxml "$DOMAIN" > "$DOMAIN_MOUNTBASE/config.xml"
|
|
|
|
unfreeze_vm
|
|
trap "delete_snapshots" INT TERM EXIT
|
|
|
|
# mount disks snapshots
|
|
for i in $DISKS; do
|
|
extract_lvm
|
|
SNAPSHOT="/dev/$VG/backup-$DEVICE"
|
|
fsck -y "$SNAPSHOT" > /dev/null 2> /dev/null
|
|
|
|
(
|
|
mkdir "$DOMAIN_MOUNTBASE/$DEVICE"
|
|
mount -o ro "$SNAPSHOT" "$DOMAIN_MOUNTBASE/$DEVICE"
|
|
) 2> /dev/null
|
|
done
|
|
|
|
{% if backup_backend == 'restic' %}
|
|
# restic backend
|
|
source /etc/backup-client/restic.env
|
|
restic backup \
|
|
--verbose \
|
|
--host "$DOMAIN" \
|
|
--exclude-file "/etc/backup-client/vms/$DOMAIN/exclude_files" \
|
|
"$DOMAIN_MOUNTBASE"
|
|
{% endif %}
|
|
|
|
# delete snapshot
|
|
delete_snapshots;
|
|
trap - INT TERM EXIT
|
|
}
|
|
|
|
test -f "/etc/backup-client/vms/$DOMAIN/enabled" && backup_vm || echo "Backup for $DOMAIN is disabled"
|
|
) 200>/var/lock/backup-vm.lock
|