mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-09-19 22:44:21 +00:00
Merge branch 'main' into vgdp-ms-resume-pvb-pvr
This commit is contained in:
@@ -823,7 +823,8 @@ func (kb *kubernetesBackupper) waitUntilPVBsProcessed(ctx context.Context, log l
|
||||
}
|
||||
for _, pvb := range pvbs {
|
||||
pvbMap[pvb] = pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseCompleted ||
|
||||
pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed
|
||||
pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed ||
|
||||
pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseCanceled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -840,7 +841,8 @@ func (kb *kubernetesBackupper) waitUntilPVBsProcessed(ctx context.Context, log l
|
||||
continue
|
||||
}
|
||||
if updatedPVB.Status.Phase == velerov1api.PodVolumeBackupPhaseCompleted ||
|
||||
updatedPVB.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed {
|
||||
updatedPVB.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed ||
|
||||
updatedPVB.Status.Phase == velerov1api.PodVolumeBackupPhaseCanceled {
|
||||
pvbMap[pvb] = true
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -786,7 +786,11 @@ func describePodVolumeBackups(d *Describer, details bool, podVolumeBackups []vel
|
||||
for _, phase := range []string{
|
||||
string(velerov1api.PodVolumeBackupPhaseCompleted),
|
||||
string(velerov1api.PodVolumeBackupPhaseFailed),
|
||||
string(velerov1api.PodVolumeBackupPhaseCanceled),
|
||||
"In Progress",
|
||||
string(velerov1api.PodVolumeBackupPhaseCanceling),
|
||||
string(velerov1api.PodVolumeBackupPhasePrepared),
|
||||
string(velerov1api.PodVolumeBackupPhaseAccepted),
|
||||
string(velerov1api.PodVolumeBackupPhaseNew),
|
||||
} {
|
||||
if len(backupsByPhase[phase]) == 0 {
|
||||
@@ -822,7 +826,11 @@ func groupByPhase(backups []velerov1api.PodVolumeBackup) map[string][]velerov1ap
|
||||
phaseToGroup := map[velerov1api.PodVolumeBackupPhase]string{
|
||||
velerov1api.PodVolumeBackupPhaseCompleted: string(velerov1api.PodVolumeBackupPhaseCompleted),
|
||||
velerov1api.PodVolumeBackupPhaseFailed: string(velerov1api.PodVolumeBackupPhaseFailed),
|
||||
velerov1api.PodVolumeBackupPhaseCanceled: string(velerov1api.PodVolumeBackupPhaseCanceled),
|
||||
velerov1api.PodVolumeBackupPhaseInProgress: "In Progress",
|
||||
velerov1api.PodVolumeBackupPhaseCanceling: string(velerov1api.PodVolumeBackupPhaseCanceling),
|
||||
velerov1api.PodVolumeBackupPhasePrepared: string(velerov1api.PodVolumeBackupPhasePrepared),
|
||||
velerov1api.PodVolumeBackupPhaseAccepted: string(velerov1api.PodVolumeBackupPhaseAccepted),
|
||||
velerov1api.PodVolumeBackupPhaseNew: string(velerov1api.PodVolumeBackupPhaseNew),
|
||||
"": string(velerov1api.PodVolumeBackupPhaseNew),
|
||||
}
|
||||
|
||||
@@ -572,6 +572,54 @@ func TestDescribePodVolumeBackups(t *testing.T) {
|
||||
PodName("pod-2").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-2").Result()
|
||||
pvb3 := builder.ForPodVolumeBackup("test-ns1", "test-pvb3").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseFailed).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-3").
|
||||
PodName("pod-3").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-3").Result()
|
||||
pvb4 := builder.ForPodVolumeBackup("test-ns1", "test-pvb4").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseCanceled).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-4").
|
||||
PodName("pod-4").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-4").Result()
|
||||
pvb5 := builder.ForPodVolumeBackup("test-ns1", "test-pvb5").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseInProgress).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-5").
|
||||
PodName("pod-5").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-5").Result()
|
||||
pvb6 := builder.ForPodVolumeBackup("test-ns1", "test-pvb6").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseCanceling).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-6").
|
||||
PodName("pod-6").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-6").Result()
|
||||
pvb7 := builder.ForPodVolumeBackup("test-ns1", "test-pvb7").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhasePrepared).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-7").
|
||||
PodName("pod-7").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-7").Result()
|
||||
pvb8 := builder.ForPodVolumeBackup("test-ns1", "test-pvb6").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseAccepted).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-8").
|
||||
PodName("pod-8").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-8").Result()
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
@@ -602,6 +650,28 @@ func TestDescribePodVolumeBackups(t *testing.T) {
|
||||
Completed:
|
||||
pod-ns-1/pod-1: vol-1
|
||||
pod-ns-1/pod-2: vol-2
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "all phases with details",
|
||||
inputPVBList: []velerov1api.PodVolumeBackup{*pvb1, *pvb2, *pvb3, *pvb4, *pvb5, *pvb6, *pvb7, *pvb8},
|
||||
inputDetails: true,
|
||||
expect: ` Pod Volume Backups - kopia:
|
||||
Completed:
|
||||
pod-ns-1/pod-1: vol-1
|
||||
pod-ns-1/pod-2: vol-2
|
||||
Failed:
|
||||
pod-ns-1/pod-3: vol-3
|
||||
Canceled:
|
||||
pod-ns-1/pod-4: vol-4
|
||||
In Progress:
|
||||
pod-ns-1/pod-5: vol-5
|
||||
Canceling:
|
||||
pod-ns-1/pod-6: vol-6
|
||||
Prepared:
|
||||
pod-ns-1/pod-7: vol-7
|
||||
Accepted:
|
||||
pod-ns-1/pod-8: vol-8
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -499,7 +499,11 @@ func describePodVolumeBackupsInSF(backups []velerov1api.PodVolumeBackup, details
|
||||
for _, phase := range []string{
|
||||
string(velerov1api.PodVolumeBackupPhaseCompleted),
|
||||
string(velerov1api.PodVolumeBackupPhaseFailed),
|
||||
string(velerov1api.PodVolumeBackupPhaseCanceled),
|
||||
"In Progress",
|
||||
string(velerov1api.PodVolumeBackupPhaseCanceling),
|
||||
string(velerov1api.PodVolumeBackupPhasePrepared),
|
||||
string(velerov1api.PodVolumeBackupPhaseAccepted),
|
||||
string(velerov1api.PodVolumeBackupPhaseNew),
|
||||
} {
|
||||
if len(backupsByPhase[phase]) == 0 {
|
||||
|
||||
@@ -240,6 +240,55 @@ func TestDescribePodVolumeBackupsInSF(t *testing.T) {
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-2").Result()
|
||||
|
||||
pvb3 := builder.ForPodVolumeBackup("test-ns1", "test-pvb3").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseFailed).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-3").
|
||||
PodName("pod-3").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-3").Result()
|
||||
pvb4 := builder.ForPodVolumeBackup("test-ns1", "test-pvb4").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseCanceled).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-4").
|
||||
PodName("pod-4").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-4").Result()
|
||||
pvb5 := builder.ForPodVolumeBackup("test-ns1", "test-pvb5").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseInProgress).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-5").
|
||||
PodName("pod-5").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-5").Result()
|
||||
pvb6 := builder.ForPodVolumeBackup("test-ns1", "test-pvb6").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseCanceling).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-6").
|
||||
PodName("pod-6").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-6").Result()
|
||||
pvb7 := builder.ForPodVolumeBackup("test-ns1", "test-pvb7").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhasePrepared).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-7").
|
||||
PodName("pod-7").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-7").Result()
|
||||
pvb8 := builder.ForPodVolumeBackup("test-ns1", "test-pvb6").
|
||||
UploaderType("kopia").
|
||||
Phase(velerov1api.PodVolumeBackupPhaseAccepted).
|
||||
BackupStorageLocation("bsl-1").
|
||||
Volume("vol-8").
|
||||
PodName("pod-8").
|
||||
PodNamespace("pod-ns-1").
|
||||
SnapshotID("snap-8").Result()
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
inputPVBList []velerov1api.PodVolumeBackup
|
||||
@@ -268,6 +317,40 @@ func TestDescribePodVolumeBackupsInSF(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all phases",
|
||||
inputPVBList: []velerov1api.PodVolumeBackup{*pvb1, *pvb2, *pvb3, *pvb4, *pvb5, *pvb6, *pvb7, *pvb8},
|
||||
inputDetails: true,
|
||||
expect: map[string]any{
|
||||
"podVolumeBackups": map[string]any{
|
||||
"podVolumeBackupsDetails": map[string]any{
|
||||
"Completed": []map[string]string{
|
||||
{"pod-ns-1/pod-1": "vol-1"},
|
||||
{"pod-ns-1/pod-2": "vol-2"},
|
||||
},
|
||||
"Failed": []map[string]string{
|
||||
{"pod-ns-1/pod-3": "vol-3"},
|
||||
},
|
||||
"Canceled": []map[string]string{
|
||||
{"pod-ns-1/pod-4": "vol-4"},
|
||||
},
|
||||
"In Progress": []map[string]string{
|
||||
{"pod-ns-1/pod-5": "vol-5"},
|
||||
},
|
||||
"Canceling": []map[string]string{
|
||||
{"pod-ns-1/pod-6": "vol-6"},
|
||||
},
|
||||
"Prepared": []map[string]string{
|
||||
{"pod-ns-1/pod-7": "vol-7"},
|
||||
},
|
||||
"Accepted": []map[string]string{
|
||||
{"pod-ns-1/pod-8": "vol-8"},
|
||||
},
|
||||
},
|
||||
"uploderType": "kopia",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(tt *testing.T) {
|
||||
|
||||
@@ -362,8 +362,11 @@ func describePodVolumeRestores(d *Describer, restores []velerov1api.PodVolumeRes
|
||||
// go through phases in a specific order
|
||||
for _, phase := range []string{
|
||||
string(velerov1api.PodVolumeRestorePhaseCompleted),
|
||||
string(velerov1api.PodVolumeRestorePhaseCanceled),
|
||||
string(velerov1api.PodVolumeRestorePhaseFailed),
|
||||
"In Progress",
|
||||
string(velerov1api.PodVolumeRestorePhasePrepared),
|
||||
string(velerov1api.PodVolumeRestorePhaseAccepted),
|
||||
string(velerov1api.PodVolumeRestorePhaseNew),
|
||||
} {
|
||||
if len(restoresByPhase[phase]) == 0 {
|
||||
@@ -442,8 +445,11 @@ func groupRestoresByPhase(restores []velerov1api.PodVolumeRestore) map[string][]
|
||||
|
||||
phaseToGroup := map[velerov1api.PodVolumeRestorePhase]string{
|
||||
velerov1api.PodVolumeRestorePhaseCompleted: string(velerov1api.PodVolumeRestorePhaseCompleted),
|
||||
velerov1api.PodVolumeRestorePhaseCanceled: string(velerov1api.PodVolumeRestorePhaseCanceled),
|
||||
velerov1api.PodVolumeRestorePhaseFailed: string(velerov1api.PodVolumeRestorePhaseFailed),
|
||||
velerov1api.PodVolumeRestorePhaseInProgress: "In Progress",
|
||||
velerov1api.PodVolumeRestorePhasePrepared: string(velerov1api.PodVolumeRestorePhasePrepared),
|
||||
velerov1api.PodVolumeRestorePhaseAccepted: string(velerov1api.PodVolumeRestorePhaseAccepted),
|
||||
velerov1api.PodVolumeRestorePhaseNew: string(velerov1api.PodVolumeRestorePhaseNew),
|
||||
"": string(velerov1api.PodVolumeRestorePhaseNew),
|
||||
}
|
||||
|
||||
@@ -426,8 +426,10 @@ func (b *backupper) WaitAllPodVolumesProcessed(log logrus.FieldLogger) []*velero
|
||||
continue
|
||||
}
|
||||
podVolumeBackups = append(podVolumeBackups, pvb)
|
||||
if pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed || pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseCanceled {
|
||||
if pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseFailed {
|
||||
log.Errorf("pod volume backup failed: %s", pvb.Status.Message)
|
||||
} else if pvb.Status.Phase == velerov1api.PodVolumeBackupPhaseCanceled {
|
||||
log.Errorf("pod volume backup canceled: %s", pvb.Status.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +228,10 @@ ForEachVolume:
|
||||
errs = append(errs, errors.New("timed out waiting for all PodVolumeRestores to complete"))
|
||||
break ForEachVolume
|
||||
case res := <-resultsChan:
|
||||
if res.Status.Phase == velerov1api.PodVolumeRestorePhaseFailed || res.Status.Phase == velerov1api.PodVolumeRestorePhaseCanceled {
|
||||
if res.Status.Phase == velerov1api.PodVolumeRestorePhaseFailed {
|
||||
errs = append(errs, errors.Errorf("pod volume restore failed: %s", res.Status.Message))
|
||||
} else if res.Status.Phase == velerov1api.PodVolumeRestorePhaseCanceled {
|
||||
errs = append(errs, errors.Errorf("pod volume restore canceled: %s", res.Status.Message))
|
||||
}
|
||||
tracker.TrackPodVolume(res)
|
||||
case err := <-r.nodeAgentCheck:
|
||||
|
||||
@@ -250,6 +250,7 @@ func TestMaintain(t *testing.T) {
|
||||
tc.returnRepoWriter.On("AlsoLogToContentLog", mock.Anything).Return(nil)
|
||||
tc.returnRepoWriter.On("Close", mock.Anything).Return(nil)
|
||||
tc.returnRepoWriter.On("FindManifests", mock.Anything, mock.Anything).Return(nil, tc.findManifestError)
|
||||
tc.returnRepoWriter.On("ClientOptions").Return(repo.ClientOptions{})
|
||||
}
|
||||
|
||||
err := service.Maintain(ctx, tc.repoOptions)
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/uploader"
|
||||
|
||||
"github.com/kopia/kopia/snapshot/snapshotfs"
|
||||
"github.com/kopia/kopia/snapshot/upload"
|
||||
)
|
||||
|
||||
// Throttle throttles controlle the interval of output result
|
||||
@@ -63,7 +63,7 @@ type Progress struct {
|
||||
outputThrottle Throttle // which control the frequency of update progress
|
||||
updater uploader.ProgressUpdater //which kopia progress will call the UpdateProgress interface, the third party will implement the interface to do the progress update
|
||||
log logrus.FieldLogger // output info into log when backup
|
||||
estimationParam snapshotfs.EstimationParameters
|
||||
estimationParam upload.EstimationParameters
|
||||
}
|
||||
|
||||
func NewProgress(updater uploader.ProgressUpdater, interval time.Duration, log logrus.FieldLogger) *Progress {
|
||||
@@ -73,8 +73,8 @@ func NewProgress(updater uploader.ProgressUpdater, interval time.Duration, log l
|
||||
interval: interval,
|
||||
},
|
||||
updater: updater,
|
||||
estimationParam: snapshotfs.EstimationParameters{
|
||||
Type: snapshotfs.EstimationTypeClassic,
|
||||
estimationParam: upload.EstimationParameters{
|
||||
Type: upload.EstimationTypeClassic,
|
||||
AdaptiveThreshold: 300000,
|
||||
},
|
||||
log: log,
|
||||
@@ -169,7 +169,7 @@ func (p *Progress) ProgressBytes(processedBytes int64, totalBytes int64) {
|
||||
|
||||
func (p *Progress) FinishedFile(fname string, err error) {}
|
||||
|
||||
func (p *Progress) EstimationParameters() snapshotfs.EstimationParameters {
|
||||
func (p *Progress) EstimationParameters() upload.EstimationParameters {
|
||||
return p.estimationParam
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kopia/kopia/snapshot/snapshotfs"
|
||||
"github.com/kopia/kopia/snapshot/upload"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@@ -85,7 +85,7 @@ func NewKopiaUploaderProvider(
|
||||
}
|
||||
|
||||
// CheckContext check context status check if context is timeout or cancel and backup restore once finished it will quit and return
|
||||
func (kp *kopiaProvider) CheckContext(ctx context.Context, finishChan chan struct{}, restoreChan chan struct{}, uploader *snapshotfs.Uploader) {
|
||||
func (kp *kopiaProvider) CheckContext(ctx context.Context, finishChan chan struct{}, restoreChan chan struct{}, uploader *upload.Uploader) {
|
||||
select {
|
||||
case <-finishChan:
|
||||
kp.log.Infof("Action finished")
|
||||
@@ -135,7 +135,7 @@ func (kp *kopiaProvider) RunBackup(
|
||||
"parentSnapshot": parentSnapshot,
|
||||
})
|
||||
repoWriter := kopia.NewShimRepo(kp.bkRepo)
|
||||
kpUploader := snapshotfs.NewUploader(repoWriter)
|
||||
kpUploader := upload.NewUploader(repoWriter)
|
||||
kpUploader.Progress = kopia.NewProgress(updater, backupProgressCheckInterval, log)
|
||||
kpUploader.FailFast = true
|
||||
quit := make(chan struct{})
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/kopia/kopia/repo"
|
||||
"github.com/kopia/kopia/snapshot/snapshotfs"
|
||||
"github.com/kopia/kopia/snapshot/upload"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -172,7 +172,7 @@ func TestCheckContext(t *testing.T) {
|
||||
name string
|
||||
finishChan chan struct{}
|
||||
restoreChan chan struct{}
|
||||
uploader *snapshotfs.Uploader
|
||||
uploader *upload.Uploader
|
||||
expectCancel bool
|
||||
expectBackup bool
|
||||
expectRestore bool
|
||||
@@ -181,7 +181,7 @@ func TestCheckContext(t *testing.T) {
|
||||
name: "FinishChan",
|
||||
finishChan: make(chan struct{}),
|
||||
restoreChan: make(chan struct{}),
|
||||
uploader: &snapshotfs.Uploader{},
|
||||
uploader: &upload.Uploader{},
|
||||
expectCancel: false,
|
||||
expectBackup: false,
|
||||
expectRestore: false,
|
||||
|
||||
@@ -117,7 +117,7 @@ func newConfigCredential(creds map[string]string, options configCredentialOption
|
||||
if username := creds[CredentialKeyUsername]; username != "" {
|
||||
if password := creds[CredentialKeyPassword]; password != "" {
|
||||
return azidentity.NewUsernamePasswordCredential(tenantID, clientID, username, password,
|
||||
&azidentity.UsernamePasswordCredentialOptions{
|
||||
&azidentity.UsernamePasswordCredentialOptions{ //nolint:staticcheck // will be solved by https://github.com/vmware-tanzu/velero/issues/9028
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
})
|
||||
|
||||
@@ -70,7 +70,7 @@ func TestNewCredential(t *testing.T) {
|
||||
os.Clearenv()
|
||||
|
||||
// managed identity credential
|
||||
creds = map[string]string{}
|
||||
creds = map[string]string{CredentialKeyClientID: "clientid"}
|
||||
tokenCredential, err = NewCredential(creds, options)
|
||||
require.NoError(t, err)
|
||||
assert.IsType(t, &azidentity.ManagedIdentityCredential{}, tokenCredential)
|
||||
|
||||
Reference in New Issue
Block a user