diff --git a/internal/models/models.go b/internal/models/models.go index 53a092a..7d1cd86 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -2,6 +2,7 @@ package models import ( "sort" + "strconv" "strings" "sync" "time" @@ -1118,6 +1119,51 @@ func (s *State) UpdateContainers(containers []Container) { s.LastUpdate = time.Now() } +// SyncGuestBackupTimes updates LastBackup on VMs and Containers from storage backups and PBS backups. +// Call this after updating storage backups or PBS backups to ensure guest backup indicators are accurate. +func (s *State) SyncGuestBackupTimes() { + s.mu.Lock() + defer s.mu.Unlock() + + // Build a map of VMID -> latest backup time from all backup sources + latestBackup := make(map[int]time.Time) + + // Process PVE storage backups + for _, backup := range s.PVEBackups.StorageBackups { + if backup.VMID <= 0 { + continue + } + if existing, ok := latestBackup[backup.VMID]; !ok || backup.Time.After(existing) { + latestBackup[backup.VMID] = backup.Time + } + } + + // Process PBS backups (VMID is string, BackupTime is the timestamp) + for _, backup := range s.PBSBackups { + vmid, err := strconv.Atoi(backup.VMID) + if err != nil || vmid <= 0 { + continue + } + if existing, ok := latestBackup[vmid]; !ok || backup.BackupTime.After(existing) { + latestBackup[vmid] = backup.BackupTime + } + } + + // Update VMs + for i := range s.VMs { + if backupTime, ok := latestBackup[s.VMs[i].VMID]; ok { + s.VMs[i].LastBackup = backupTime + } + } + + // Update Containers + for i := range s.Containers { + if backupTime, ok := latestBackup[s.Containers[i].VMID]; ok { + s.Containers[i].LastBackup = backupTime + } + } +} + // UpdateContainersForInstance updates containers for a specific instance, merging with existing containers func (s *State) UpdateContainersForInstance(instanceName string, containers []Container) { s.mu.Lock() diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index 26d4d36..e0c03fd 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -8363,6 +8363,9 @@ func (m *Monitor) pollStorageBackupsWithNodes(ctx context.Context, instanceName // Update state with storage backups for this instance m.state.UpdateStorageBackupsForInstance(instanceName, allBackups) + // Sync backup times to VMs/Containers for backup status indicators + m.state.SyncGuestBackupTimes() + if m.alertManager != nil { snapshot := m.state.GetSnapshot() guestsByKey, guestsByVMID := buildGuestLookups(snapshot, m.guestMetadataStore) @@ -9289,6 +9292,9 @@ func (m *Monitor) pollPBSBackups(ctx context.Context, instanceName string, clien // Update state m.state.UpdatePBSBackups(instanceName, allBackups) + // Sync backup times to VMs/Containers for backup status indicators + m.state.SyncGuestBackupTimes() + if m.alertManager != nil { snapshot := m.state.GetSnapshot() guestsByKey, guestsByVMID := buildGuestLookups(snapshot, m.guestMetadataStore)