From 70a8f53d65549de82924f6ba3267968c10ad4418 Mon Sep 17 00:00:00 2001 From: Keepers Date: Fri, 6 Jan 2023 15:47:16 -0700 Subject: [PATCH] full backup if prev snapshots have no details (#2049) ## Description In the event that a backup is completed but the details, somehow, isn't persisted, we want the next backup to do a full, instead of an incremental, backup. If we don't have this protection the following backups could end up in a bad state. Future changes will add better resilience so that the fallback isn't needed. ## Does this PR need a docs update or release note? - [x] :no_entry: No ## Type of change - [x] :sunflower: Feature ## Issue(s) * #1878 ## Test Plan - [x] :green_heart: E2E --- src/internal/kopia/snapshot_manager.go | 6 ++---- src/internal/operations/backup.go | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/internal/kopia/snapshot_manager.go b/src/internal/kopia/snapshot_manager.go index ef8e82e01..f82d742ed 100644 --- a/src/internal/kopia/snapshot_manager.go +++ b/src/internal/kopia/snapshot_manager.go @@ -322,11 +322,9 @@ func fetchPrevSnapshotManifests( // If the manifest already exists and it's incomplete then we should // merge the reasons for consistency. This will become easier to handle // once we update how checkpoint manifests are tagged. - if len(found.IncompleteReason) == 0 { - continue + if len(found.IncompleteReason) > 0 { + found.Reasons = append(found.Reasons, m.Reasons...) } - - found.Reasons = append(found.Reasons, m.Reasons...) } } } diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index e099d1b48..4de5c6aef 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -283,6 +283,31 @@ func produceManifestsAndMetadata( continue } + tk, _ := kopia.MakeTagKV(kopia.TagBackupID) + + bID := man.Tags[tk] + if len(bID) == 0 { + return nil, nil, errors.New("missing backup id in prior manifest") + } + + dID, _, err := sw.GetDetailsIDFromBackupID(ctx, model.StableID(bID)) + if err != nil { + return nil, nil, errors.Wrap(err, "retrieving prior backup data") + } + + // if no detailsID exists for any of the complete manifests, we want + // to fall back to a complete backup. This is a temporary prevention + // mechanism to keep backups from falling into a perpetually bad state. + // This makes an assumption that the ID points to a populated set of + // details; we aren't doing the work to look them up. + if len(dID) == 0 { + logger.Ctx(ctx).Infow( + "backup missing details ID, falling back to full backup", + "backup_id", bID) + + return ms, nil, nil + } + colls, err := collectMetadata(ctx, kw, man, metadataFiles, tenantID) if err != nil && !errors.Is(err, kopia.ErrNotFound) { // prior metadata isn't guaranteed to exist.