From 9670afe0cb9f8391e22a64d98459b9ad3946556f Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 5 Nov 2025 19:38:32 +0000 Subject: [PATCH] Fix NODE column in backups to show actual guest node Related to discussion #577 When backups are stored on shared storage accessible from multiple nodes, the backup polling code was incorrectly assigning the backup to whichever node it was discovered on during the scan, rather than the node where the VM/container actually resides. This fix: - Builds a lookup map of VMID -> actual node at the start of backup polling - Uses this map to assign the correct node for guest backups (VMID > 0) - Preserves existing behavior for host backups (VMID == 0) - Falls back to the queried node if the guest is not found in the map This ensures the NODE column accurately reflects which node hosts each guest, matching the information displayed on the main page. --- internal/monitoring/monitor.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index b6a9e50..60a2f87 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -7735,6 +7735,20 @@ func (m *Monitor) pollStorageBackupsWithNodes(ctx context.Context, instanceName contentFailures := 0 // Number of failed storage content fetches storageQueryErrors := 0 // Number of nodes where storage list could not be queried + // Build guest lookup map to find actual node for each VMID + snapshot := m.state.GetSnapshot() + guestNodeMap := make(map[int]string) // VMID -> actual node name + for _, vm := range snapshot.VMs { + if vm.Instance == instanceName { + guestNodeMap[vm.VMID] = vm.Node + } + } + for _, ct := range snapshot.Containers { + if ct.Instance == instanceName { + guestNodeMap[int(ct.VMID)] = ct.Node + } + } + // For each node, get storage and check content for _, node := range nodes { if nodeEffectiveStatus[node.Node] != "online" { @@ -7828,8 +7842,15 @@ func (m *Monitor) pollStorageBackupsWithNodes(ctx context.Context, instanceName backupType = "qemu" } - // Always use the actual node name + // Determine the correct node: for guest backups (VMID > 0), use the actual guest's node + // For host backups (VMID == 0), use the node where the backup was found backupNode := node.Node + if content.VMID > 0 { + if actualNode, found := guestNodeMap[content.VMID]; found { + backupNode = actualNode + } + // If not found in map, fall back to queried node (shouldn't happen normally) + } isPBSStorage := strings.HasPrefix(storage.Storage, "pbs-") || storage.Type == "pbs" // Check verification status for PBS backups