diff --git a/templates/backup-vm.j2 b/templates/backup-vm.j2 index e16a6b120ee6a31a2c65695dffa8cc17799f9564..a4575b52d8469b2160cbbd0351310a1730dd63c0 100755 --- a/templates/backup-vm.j2 +++ b/templates/backup-vm.j2 @@ -20,6 +20,11 @@ set -euo pipefail SNAPSHOT="/dev/$VG/backup-$DEVICE" lvremove -f "$SNAPSHOT" > /dev/null 2>&1 || true done + for i in $DISKS_QCOW2; do + extract_lvm_qcow2 + SNAPSHOT="/dev/$VG/backup-$DEVICE" + lvremove -f "$SNAPSHOT" > /dev/null 2>&1 || true + done } function cleanup_vmmount { @@ -35,6 +40,16 @@ set -euo pipefail LV=`lvs --noheadings -o lv_name "$DISK" | tr -d ' '` } + function extract_lvm_qcow2 { + DISK=`echo $i | awk -F, '{print $1}'` + DEVICE=`echo $i | awk -F, '{print $2}'` + DEVICEPATH=`df "$DISK" | awk '{print $1}' | tail -n1` + MOUNTPOINT=`df "$DISK" | awk '{print $6}' | tail -n1` + RELIMAGEPATH="${DISK#$MOUNTPOINT}" + VG=`lvs --noheadings -o vg_name "$DEVICEPATH" | tr -d ' '` + LV=`lvs --noheadings -o lv_name "$DEVICEPATH" | tr -d ' '` + } + function backup_vm { # get a list of disks DISKS=`virsh domblklist "$DOMAIN" --details \ @@ -42,7 +57,13 @@ set -euo pipefail | grep ^block \ | grep -v swap \ | awk '{printf "%s,%s ",$4, $3}'` - echo "backing up $DOMAIN: $DISKS" + DISKS_QCOW2=`virsh domblklist "$DOMAIN" --details \ + | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' \ + | grep ^file \ + | grep -v swap \ + | grep '.qcow2' \ + | awk '{printf "%s,%s ",$4, $3}'` + echo "backing up $DOMAIN: $DISKS $DISKS_QCOW2" trap "unfreeze_vm || true; delete_snapshots" INT TERM EXIT @@ -58,6 +79,12 @@ set -euo pipefail lvcreate -L16G -s -n "backup-$DEVICE" "$DISK" > /dev/null done + # create snapshots of all volumes containing qcow2 images + for i in $DISKS_QCOW2; do + extract_lvm_qcow2 + lvcreate -L16G -s -n "backup-$DEVICE" "$DEVICEPATH" > /dev/null + done + # dump vm config virsh dumpxml "$DOMAIN" > "$DOMAIN_MOUNTBASE/config.xml" @@ -76,6 +103,21 @@ set -euo pipefail ) 2> /dev/null done + # mount qcow2 disk images backing storage + for i in $DISKS_QCOW2; do + extract_lvm_qcow2 + SNAPSHOT="/dev/$VG/backup-$DEVICE" + fsck -y "$SNAPSHOT" > /dev/null 2> /dev/null + ( + mkdir "$DOMAIN_MOUNTBASE/IMAGECONTAINER_$DEVICE" + # to be able to run fsck inside the vm we have to mount the containers r/w + mount -o rw "$SNAPSHOT" "$DOMAIN_MOUNTBASE/IMAGECONTAINER_$DEVICE" + + mkdir "$DOMAIN_MOUNTBASE/$DEVICE" + guestmount -m /dev/sda -a "$DOMAIN_MOUNTBASE/IMAGECONTAINER_$DEVICE/$RELIMAGEPATH" "$DOMAIN_MOUNTBASE/$DEVICE" + ) 2> /dev/null + done + {% if backup_backend == 'restic' %} # restic backend source /etc/backup-client/restic.env @@ -83,6 +125,7 @@ set -euo pipefail --verbose \ --host "$DOMAIN" \ --exclude-file "/etc/backup-client/vms/$DOMAIN/exclude_files" \ + --exclude="$DOMAIN_MOUNTBASE/IMAGECONTAINER_*" \ "$DOMAIN_MOUNTBASE" {% endif %}