Merge branch 'main' into report-incremental-fallback

This commit is contained in:
Lyndon-Li
2026-09-09 14:19:59 +08:00
30 changed files with 425 additions and 88 deletions
+39 -37
View File
@@ -169,50 +169,52 @@ func getParentBackupInfo(ctx context.Context, rep udmrepo.BackupRepo, forceFull
}
var previous *udmrepo.Snapshot
if parentSnapshot != "" {
log.Infof("Loading provided parent snapshot %s", parentSnapshot)
snap, err := rep.GetSnapshot(ctx, udmrepo.ID(parentSnapshot))
if err != nil {
return parentBackupInfo{}, errors.Wrapf(err, "error loading previous snapshot")
if !forceFull {
if parentSnapshot != "" {
snap, err := rep.GetSnapshot(ctx, udmrepo.ID(parentSnapshot))
if err != nil {
log.WithError(err).Warn("Failed to load previous snapshot, fallback to full backup")
} else {
previous = &snap
log.Infof("Using provided parent snapshot %s", parentSnapshot)
}
} else {
log.Infof("Searching for parent snapshot")
snap, err := findPreviousSnapshot(ctx, rep, realSource, snapshotTags, nil, log)
if err != nil {
log.WithError(err).Warn("Failed to search previous snapshot, fallback to full backup")
} else {
previous = &snap
log.Infof("Using previous snapshot %s", snap.ID)
}
}
previous = &snap
} else {
log.Infof("Searching for parent snapshot")
log.Info("Forcing full snapshot")
}
snap, err := findPreviousSnapshot(ctx, rep, realSource, snapshotTags, nil, log)
if err != nil {
return parentBackupInfo{}, errors.Wrapf(err, "error searching previous snapshot")
parentInfo := parentBackupInfo{}
if previous != nil {
if previous.Tags == nil {
log.Warnf("No tag from parent snapshot %s, fallback to full backup", previous.ID)
} else if previous.Tags[uploader.CBTChangeIDTag] == "" {
log.Warnf("No ChangeID tag from parent snapshot %s, fallback to full backup", previous.ID)
} else if previous.Tags[uploader.CBTVolumeIDTag] == "" {
log.Warnf("No VolumeID tag from parent snapshot %s, fallback to full backup", previous.ID)
} else if previous.Tags[uploader.CBTVolumeIDTag] != volumeID {
log.Warnf("VolumeID %s from parent snapshot %s is not expected as %s, fallback to full backup", previous.Tags[uploader.CBTVolumeIDTag], previous.ID, volumeID)
} else if obj, err := loadObjectFromSnapshot(ctx, rep, previous); err != nil {
log.WithError(err).Warnf("Failed to load object from parent snapshot %s, fallback to full backup", previous.ID)
} else {
parentInfo.parentObject = obj
parentInfo.changeID = previous.Tags[uploader.CBTChangeIDTag]
parentInfo.volumeID = previous.Tags[uploader.CBTVolumeIDTag]
log.Infof("Using parent snapshot %s, start time %v, end time %v, description %s", previous.ID, previous.StartTime, previous.EndTime, previous.Description)
}
previous = &snap
}
if previous.Tags == nil {
return parentBackupInfo{}, errors.Errorf("no tag from parent snapshot %s", previous.ID)
}
if previous.Tags[uploader.CBTChangeIDTag] == "" {
return parentBackupInfo{}, errors.Errorf("no ChangeID tag from parent snapshot %s", previous.ID)
}
if previous.Tags[uploader.CBTVolumeIDTag] == "" {
return parentBackupInfo{}, errors.Errorf("no VolumeID tag from parent snapshot %s", previous.ID)
}
if previous.Tags[uploader.CBTVolumeIDTag] != volumeID {
return parentBackupInfo{}, errors.Errorf("VolumeID %s from parent snapshot %s is not expected as %s", previous.Tags[uploader.CBTVolumeIDTag], previous.ID, volumeID)
}
obj, err := loadObjectFromSnapshot(ctx, rep, previous)
if err != nil {
return parentBackupInfo{}, errors.Errorf("error loading object from parent snapshot %s", previous.ID)
}
log.Infof("Using parent snapshot %s, start time %v, end time %v, description %s", previous.ID, previous.StartTime, previous.EndTime, previous.Description)
return parentBackupInfo{
parentObject: obj,
changeID: previous.Tags[uploader.CBTChangeIDTag],
+3 -1
View File
@@ -351,6 +351,7 @@ func TestSnapshotSource(t *testing.T) {
func TestGetParentBackupInfoLogsDiscoveredParentID(t *testing.T) {
const volumeID = "vol-123"
const realSource = "/test/source"
const parentSnapID = "snap-parent-42"
const rootObj = "root-obj-42"
snapshotTags := map[string]string{
@@ -364,6 +365,7 @@ func TestGetParentBackupInfoLogsDiscoveredParentID(t *testing.T) {
repo := udmrepomocks.NewBackupRepo(t)
repo.On("ListSnapshot", mock.Anything, realSource).
Return([]udmrepo.Snapshot{{
ID: parentSnapID,
RootObject: udmrepo.ObjectMetadata{ID: rootObj},
Tags: map[string]string{
uploader.CBTChangeIDTag: "cid-abc",
@@ -389,7 +391,7 @@ func TestGetParentBackupInfoLogsDiscoveredParentID(t *testing.T) {
for _, entry := range hook.AllEntries() {
if strings.HasPrefix(entry.Message, "Using parent snapshot ") {
found = true
assert.Contains(t, entry.Message, rootObj,
assert.Contains(t, entry.Message, parentSnapID,
"parent-selection message must name the discovered snapshot, got %q", entry.Message)
}
}
+5 -5
View File
@@ -167,17 +167,17 @@ func (blkup *blockUploader) Restore(snapshot udmrepo.Snapshot, dest destInfo, bi
meta, err := blkup.repoWriter.ReadMetadata(blkup.ctx, snapshot.RootObject.ID)
if err != nil {
return 0, 0, errors.Wrapf(err, "error reading snapshot metadata for %s", snapshot.Description)
return 0, 0, errors.Wrapf(err, "error reading snapshot metadata for %s", snapshot.ID)
}
if len(meta.SubObjects) != 1 {
return 0, 0, errors.Errorf("unexpected number of bdev object (%d) for snapshot %s", len(meta.SubObjects), snapshot.Description)
return 0, 0, errors.Errorf("unexpected number of bdev object (%d) for snapshot %s", len(meta.SubObjects), snapshot.ID)
}
sourceSize, err := getSourceSize(snapshot)
if err != nil {
sourceSize = meta.SubObjects[0].Size
blkup.log.Warnf("Failed to get source size from snapshot %s, use backup size %v", snapshot.Description, sourceSize)
blkup.log.Warnf("Failed to get source size from snapshot %s, use backup size %v", snapshot.ID, sourceSize)
}
if sourceSize > meta.SubObjects[0].Size {
@@ -667,11 +667,11 @@ func loadObjectFromSnapshot(ctx context.Context, rep udmrepo.BackupRepo, snapsho
meta, err := rep.ReadMetadata(ctx, snapshot.RootObject.ID)
if err != nil {
return "", errors.Wrapf(err, "error reading snapshot metadata for %s", snapshot.Description)
return "", errors.Wrap(err, "error reading snapshot metadata")
}
if len(meta.SubObjects) != 1 {
return "", errors.Errorf("unexpected number of bdev object (%d) for snapshot %s", len(meta.SubObjects), snapshot.Description)
return "", errors.Errorf("unexpected number of bdev object (%d)", len(meta.SubObjects))
}
return meta.SubObjects[0].ID, nil