From 4e6ee4918c5aedead41ef048d91ac915538a9aec Mon Sep 17 00:00:00 2001 From: Moritz Tanner Date: Fri, 3 Jul 2026 13:53:19 +0200 Subject: [PATCH] Fix NAS backup filename for legacy LINSTOR path When backing up a running VM, nasbackup.sh derives the backup filename from the disk source path reported by libvirt. VMs started before the switch to /dev/drbd/by-res/ paths still carry the raw DRBD device node (e.g. /dev/drbd1098) in their live domain XML, which fell into the basename fallback and produced root.drbd1098.qcow2 instead of root..qcow2. Restore always expects the UUID-based name, so these backups could not be restored until the VM was stopped and started. Resolve raw /dev/drbdNNNN device nodes back to the volume UUID by asking udev for the device's /dev/drbd/by-res/cs- symlink. Apply the same handling in all three backup loops (running-VM XML build, sparsify, and stopped-VM convert). Signed-off-by: Moritz Tanner --- scripts/vm/hypervisor/kvm/nasbackup.sh | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/scripts/vm/hypervisor/kvm/nasbackup.sh b/scripts/vm/hypervisor/kvm/nasbackup.sh index 0b09d841aff5..71d9a8276f0c 100755 --- a/scripts/vm/hypervisor/kvm/nasbackup.sh +++ b/scripts/vm/hypervisor/kvm/nasbackup.sh @@ -108,6 +108,21 @@ get_linstor_uuid_from_path() { echo "$volUuid" } +get_linstor_uuid_from_device() { + local fullpath="$1" + # VMs started before the /dev/drbd/by-res/ change still reference the raw DRBD + # device node (e.g. /dev/drbd1098) in their live libvirt XML. Ask udev for the + # device's symlinks and map it back to the volume UUID via the by-res symlink. + local link + for link in $(udevadm info --query=symlink --name="$fullpath" 2>/dev/null || true); do + if [[ "$link" == drbd/by-res/cs-* ]]; then + get_linstor_uuid_from_path "/dev/$link" + return 0 + fi + done + echo "${fullpath##*/}" +} + backup_running_vm() { mount_operation mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; } @@ -117,6 +132,8 @@ backup_running_vm() { while read -r disk fullpath; do if [[ "$fullpath" == /dev/drbd/by-res/* ]]; then volUuid=$(get_linstor_uuid_from_path "$fullpath") + elif [[ "$fullpath" == /dev/drbd[0-9]* ]]; then + volUuid=$(get_linstor_uuid_from_device "$fullpath") else volUuid="${fullpath##*/}" fi @@ -174,10 +191,14 @@ backup_running_vm() { # Use qemu-img convert to sparsify linstor backups which get bloated due to virsh backup-begin. name="root" while read -r disk fullpath; do - if [[ "$fullpath" != /dev/drbd/by-res/* ]]; then + if [[ "$fullpath" == /dev/drbd/by-res/* ]]; then + volUuid=$(get_linstor_uuid_from_path "$fullpath") + elif [[ "$fullpath" == /dev/drbd[0-9]* ]]; then + volUuid=$(get_linstor_uuid_from_device "$fullpath") + else + name="datadisk" continue fi - volUuid=$(get_linstor_uuid_from_path "$fullpath") if ! qemu-img convert -O qcow2 "$dest/$name.$volUuid.qcow2" "$dest/$name.$volUuid.qcow2.tmp" >> "$logFile" 2> >(cat >&2); then echo "qemu-img convert failed for $dest/$name.$volUuid.qcow2" cleanup @@ -213,6 +234,8 @@ backup_stopped_vm() { volUuid=$(get_ceph_uuid_from_path "$disk") elif [[ "$disk" == /dev/drbd/by-res/* ]]; then volUuid=$(get_linstor_uuid_from_path "$disk") + elif [[ "$disk" == /dev/drbd[0-9]* ]]; then + volUuid=$(get_linstor_uuid_from_device "$disk") else volUuid="${disk##*/}" fi