@@ -245,6 +245,11 @@ func (r *BackupReconciler) deleteBackupFiles(reqCtx intctrlutil.RequestCtx, back
245245// handleDeletingPhase handles the deletion of backup. It will delete the backup CR
246246// and the backup workload(job).
247247func (r * BackupReconciler ) handleDeletingPhase (reqCtx intctrlutil.RequestCtx , backup * dpv1alpha1.Backup ) (ctrl.Result , error ) {
248+ // delete related backups
249+ if err := r .deleteRelatedBackups (reqCtx , backup ); err != nil {
250+ return intctrlutil .RequeueWithError (err , reqCtx .Log , "" )
251+ }
252+
248253 // if backup phase is Deleting, delete the backup reference workloads,
249254 // backup data stored in backup repository and volume snapshots.
250255 // TODO(ldm): if backup is being used by restore, do not delete it.
@@ -395,28 +400,11 @@ func (r *BackupReconciler) prepareBackupRequest(
395400 if err != nil {
396401 return nil , err
397402 }
398- request .ActionSet = actionSet
399-
400- // check continuous backups should have backupschedule label
401- if request .ActionSet .Spec .BackupType == dpv1alpha1 .BackupTypeContinuous {
402- if _ , ok := request .Labels [dptypes .BackupScheduleLabelKey ]; ! ok {
403- return nil , fmt .Errorf ("continuous backup is only allowed to be created by backupSchedule" )
404- }
405- backupSchedule := & dpv1alpha1.BackupSchedule {}
406- if err := request .Client .Get (reqCtx .Ctx , client.ObjectKey {Name : backup .Labels [dptypes .BackupScheduleLabelKey ],
407- Namespace : backup .Namespace }, backupSchedule ); err != nil {
408- return nil , err
409- }
410- if backupSchedule .Status .Phase != dpv1alpha1 .BackupSchedulePhaseAvailable {
411- return nil , fmt .Errorf ("create continuous backup by failed backupschedule %s/%s" ,
412- backupSchedule .Namespace , backupSchedule .Name )
413- }
414- }
415-
416403 // validate parameters
417404 if err := dputils .ValidateParameters (actionSet , backup .Spec .Parameters , true ); err != nil {
418405 return nil , fmt .Errorf ("fails to validate parameters with actionset %s: %v" , actionSet .Name , err )
419406 }
407+ request .ActionSet = actionSet
420408 }
421409
422410 // check encryption config
@@ -432,13 +420,25 @@ func (r *BackupReconciler) prepareBackupRequest(
432420 }
433421
434422 request .BackupPolicy = backupPolicy
423+ request .BackupMethod = backupMethod
424+
425+ switch dpv1alpha1 .BackupType (request .GetBackupType ()) {
426+ case dpv1alpha1 .BackupTypeIncremental :
427+ request , err = prepare4Incremental (request )
428+ case dpv1alpha1 .BackupTypeContinuous :
429+ err = validateContinuousBackup (backup , reqCtx , request .Client )
430+ }
431+ if err != nil {
432+ return nil , err
433+ }
434+
435435 if ! snapshotVolumes {
436436 // if use volume snapshot, ignore backup repo
437437 if err = HandleBackupRepo (request ); err != nil {
438438 return nil , err
439439 }
440440 }
441- request . BackupMethod = backupMethod
441+
442442 return request , nil
443443}
444444
@@ -527,6 +527,14 @@ func (r *BackupReconciler) patchBackupStatus(
527527 request .Status .Phase = dpv1alpha1 .BackupPhaseRunning
528528 request .Status .StartTimestamp = & metav1.Time {Time : r .clock .Now ().UTC ()}
529529
530+ // set status parent backup and base backup name
531+ if request .ParentBackup != nil {
532+ request .Status .ParentBackupName = request .ParentBackup .Name
533+ }
534+ if request .BaseBackup != nil {
535+ request .Status .BaseBackupName = request .BaseBackup .Name
536+ }
537+
530538 if err = dpbackup .SetExpirationByCreationTime (request .Backup ); err != nil {
531539 return err
532540 }
@@ -751,6 +759,33 @@ func (r *BackupReconciler) deleteExternalResources(
751759 return deleteRelatedObjectList (reqCtx , r .Client , & appsv1.StatefulSetList {}, namespaces , labels )
752760}
753761
762+ // deleteRelatedBackups deletes the related backups.
763+ func (r * BackupReconciler ) deleteRelatedBackups (
764+ reqCtx intctrlutil.RequestCtx ,
765+ backup * dpv1alpha1.Backup ) error {
766+ backupList := & dpv1alpha1.BackupList {}
767+ labels := map [string ]string {
768+ dptypes .BackupPolicyLabelKey : backup .Spec .BackupPolicyName ,
769+ }
770+ if err := r .Client .List (reqCtx .Ctx , backupList ,
771+ client .InNamespace (backup .Namespace ), client .MatchingLabels (labels )); client .IgnoreNotFound (err ) != nil {
772+ return err
773+ }
774+ for i := range backupList .Items {
775+ bp := & backupList .Items [i ]
776+ // delete backups related to the current backup
777+ // files in the related backup's status.path will be deleted by its own associated deleter
778+ if bp .Status .ParentBackupName != backup .Name && bp .Status .BaseBackupName != backup .Name {
779+ continue
780+ }
781+ if err := intctrlutil .BackgroundDeleteObject (r .Client , reqCtx .Ctx , bp ); err != nil {
782+ return err
783+ }
784+ reqCtx .Log .Info ("delete the related backup" , "backup" , fmt .Sprintf ("%s/%s" , bp .Namespace , bp .Name ))
785+ }
786+ return nil
787+ }
788+
754789// PatchBackupObjectMeta patches backup object metaObject include cluster snapshot.
755790func PatchBackupObjectMeta (
756791 original * dpv1alpha1.Backup ,
@@ -922,3 +957,56 @@ func setClusterSnapshotAnnotation(request *dpbackup.Request, cluster *kbappsv1.C
922957 request .Backup .Annotations [constant .ClusterSnapshotAnnotationKey ] = * clusterString
923958 return nil
924959}
960+
961+ // validateContinuousBackup validates the continuous backup.
962+ func validateContinuousBackup (backup * dpv1alpha1.Backup , reqCtx intctrlutil.RequestCtx , cli client.Client ) error {
963+ // validate if the continuous backup is created by a backupSchedule.
964+ if _ , ok := backup .Labels [dptypes .BackupScheduleLabelKey ]; ! ok {
965+ return fmt .Errorf ("continuous backup is only allowed to be created by backupSchedule" )
966+ }
967+ backupSchedule := & dpv1alpha1.BackupSchedule {}
968+ if err := cli .Get (reqCtx .Ctx , client.ObjectKey {Name : backup .Labels [dptypes .BackupScheduleLabelKey ],
969+ Namespace : backup .Namespace }, backupSchedule ); err != nil {
970+ return err
971+ }
972+ if backupSchedule .Status .Phase != dpv1alpha1 .BackupSchedulePhaseAvailable {
973+ return fmt .Errorf ("create continuous backup by failed backupschedule %s/%s" ,
974+ backupSchedule .Namespace , backupSchedule .Name )
975+ }
976+ return nil
977+ }
978+
979+ // prepare4Incremental prepares for incremental backup
980+ func prepare4Incremental (request * dpbackup.Request ) (* dpbackup.Request , error ) {
981+ // get and validate parent backup
982+ parentBackup , err := GetParentBackup (request .Ctx , request .Client , request .Backup , request .BackupMethod )
983+ if err != nil {
984+ return nil , err
985+ }
986+ parentBackupType , err := dputils .GetBackupTypeByMethodName (request .RequestCtx ,
987+ request .Client , parentBackup .Spec .BackupMethod , request .BackupPolicy )
988+ if err != nil {
989+ return nil , err
990+ }
991+ request .ParentBackup = parentBackup
992+ // get and validate base backup
993+ switch parentBackupType {
994+ case dpv1alpha1 .BackupTypeFull :
995+ request .BaseBackup = request .ParentBackup
996+ case dpv1alpha1 .BackupTypeIncremental :
997+ baseBackup := & dpv1alpha1.Backup {}
998+ baseBackupName := request .ParentBackup .Status .BaseBackupName
999+ if len (baseBackupName ) == 0 {
1000+ return nil , fmt .Errorf ("backup %s/%s base backup name is empty" ,
1001+ request .ParentBackup .Namespace , request .ParentBackup .Name )
1002+ }
1003+ if err := request .Client .Get (request .Ctx , client.ObjectKey {Name : baseBackupName ,
1004+ Namespace : request .ParentBackup .Namespace }, baseBackup ); err != nil {
1005+ return nil , fmt .Errorf ("failed to get base backup %s/%s: %w" , request .ParentBackup .Namespace , baseBackupName , err )
1006+ }
1007+ request .BaseBackup = baseBackup
1008+ default :
1009+ return nil , fmt .Errorf ("parent backup type is %s, but only full and incremental backup are supported" , parentBackupType )
1010+ }
1011+ return request , nil
1012+ }
0 commit comments