From 5c5ac0ac74a1bff76013eeb42ee26f172d89d399 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 | 41 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/scripts/vm/hypervisor/kvm/nasbackup.sh b/scripts/vm/hypervisor/kvm/nasbackup.sh index 0b09d841aff5..656ff5ac28d6 100755 --- a/scripts/vm/hypervisor/kvm/nasbackup.sh +++ b/scripts/vm/hypervisor/kvm/nasbackup.sh @@ -108,6 +108,23 @@ 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 + # Without a by-res symlink we cannot derive the volume UUID. Falling back to the + # raw device name would produce a backup that restore cannot find, so fail hard. + return 1 +} + backup_running_vm() { mount_operation mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; } @@ -117,6 +134,12 @@ 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 + if ! volUuid=$(get_linstor_uuid_from_device "$fullpath"); then + echo "Failed to resolve LINSTOR volume UUID for $fullpath" + cleanup + exit 1 + fi else volUuid="${fullpath##*/}" fi @@ -174,10 +197,18 @@ 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 + if ! volUuid=$(get_linstor_uuid_from_device "$fullpath"); then + echo "Failed to resolve LINSTOR volume UUID for $fullpath" + cleanup + exit 1 + fi + 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 +244,12 @@ 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 + if ! volUuid=$(get_linstor_uuid_from_device "$disk"); then + echo "Failed to resolve LINSTOR volume UUID for $disk" + cleanup + exit 1 + fi else volUuid="${disk##*/}" fi