@@ -30,6 +30,7 @@ import (
3030
3131 "github.com/percona/percona-server-mongodb-operator/clientcmd"
3232 psmdbv1 "github.com/percona/percona-server-mongodb-operator/pkg/apis/psmdb/v1"
33+ "github.com/percona/percona-server-mongodb-operator/pkg/k8s"
3334 "github.com/percona/percona-server-mongodb-operator/pkg/naming"
3435 "github.com/percona/percona-server-mongodb-operator/pkg/psmdb"
3536 "github.com/percona/percona-server-mongodb-operator/pkg/psmdb/backup"
@@ -118,7 +119,7 @@ func (r *ReconcilePerconaServerMongoDBBackup) Reconcile(ctx context.Context, req
118119 // Request object not found, could have been deleted after reconcile request.
119120 // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
120121 // Return and don't requeue
121- return rr , nil
122+ return reconcile. Result {} , nil
122123 }
123124 // Error reading the object - requeue the request.
124125 return rr , err
@@ -144,6 +145,16 @@ func (r *ReconcilePerconaServerMongoDBBackup) Reconcile(ctx context.Context, req
144145 if uerr != nil {
145146 log .Error (uerr , "failed to update backup status" , "backup" , cr .Name )
146147 }
148+
149+ switch cr .Status .State {
150+ case psmdbv1 .BackupStateReady , psmdbv1 .BackupStateError :
151+ log .Info ("Releasing backup lock" , "lease" , naming .BackupLeaseName (cr .Spec .ClusterName ))
152+
153+ err := k8s .ReleaseLease (ctx , r .client , naming .BackupLeaseName (cr .Spec .ClusterName ), cr .Namespace , naming .BackupHolderId (cr ))
154+ if err != nil {
155+ log .Error (err , "failed to release the lock" )
156+ }
157+ }
147158 }
148159 }()
149160
@@ -228,14 +239,28 @@ func (r *ReconcilePerconaServerMongoDBBackup) reconcile(
228239 }
229240
230241 if cjobs {
231- if cr .Status .State != psmdbv1 .BackupStateWaiting {
232- log .Info ("Waiting to finish another backup/restore." )
233- }
242+ log .Info ("Waiting to finish another backup/restore." )
234243 status .State = psmdbv1 .BackupStateWaiting
235244 return status , nil
236245 }
237246
238- switch cr .Status .State {
247+ log .Info ("Acquiring the backup lock" )
248+ lease , err := k8s .AcquireLease (ctx , r .client , naming .BackupLeaseName (cluster .Name ), cr .Namespace , naming .BackupHolderId (cr ))
249+ if err != nil {
250+ return status , errors .Wrap (err , "acquire backup lock" )
251+ }
252+
253+ if lease .Spec .HolderIdentity != nil && * lease .Spec .HolderIdentity != naming .BackupHolderId (cr ) {
254+ log .Info ("Another backup is holding the lock" , "holder" , * lease .Spec .HolderIdentity )
255+ status .State = psmdbv1 .BackupStateWaiting
256+ return status , nil
257+ }
258+
259+ if err := r .ensureReleaseLockFinalizer (ctx , cluster , cr ); err != nil {
260+ return status , errors .Wrapf (err , "ensure %s finalizer" , naming .FinalizerReleaseLock )
261+ }
262+
263+ switch status .State {
239264 case psmdbv1 .BackupStateNew , psmdbv1 .BackupStateWaiting :
240265 return bcp .Start (ctx , r .client , cluster , cr )
241266 }
@@ -251,6 +276,28 @@ func (r *ReconcilePerconaServerMongoDBBackup) reconcile(
251276 return status , err
252277}
253278
279+ func (r * ReconcilePerconaServerMongoDBBackup ) ensureReleaseLockFinalizer (
280+ ctx context.Context ,
281+ cluster * psmdbv1.PerconaServerMongoDB ,
282+ cr * psmdbv1.PerconaServerMongoDBBackup ,
283+ ) error {
284+ for _ , f := range cr .GetFinalizers () {
285+ if f == naming .FinalizerReleaseLock {
286+ return nil
287+ }
288+ }
289+
290+ orig := cr .DeepCopy ()
291+ cr .SetFinalizers (append (cr .GetFinalizers (), naming .FinalizerReleaseLock ))
292+ if err := r .client .Patch (ctx , cr .DeepCopy (), client .MergeFrom (orig )); err != nil {
293+ return errors .Wrap (err , "patch finalizers" )
294+ }
295+
296+ logf .FromContext (ctx ).V (1 ).Info ("Added finalizer" , "finalizer" , naming .FinalizerReleaseLock )
297+
298+ return nil
299+ }
300+
254301func (r * ReconcilePerconaServerMongoDBBackup ) getPBMStorage (ctx context.Context , cluster * psmdbv1.PerconaServerMongoDB , cr * psmdbv1.PerconaServerMongoDBBackup ) (storage.Storage , error ) {
255302 switch {
256303 case cr .Status .Azure != nil :
@@ -379,18 +426,24 @@ func (r *ReconcilePerconaServerMongoDBBackup) checkFinalizers(ctx context.Contex
379426
380427 finalizers := []string {}
381428
382- if cr . Status . State == psmdbv1 . BackupStateReady {
383- for _ , f := range cr . GetFinalizers () {
384- switch f {
385- case "delete-backup" :
386- log . Info ( "delete-backup finalizer is deprecated and will be deleted in 1.20.0. Use percona.com/delete-backup instead" )
387- fallthrough
388- case naming . FinalizerDeleteBackup :
429+ for _ , f := range cr . GetFinalizers () {
430+ switch f {
431+ case "delete-backup" :
432+ log . Info ( "delete-backup finalizer is deprecated and will be deleted in 1.20.0. Use percona.com/delete-backup instead" )
433+ fallthrough
434+ case naming . FinalizerDeleteBackup :
435+ if cr . Status . State == psmdbv1 . BackupStateReady {
389436 if err := r .deleteBackupFinalizer (ctx , cr , cluster , b ); err != nil {
390437 log .Error (err , "failed to run finalizer" , "finalizer" , f )
391438 finalizers = append (finalizers , f )
392439 }
393440 }
441+ case naming .FinalizerReleaseLock :
442+ err = r .runReleaseLockFinalizer (ctx , cr )
443+ if err != nil {
444+ log .Error (err , "failed to release backup lock" )
445+ finalizers = append (finalizers , f )
446+ }
394447 }
395448 }
396449
@@ -400,6 +453,20 @@ func (r *ReconcilePerconaServerMongoDBBackup) checkFinalizers(ctx context.Contex
400453 return err
401454}
402455
456+ func (r * ReconcilePerconaServerMongoDBBackup ) runReleaseLockFinalizer (ctx context.Context , cr * psmdbv1.PerconaServerMongoDBBackup ) error {
457+ leaseName := naming .BackupLeaseName (cr .Spec .ClusterName )
458+ holderId := naming .BackupHolderId (cr )
459+ log := logf .FromContext (ctx ).WithValues ("lease" , leaseName , "holder" , holderId )
460+
461+ log .Info ("releasing backup lock" )
462+ err := k8s .ReleaseLease (ctx , r .client , leaseName , cr .Namespace , holderId )
463+ if k8serrors .IsNotFound (err ) || errors .Is (err , k8s .ErrNotTheHolder ) {
464+ log .V (1 ).Info ("failed to release backup lock" , "error" , err )
465+ return nil
466+ }
467+ return errors .Wrap (err , "release backup lock" )
468+ }
469+
403470func (r * ReconcilePerconaServerMongoDBBackup ) deleteBackupFinalizer (ctx context.Context , cr * psmdbv1.PerconaServerMongoDBBackup , cluster * psmdbv1.PerconaServerMongoDB , b * Backup ) error {
404471 if len (cr .Status .PBMname ) == 0 {
405472 return nil
0 commit comments