Skip to content

Commit

Permalink
kopia pvbr update
Browse files Browse the repository at this point in the history
Signed-off-by: Lyndon-Li <[email protected]>
  • Loading branch information
Lyndon-Li committed Sep 1, 2022
1 parent 21d87c0 commit 2590492
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 40 deletions.
2 changes: 1 addition & 1 deletion config/crd/v1/bases/velero.io_backuprepositories.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ spec:
repositoryType:
description: RepositoryType indicates the type of the backend repository
enum:
- unified
- kopia
- restic
- ""
type: string
Expand Down
2 changes: 1 addition & 1 deletion config/crd/v1/crds/crds.go

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions pkg/apis/velero/v1/backup_repository_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type BackupRepositorySpec struct {
BackupStorageLocation string `json:"backupStorageLocation"`

// RepositoryType indicates the type of the backend repository
// +kubebuilder:validation:Enum=unified;restic;""
// +kubebuilder:validation:Enum=kopia;restic;""
// +optional
RepositoryType string `json:"repositoryType"`

Expand All @@ -52,8 +52,8 @@ const (
BackupRepositoryPhaseReady BackupRepositoryPhase = "Ready"
BackupRepositoryPhaseNotReady BackupRepositoryPhase = "NotReady"

BackupRepositoryTypeRestic string = "restic"
BackupRepositoryTypeUnified string = "unified"
BackupRepositoryTypeRestic string = "restic"
BackupRepositoryTypeKopia string = "kopia"
)

// BackupRepositoryStatus is the current status of a BackupRepository.
Expand Down
8 changes: 4 additions & 4 deletions pkg/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type kubernetesBackupper struct {
resticTimeout time.Duration
defaultVolumesToRestic bool
clientPageSize int
pvbrUploaderType string
uploaderType string
}

func (i *itemKey) String() string {
Expand All @@ -105,7 +105,7 @@ func NewKubernetesBackupper(
resticTimeout time.Duration,
defaultVolumesToRestic bool,
clientPageSize int,
pvbrUploaderType string,
uploaderType string,
) (Backupper, error) {
return &kubernetesBackupper{
backupClient: backupClient,
Expand All @@ -116,7 +116,7 @@ func NewKubernetesBackupper(
resticTimeout: resticTimeout,
defaultVolumesToRestic: defaultVolumesToRestic,
clientPageSize: clientPageSize,
pvbrUploaderType: pvbrUploaderType,
uploaderType: uploaderType,
}, nil
}

Expand Down Expand Up @@ -239,7 +239,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers(log logrus.FieldLogger,

var resticBackupper podvolume.Backupper
if kb.resticBackupperFactory != nil {
resticBackupper, err = kb.resticBackupperFactory.NewBackupper(ctx, backupRequest.Backup, kb.pvbrUploaderType)
resticBackupper, err = kb.resticBackupperFactory.NewBackupper(ctx, backupRequest.Backup, kb.uploaderType)
if err != nil {
return errors.WithStack(err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func NewCommand(f client.Factory) *cobra.Command {
command.Flags().StringVar(&config.profilerAddress, "profiler-address", config.profilerAddress, "The address to expose the pprof profiler.")
command.Flags().DurationVar(&config.resourceTerminatingTimeout, "terminating-resource-timeout", config.resourceTerminatingTimeout, "How long to wait on persistent volumes and namespaces to terminate during a restore before timing out.")
command.Flags().DurationVar(&config.defaultBackupTTL, "default-backup-ttl", config.defaultBackupTTL, "How long to wait by default before backups can be garbage collected.")
command.Flags().DurationVar(&config.repoMaintenanceFrequency, "default-restic-prune-frequency", config.repoMaintenanceFrequency, "How often 'restic prune' is run for restic repositories by default.")
command.Flags().DurationVar(&config.repoMaintenanceFrequency, "default-restic-prune-frequency", config.repoMaintenanceFrequency, "How often 'prune' is run for backup repositories by default.")
command.Flags().DurationVar(&config.garbageCollectionFrequency, "garbage-collection-frequency", config.garbageCollectionFrequency, "How often garbage collection is run for expired backups.")
command.Flags().BoolVar(&config.defaultVolumesToRestic, "default-volumes-to-restic", config.defaultVolumesToRestic, "Backup all volumes with restic by default.")
command.Flags().StringVar(&config.uploaderType, "uploader-type", config.uploaderType, "Type of uploader to handle the transfer of data of pod volumes")
Expand Down
15 changes: 1 addition & 14 deletions pkg/controller/backup_deletion_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,18 +508,5 @@ func getSnapshotsInBackup(ctx context.Context, backup *velerov1api.Backup, kbCli
return nil, errors.WithStack(err)
}

var res []repository.SnapshotIdentifier
for _, item := range podVolumeBackups.Items {
if item.Status.SnapshotID == "" {
continue
}
res = append(res, repository.SnapshotIdentifier{
VolumeNamespace: item.Spec.Pod.Namespace,
BackupStorageLocation: backup.Spec.StorageLocation,
SnapshotID: item.Status.SnapshotID,
RepositoryType: podvolume.GetRepositoryTypeFromUploaderType(item.Spec.UploaderType),
})
}

return res, nil
return podvolume.GetSnapshotIdentifier(podVolumeBackups), nil
}
3 changes: 3 additions & 0 deletions pkg/controller/backup_deletion_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -771,10 +771,12 @@ func TestGetSnapshotsInBackup(t *testing.T) {
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-3",
RepositoryType: "restic",
},
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-4",
RepositoryType: "restic",
},
},
},
Expand Down Expand Up @@ -822,6 +824,7 @@ func TestGetSnapshotsInBackup(t *testing.T) {
{
VolumeNamespace: "ns-1",
SnapshotID: "snap-3",
RepositoryType: "restic",
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/podvolume/backupper.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (b *backupper) BackupPodVolumes(backup *velerov1api.Backup, pod *corev1api.
return nil, nil
}

repositoryType := GetRepositoryTypeFromUploaderType(b.uploaderType)
repositoryType := getRepositoryType(b.uploaderType)
if repositoryType == "" {
err := errors.New("invalid repository type")
return nil, []error{err}
Expand Down
2 changes: 1 addition & 1 deletion pkg/podvolume/restorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func newRestorer(
}

func (r *restorer) RestorePodVolumes(data RestoreData) []error {
volumesToRestore := GetVolumeBackupInfoForPod(data.PodVolumeBackups, data.Pod, data.SourceNamespace)
volumesToRestore := getVolumeBackupInfoForPod(data.PodVolumeBackups, data.Pod, data.SourceNamespace)
if len(volumesToRestore) == 0 {
return nil
}
Expand Down
53 changes: 44 additions & 9 deletions pkg/podvolume/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/repository"
"github.com/vmware-tanzu/velero/pkg/uploader"
)

Expand Down Expand Up @@ -59,7 +60,7 @@ type VolumeBackupInfo struct {
// GetVolumeBackupsForPod returns a map, of volume name -> snapshot id,
// of the PodVolumeBackups that exist for the provided pod.
func GetVolumeBackupsForPod(podVolumeBackups []*velerov1api.PodVolumeBackup, pod *corev1api.Pod, sourcePodNs string) map[string]string {
volumeBkInfo := GetVolumeBackupInfoForPod(podVolumeBackups, pod, sourcePodNs)
volumeBkInfo := getVolumeBackupInfoForPod(podVolumeBackups, pod, sourcePodNs)
if volumeBkInfo == nil {
return nil
}
Expand All @@ -72,9 +73,9 @@ func GetVolumeBackupsForPod(podVolumeBackups []*velerov1api.PodVolumeBackup, pod
return volumes
}

// GetVolumeBackupInfoForPod returns a map, of volume name -> VolumeBackupInfo,
// getVolumeBackupInfoForPod returns a map, of volume name -> VolumeBackupInfo,
// of the PodVolumeBackups that exist for the provided pod.
func GetVolumeBackupInfoForPod(podVolumeBackups []*velerov1api.PodVolumeBackup, pod *corev1api.Pod, sourcePodNs string) map[string]VolumeBackupInfo {
func getVolumeBackupInfoForPod(podVolumeBackups []*velerov1api.PodVolumeBackup, pod *corev1api.Pod, sourcePodNs string) map[string]VolumeBackupInfo {
volumes := make(map[string]VolumeBackupInfo)

for _, pvb := range podVolumeBackups {
Expand All @@ -97,8 +98,8 @@ func GetVolumeBackupInfoForPod(podVolumeBackups []*velerov1api.PodVolumeBackup,

volumes[pvb.Spec.Volume] = VolumeBackupInfo{
SnapshotID: pvb.Status.SnapshotID,
UploaderType: pvb.Spec.UploaderType,
RepositoryType: GetRepositoryTypeFromUploaderType(pvb.Spec.UploaderType),
UploaderType: getUploaderTypeOrDefault(pvb.Spec.UploaderType),
RepositoryType: getRepositoryType(pvb.Spec.UploaderType),
}
}

Expand All @@ -118,13 +119,47 @@ func GetVolumeBackupInfoForPod(podVolumeBackups []*velerov1api.PodVolumeBackup,
return volumes
}

// GetRepositoryTypeFromUploaderType returns the repository type associated with the uploader for PodVolumeBackups
func GetRepositoryTypeFromUploaderType(uploaderType string) string {
func GetSnapshotIdentifier(podVolumeBackups *velerov1api.PodVolumeBackupList) []repository.SnapshotIdentifier {
var res []repository.SnapshotIdentifier
for _, item := range podVolumeBackups.Items {
if item.Status.SnapshotID == "" {
continue
}

res = append(res, repository.SnapshotIdentifier{
VolumeNamespace: item.Spec.Pod.Namespace,
BackupStorageLocation: item.Spec.BackupStorageLocation,
SnapshotID: item.Status.SnapshotID,
RepositoryType: getRepositoryType(item.Spec.UploaderType),
})
}

return res
}

func getUploaderTypeOrDefault(uploaderType string) string {
if uploaderType != "" {
return uploaderType
} else {
return uploader.ResticType
}
}

// getRepositoryType returns the hardcode repositoryType for different backup methods - Restic or Kopia,uploaderType
// indicates the method.
// For Restic backup method, it is always hardcode to BackupRepositoryTypeRestic, never changed.
// For Kopia backup method, this means we hardcode repositoryType as BackupRepositoryTypeKopia for Unified Repo,
// at present (Kopia backup method is using Unified Repo). However, it doesn't mean we could deduce repositoryType
// from uploaderType for Unified Repo.
// TODO: post v1.10, refactor this function for Kopia backup method. In future, when we have multiple implementations of
// Unified Repo (besides Kopia), we will add the repositoryType to BSL, because by then, we are not able to hardcode
// the repositoryType to BackupRepositoryTypeKopia for Unified Repo.
func getRepositoryType(uploaderType string) string {
switch uploaderType {
case uploader.ResticType:
case "", uploader.ResticType:
return velerov1api.BackupRepositoryTypeRestic
case uploader.KopiaType:
return velerov1api.BackupRepositoryTypeUnified
return velerov1api.BackupRepositoryTypeKopia
default:
return ""
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/repository/ensurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (r *RepositoryEnsurer) EnsureRepo(ctx context.Context, namespace, volumeNam
// It's only safe to have one instance of this method executing concurrently for a
// given volumeNamespace + backupLocation + repositoryType, so synchronize based on that. It's fine
// to run concurrently for *different* namespaces/locations. If you had 2 goroutines
// running this for the same inputs, both might find no ResticRepository exists, then
// running this for the same inputs, both might find no BackupRepository exists, then
// both would create new ones for the same namespace/location.
//
// This issue could probably be avoided if we had a deterministic name for
Expand All @@ -143,7 +143,7 @@ func (r *RepositoryEnsurer) EnsureRepo(ctx context.Context, namespace, volumeNam
return nil, errors.WithStack(err)
}
if len(repos) > 1 {
return nil, errors.Errorf("more than one ResticRepository found for workload namespace %q, backup storage location %q, repository type %q", volumeNamespace, backupLocation, repositoryType)
return nil, errors.Errorf("more than one BackupRepository found for workload namespace %q, backup storage location %q, repository type %q", volumeNamespace, backupLocation, repositoryType)
}
if len(repos) == 1 {
if repos[0].Status.Phase != velerov1api.BackupRepositoryPhaseReady {
Expand Down
6 changes: 3 additions & 3 deletions pkg/repository/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func NewManager(
}

mgr.providers[velerov1api.BackupRepositoryTypeRestic] = provider.NewResticRepositoryProvider(credentialFileStore, mgr.fileSystem, mgr.log)
mgr.providers[velerov1api.BackupRepositoryTypeUnified] = provider.NewUnifiedRepoProvider(credentials.CredentialGetter{
mgr.providers[velerov1api.BackupRepositoryTypeKopia] = provider.NewUnifiedRepoProvider(credentials.CredentialGetter{
FromFile: credentialFileStore,
FromSecret: credentialSecretStore,
}, mgr.log)
Expand Down Expand Up @@ -211,8 +211,8 @@ func (m *manager) getRepositoryProvider(repo *velerov1api.BackupRepository) (pro
switch repo.Spec.RepositoryType {
case "", velerov1api.BackupRepositoryTypeRestic:
return m.providers[velerov1api.BackupRepositoryTypeRestic], nil
case velerov1api.BackupRepositoryTypeUnified:
return m.providers[velerov1api.BackupRepositoryTypeUnified], nil
case velerov1api.BackupRepositoryTypeKopia:
return m.providers[velerov1api.BackupRepositoryTypeKopia], nil
default:
return nil, fmt.Errorf("failed to get provider for repository %s", repo.Spec.RepositoryType)
}
Expand Down

0 comments on commit 2590492

Please sign in to comment.