mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-08-21 14:46:07 +00:00
Improvements to BSL logic
Signed-off-by: Carlisia <carlisia@vmware.com>
This commit is contained in:
@@ -343,8 +343,15 @@ func (c *backupController) prepareBackupRequest(backup *velerov1api.Backup) *pkg
|
||||
// calculate expiration
|
||||
request.Status.Expiration = &metav1.Time{Time: c.clock.Now().Add(request.Spec.TTL.Duration)}
|
||||
|
||||
// default storage location if not specified
|
||||
if request.Spec.DefaultVolumesToRestic == nil {
|
||||
request.Spec.DefaultVolumesToRestic = &c.defaultVolumesToRestic
|
||||
}
|
||||
|
||||
// find which storage location to use
|
||||
var serverSpecified bool
|
||||
if request.Spec.StorageLocation == "" {
|
||||
// when the user doesn't specify a location, use the server default unless there is an existing BSL marked as default
|
||||
// TODO(2.0) c.defaultBackupLocation will be deprecated
|
||||
request.Spec.StorageLocation = c.defaultBackupLocation
|
||||
|
||||
locationList, err := storage.ListBackupStorageLocations(context.Background(), c.kbClient, request.Namespace)
|
||||
@@ -356,10 +363,32 @@ func (c *backupController) prepareBackupRequest(backup *velerov1api.Backup) *pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
serverSpecified = true
|
||||
}
|
||||
|
||||
if request.Spec.DefaultVolumesToRestic == nil {
|
||||
request.Spec.DefaultVolumesToRestic = &c.defaultVolumesToRestic
|
||||
// get the storage location, and store the BackupStorageLocation API obj on the request
|
||||
storageLocation := &velerov1api.BackupStorageLocation{}
|
||||
if err := c.kbClient.Get(context.Background(), kbclient.ObjectKey{
|
||||
Namespace: request.Namespace,
|
||||
Name: request.Spec.StorageLocation,
|
||||
}, storageLocation); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
if serverSpecified {
|
||||
// TODO(2.0) remove this. For now, without mentioning "server default" it could be confusing trying to grasp where the default came from.
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("an existing backup storage location wasn't specified at backup creation time and the server default '%s' doesn't exist. Please address this issue (see `velero backup-location -h` for options) and create a new backup. Error: %v", request.Spec.StorageLocation, err))
|
||||
} else {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("an existing backup storage location wasn't specified at backup creation time and the default '%s' wasn't found. Please address this issue (see `velero backup-location -h` for options) and create a new backup. Error: %v", request.Spec.StorageLocation, err))
|
||||
}
|
||||
} else {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("error getting backup storage location: %v", err))
|
||||
}
|
||||
} else {
|
||||
request.StorageLocation = storageLocation
|
||||
|
||||
if request.StorageLocation.Spec.AccessMode == velerov1api.BackupStorageLocationAccessModeReadOnly {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors,
|
||||
fmt.Sprintf("backup can't be created because backup storage location %s is currently in read-only mode", request.StorageLocation.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// add the storage location as a label for easy filtering later.
|
||||
@@ -368,6 +397,18 @@ func (c *backupController) prepareBackupRequest(backup *velerov1api.Backup) *pkg
|
||||
}
|
||||
request.Labels[velerov1api.StorageLocationLabel] = label.GetValidName(request.Spec.StorageLocation)
|
||||
|
||||
// validate and get the backup's VolumeSnapshotLocations, and store the
|
||||
// VolumeSnapshotLocation API objs on the request
|
||||
if locs, errs := c.validateAndGetSnapshotLocations(request.Backup); len(errs) > 0 {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, errs...)
|
||||
} else {
|
||||
request.Spec.VolumeSnapshotLocations = nil
|
||||
for _, loc := range locs {
|
||||
request.Spec.VolumeSnapshotLocations = append(request.Spec.VolumeSnapshotLocations, loc.Name)
|
||||
request.SnapshotLocations = append(request.SnapshotLocations, loc)
|
||||
}
|
||||
}
|
||||
|
||||
// Getting all information of cluster version - useful for future skip-level migration
|
||||
if request.Annotations == nil {
|
||||
request.Annotations = make(map[string]string)
|
||||
@@ -386,37 +427,6 @@ func (c *backupController) prepareBackupRequest(backup *velerov1api.Backup) *pkg
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("Invalid included/excluded namespace lists: %v", err))
|
||||
}
|
||||
|
||||
// validate the storage location, and store the BackupStorageLocation API obj on the request
|
||||
storageLocation := &velerov1api.BackupStorageLocation{}
|
||||
if err := c.kbClient.Get(context.Background(), kbclient.ObjectKey{
|
||||
Namespace: request.Namespace,
|
||||
Name: request.Spec.StorageLocation,
|
||||
}, storageLocation); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("a BackupStorageLocation CRD with the name specified in the backup spec needs to be created before this backup can be executed. Error: %v", err))
|
||||
} else {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("error getting backup storage location: %v", err))
|
||||
}
|
||||
} else {
|
||||
request.StorageLocation = storageLocation
|
||||
|
||||
if request.StorageLocation.Spec.AccessMode == velerov1api.BackupStorageLocationAccessModeReadOnly {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors,
|
||||
fmt.Sprintf("backup can't be created because backup storage location %s is currently in read-only mode", request.StorageLocation.Name))
|
||||
}
|
||||
}
|
||||
// validate and get the backup's VolumeSnapshotLocations, and store the
|
||||
// VolumeSnapshotLocation API objs on the request
|
||||
if locs, errs := c.validateAndGetSnapshotLocations(request.Backup); len(errs) > 0 {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, errs...)
|
||||
} else {
|
||||
request.Spec.VolumeSnapshotLocations = nil
|
||||
for _, loc := range locs {
|
||||
request.Spec.VolumeSnapshotLocations = append(request.Spec.VolumeSnapshotLocations, loc.Name)
|
||||
request.SnapshotLocations = append(request.SnapshotLocations, loc)
|
||||
}
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ func TestProcessBackupValidationFailures(t *testing.T) {
|
||||
{
|
||||
name: "non-existent backup location fails validation",
|
||||
backup: defaultBackup().StorageLocation("nonexistent").Result(),
|
||||
expectedErrs: []string{"a BackupStorageLocation CRD with the name specified in the backup spec needs to be created before this backup can be executed. Error: backupstoragelocations.velero.io \"nonexistent\" not found"},
|
||||
expectedErrs: []string{"an existing backup storage location wasn't specified at backup creation time and the default 'nonexistent' wasn't found. Please address this issue (see `velero backup-location -h` for options) and create a new backup. Error: backupstoragelocations.velero.io \"nonexistent\" not found"},
|
||||
},
|
||||
{
|
||||
name: "backup for read-only backup location fails validation",
|
||||
|
||||
@@ -81,6 +81,7 @@ func (r *BackupStorageLocationReconciler) Reconcile(req ctrl.Request) (ctrl.Resu
|
||||
isDefault := location.Spec.Default
|
||||
log := r.Log.WithField("controller", BackupStorageLocation).WithField(BackupStorageLocation, location.Name)
|
||||
|
||||
// TODO(2.0) remove this check since the server default will be deprecated
|
||||
if !defaultFound && location.Name == r.DefaultBackupLocationInfo.StorageLocation {
|
||||
// For backward-compatible, to configure the backup storage location as the default if
|
||||
// none of the BSLs be marked as the default and the BSL name matches against the
|
||||
@@ -89,7 +90,7 @@ func (r *BackupStorageLocationReconciler) Reconcile(req ctrl.Request) (ctrl.Resu
|
||||
defaultFound = true
|
||||
}
|
||||
|
||||
if !storage.IsReadyToValidate(location.Spec.ValidationFrequency, location.Status.LastValidationTime, r.DefaultBackupLocationInfo, log) {
|
||||
if !storage.IsReadyToValidate(location.Spec.ValidationFrequency, location.Status.LastValidationTime, r.DefaultBackupLocationInfo.ServerValidationFrequency, log) {
|
||||
log.Debug("Validation not required, skipping...")
|
||||
continue
|
||||
}
|
||||
@@ -165,11 +166,11 @@ func (r *BackupStorageLocationReconciler) logReconciledPhase(defaultFound bool,
|
||||
log.Errorf("Current backup storage locations available/unavailable/unknown: %v/%v/%v)", numAvailable, numUnavailable, numUnknown)
|
||||
}
|
||||
} else if numUnavailable > 0 { // some but not all BSL unavailable
|
||||
log.Warnf("Invalid backup storage locations detected: available/unavailable/unknown: %v/%v/%v, %s)", numAvailable, numUnavailable, numUnknown, strings.Join(errs, "; "))
|
||||
log.Warnf("Unavailable backup storage locations detected: available/unavailable/unknown: %v/%v/%v, %s)", numAvailable, numUnavailable, numUnknown, strings.Join(errs, "; "))
|
||||
}
|
||||
|
||||
if !defaultFound {
|
||||
log.Warn("The default backup storage location was not found; for convenience, be sure to create one or make another backup location that is designated as the default")
|
||||
log.Warn("There is no existing backup storage location set as default. Please see `velero backup-location -h` for options.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ var _ = Describe("Backup Storage Location Reconciler", func() {
|
||||
Ctx: ctx,
|
||||
Client: fake.NewFakeClientWithScheme(scheme.Scheme, locations),
|
||||
DefaultBackupLocationInfo: storage.DefaultBackupLocationInfo{
|
||||
StorageLocation: "location-1",
|
||||
StoreValidationFrequency: 0,
|
||||
StorageLocation: "location-1",
|
||||
ServerValidationFrequency: 0,
|
||||
},
|
||||
NewPluginManager: func(logrus.FieldLogger) clientmgmt.Manager { return pluginManager },
|
||||
NewBackupStore: func(loc *velerov1api.BackupStorageLocation, _ persistence.ObjectStoreGetter, _ logrus.FieldLogger) (persistence.BackupStore, error) {
|
||||
@@ -156,8 +156,8 @@ var _ = Describe("Backup Storage Location Reconciler", func() {
|
||||
Ctx: ctx,
|
||||
Client: fake.NewFakeClientWithScheme(scheme.Scheme, locations),
|
||||
DefaultBackupLocationInfo: storage.DefaultBackupLocationInfo{
|
||||
StorageLocation: "default",
|
||||
StoreValidationFrequency: 0,
|
||||
StorageLocation: "default",
|
||||
ServerValidationFrequency: 0,
|
||||
},
|
||||
NewPluginManager: func(logrus.FieldLogger) clientmgmt.Manager { return pluginManager },
|
||||
NewBackupStore: func(loc *velerov1api.BackupStorageLocation, _ persistence.ObjectStoreGetter, _ logrus.FieldLogger) (persistence.BackupStore, error) {
|
||||
@@ -229,8 +229,8 @@ var _ = Describe("Backup Storage Location Reconciler", func() {
|
||||
Ctx: ctx,
|
||||
Client: fake.NewFakeClientWithScheme(scheme.Scheme, locations),
|
||||
DefaultBackupLocationInfo: storage.DefaultBackupLocationInfo{
|
||||
StorageLocation: "default",
|
||||
StoreValidationFrequency: 0,
|
||||
StorageLocation: "default",
|
||||
ServerValidationFrequency: 0,
|
||||
},
|
||||
NewPluginManager: func(logrus.FieldLogger) clientmgmt.Manager { return pluginManager },
|
||||
NewBackupStore: func(loc *velerov1api.BackupStorageLocation, _ persistence.ObjectStoreGetter, _ logrus.FieldLogger) (persistence.BackupStore, error) {
|
||||
|
||||
@@ -88,7 +88,6 @@ type restoreController struct {
|
||||
kbClient client.Client
|
||||
snapshotLocationLister velerov1listers.VolumeSnapshotLocationLister
|
||||
restoreLogLevel logrus.Level
|
||||
defaultBackupLocation string
|
||||
metrics *metrics.ServerMetrics
|
||||
logFormat logging.Format
|
||||
clock clock.Clock
|
||||
|
||||
Reference in New Issue
Block a user