@@ -241,6 +241,11 @@ func (r *BackupReconciler) deleteBackupFiles(reqCtx intctrlutil.RequestCtx, back
241241// handleDeletingPhase handles the deletion of backup. It will delete the backup CR
242242// and the backup workload(job).
243243func (r * BackupReconciler ) handleDeletingPhase (reqCtx intctrlutil.RequestCtx , backup * dpv1alpha1.Backup ) (ctrl.Result , error ) {
244+ // delete related backups
245+ if err := r .deleteRelatedBackups (reqCtx , backup ); err != nil {
246+ return intctrlutil .RequeueWithError (err , reqCtx .Log , "" )
247+ }
248+
244249 // if backup phase is Deleting, delete the backup reference workloads,
245250 // backup data stored in backup repository and volume snapshots.
246251 // TODO(ldm): if backup is being used by restore, do not delete it.
@@ -393,22 +398,6 @@ func (r *BackupReconciler) prepareBackupRequest(
393398 return nil , err
394399 }
395400 request .ActionSet = actionSet
396-
397- // check continuous backups should have backupschedule label
398- if request .ActionSet .Spec .BackupType == dpv1alpha1 .BackupTypeContinuous {
399- if _ , ok := request .Labels [dptypes .BackupScheduleLabelKey ]; ! ok {
400- return nil , fmt .Errorf ("continuous backup is only allowed to be created by backupSchedule" )
401- }
402- backupSchedule := & dpv1alpha1.BackupSchedule {}
403- if err := request .Client .Get (reqCtx .Ctx , client.ObjectKey {Name : backup .Labels [dptypes .BackupScheduleLabelKey ],
404- Namespace : backup .Namespace }, backupSchedule ); err != nil {
405- return nil , err
406- }
407- if backupSchedule .Status .Phase != dpv1alpha1 .BackupSchedulePhaseAvailable {
408- return nil , fmt .Errorf ("create continuous backup by failed backupschedule %s/%s" ,
409- backupSchedule .Namespace , backupSchedule .Name )
410- }
411- }
412401 }
413402
414403 // check encryption config
@@ -424,13 +413,25 @@ func (r *BackupReconciler) prepareBackupRequest(
424413 }
425414
426415 request .BackupPolicy = backupPolicy
416+ request .BackupMethod = backupMethod
417+
418+ switch dpv1alpha1 .BackupType (request .GetBackupType ()) {
419+ case dpv1alpha1 .BackupTypeIncremental :
420+ request , err = prepare4Incremental (request )
421+ case dpv1alpha1 .BackupTypeContinuous :
422+ err = validateContinuousBackup (backup , reqCtx , request .Client )
423+ }
424+ if err != nil {
425+ return nil , err
426+ }
427+
427428 if ! snapshotVolumes {
428429 // if use volume snapshot, ignore backup repo
429430 if err = HandleBackupRepo (request ); err != nil {
430431 return nil , err
431432 }
432433 }
433- request . BackupMethod = backupMethod
434+
434435 return request , nil
435436}
436437
@@ -519,6 +520,14 @@ func (r *BackupReconciler) patchBackupStatus(
519520 request .Status .Phase = dpv1alpha1 .BackupPhaseRunning
520521 request .Status .StartTimestamp = & metav1.Time {Time : r .clock .Now ().UTC ()}
521522
523+ // set status parent backup and base backup name
524+ if request .ParentBackup != nil {
525+ request .Status .ParentBackupName = request .ParentBackup .Name
526+ }
527+ if request .BaseBackup != nil {
528+ request .Status .BaseBackupName = request .BaseBackup .Name
529+ }
530+
522531 if err = dpbackup .SetExpirationByCreationTime (request .Backup ); err != nil {
523532 return err
524533 }
@@ -743,6 +752,33 @@ func (r *BackupReconciler) deleteExternalResources(
743752 return deleteRelatedObjectList (reqCtx , r .Client , & appsv1.StatefulSetList {}, namespaces , labels )
744753}
745754
755+ // deleteRelatedBackups deletes the related backups.
756+ func (r * BackupReconciler ) deleteRelatedBackups (
757+ reqCtx intctrlutil.RequestCtx ,
758+ backup * dpv1alpha1.Backup ) error {
759+ backupList := & dpv1alpha1.BackupList {}
760+ labels := map [string ]string {
761+ dptypes .BackupPolicyLabelKey : backup .Spec .BackupPolicyName ,
762+ }
763+ if err := r .Client .List (reqCtx .Ctx , backupList ,
764+ client .InNamespace (backup .Namespace ), client .MatchingLabels (labels )); client .IgnoreNotFound (err ) != nil {
765+ return err
766+ }
767+ for i := range backupList .Items {
768+ bp := & backupList .Items [i ]
769+ // delete backups related to the current backup
770+ // files in the related backup's status.path will be deleted by its own associated deleter
771+ if bp .Status .ParentBackupName != backup .Name && bp .Status .BaseBackupName != backup .Name {
772+ continue
773+ }
774+ if err := intctrlutil .BackgroundDeleteObject (r .Client , reqCtx .Ctx , bp ); err != nil {
775+ return err
776+ }
777+ reqCtx .Log .Info ("delete the related backup" , "backup" , fmt .Sprintf ("%s/%s" , bp .Namespace , bp .Name ))
778+ }
779+ return nil
780+ }
781+
746782// PatchBackupObjectMeta patches backup object metaObject include cluster snapshot.
747783func PatchBackupObjectMeta (
748784 original * dpv1alpha1.Backup ,
@@ -956,3 +992,56 @@ func setClusterSnapshotAnnotation(request *dpbackup.Request, cluster *appsv1alph
956992 request .Backup .Annotations [constant .ClusterSnapshotAnnotationKey ] = * clusterString
957993 return nil
958994}
995+
996+ // validateContinuousBackup validates the continuous backup.
997+ func validateContinuousBackup (backup * dpv1alpha1.Backup , reqCtx intctrlutil.RequestCtx , cli client.Client ) error {
998+ // validate if the continuous backup is created by a backupSchedule.
999+ if _ , ok := backup .Labels [dptypes .BackupScheduleLabelKey ]; ! ok {
1000+ return fmt .Errorf ("continuous backup is only allowed to be created by backupSchedule" )
1001+ }
1002+ backupSchedule := & dpv1alpha1.BackupSchedule {}
1003+ if err := cli .Get (reqCtx .Ctx , client.ObjectKey {Name : backup .Labels [dptypes .BackupScheduleLabelKey ],
1004+ Namespace : backup .Namespace }, backupSchedule ); err != nil {
1005+ return err
1006+ }
1007+ if backupSchedule .Status .Phase != dpv1alpha1 .BackupSchedulePhaseAvailable {
1008+ return fmt .Errorf ("create continuous backup by failed backupschedule %s/%s" ,
1009+ backupSchedule .Namespace , backupSchedule .Name )
1010+ }
1011+ return nil
1012+ }
1013+
1014+ // prepare4Incremental prepares for incremental backup
1015+ func prepare4Incremental (request * dpbackup.Request ) (* dpbackup.Request , error ) {
1016+ // get and validate parent backup
1017+ parentBackup , err := GetParentBackup (request .Ctx , request .Client , request .Backup , request .BackupMethod )
1018+ if err != nil {
1019+ return nil , err
1020+ }
1021+ parentBackupType , err := dputils .GetBackupTypeByMethodName (request .RequestCtx ,
1022+ request .Client , parentBackup .Spec .BackupMethod , request .BackupPolicy )
1023+ if err != nil {
1024+ return nil , err
1025+ }
1026+ request .ParentBackup = parentBackup
1027+ // get and validate base backup
1028+ switch parentBackupType {
1029+ case dpv1alpha1 .BackupTypeFull :
1030+ request .BaseBackup = request .ParentBackup
1031+ case dpv1alpha1 .BackupTypeIncremental :
1032+ baseBackup := & dpv1alpha1.Backup {}
1033+ baseBackupName := request .ParentBackup .Status .BaseBackupName
1034+ if len (baseBackupName ) == 0 {
1035+ return nil , fmt .Errorf ("backup %s/%s base backup name is empty" ,
1036+ request .ParentBackup .Namespace , request .ParentBackup .Name )
1037+ }
1038+ if err := request .Client .Get (request .Ctx , client.ObjectKey {Name : baseBackupName ,
1039+ Namespace : request .ParentBackup .Namespace }, baseBackup ); err != nil {
1040+ return nil , fmt .Errorf ("failed to get base backup %s/%s: %w" , request .ParentBackup .Namespace , baseBackupName , err )
1041+ }
1042+ request .BaseBackup = baseBackup
1043+ default :
1044+ return nil , fmt .Errorf ("parent backup type is %s, but only full and incremental backup are supported" , parentBackupType )
1045+ }
1046+ return request , nil
1047+ }
0 commit comments