diff --git a/api/replication.storage/v1alpha1/volumereplication_types.go b/api/replication.storage/v1alpha1/volumereplication_types.go index 17377fece..0e777409b 100644 --- a/api/replication.storage/v1alpha1/volumereplication_types.go +++ b/api/replication.storage/v1alpha1/volumereplication_types.go @@ -33,6 +33,7 @@ const ( ConditionCompleted = "Completed" ConditionDegraded = "Degraded" ConditionResyncing = "Resyncing" + ConditionValidated = "Validated" ) // These are valid conditions. @@ -60,6 +61,10 @@ const ( FailedToResync = "FailedToResync" // NotResyncing condition represents the volume is not resyncing. NotResyncing = "NotResyncing" + // PrerequisiteMet condition represents that the prerequisite is met. + PrerequisiteMet = "PrerequisiteMet" + // PrerequisiteNotMet condition represents that the prerequisite is not met. + PrerequisiteNotMet = "PrerequisiteNotMet" ) // ReplicationState represents the replication operations to be performed on the volume. diff --git a/internal/controller/replication.storage/status.go b/internal/controller/replication.storage/status.go index a98273cde..d8c1de8f3 100644 --- a/internal/controller/replication.storage/status.go +++ b/internal/controller/replication.storage/status.go @@ -65,6 +65,40 @@ func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGenerat ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) + setStatusCondition(conditions, &metav1.Condition{ + Type: v1alpha1.ConditionValidated, + Reason: v1alpha1.PrerequisiteMet, + ObservedGeneration: observedGeneration, + Status: metav1.ConditionTrue, + }) +} + +// sets conditions when volume promotion was failed due to failed validation. +func setFailedValidationCondition(conditions *[]metav1.Condition, observedGeneration int64) { + setStatusCondition(conditions, &metav1.Condition{ + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.FailedToPromote, + ObservedGeneration: observedGeneration, + Status: metav1.ConditionFalse, + }) + setStatusCondition(conditions, &metav1.Condition{ + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Error, + ObservedGeneration: observedGeneration, + Status: metav1.ConditionTrue, + }) + setStatusCondition(conditions, &metav1.Condition{ + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, + ObservedGeneration: observedGeneration, + Status: metav1.ConditionFalse, + }) + setStatusCondition(conditions, &metav1.Condition{ + Type: v1alpha1.ConditionValidated, + Reason: v1alpha1.PrerequisiteNotMet, + ObservedGeneration: observedGeneration, + Status: metav1.ConditionFalse, + }) } // sets conditions when volume is demoted and ready to use (resync completed). diff --git a/internal/controller/replication.storage/volumereplication_controller.go b/internal/controller/replication.storage/volumereplication_controller.go index bd3365ea1..288d0c8ac 100644 --- a/internal/controller/replication.storage/volumereplication_controller.go +++ b/internal/controller/replication.storage/volumereplication_controller.go @@ -60,6 +60,7 @@ const ( var ( volumePromotionKnownErrors = []codes.Code{codes.FailedPrecondition} disableReplicationKnownErrors = []codes.Code{codes.NotFound} + enableReplicationKnownErrors = []codes.Code{codes.FailedPrecondition} getReplicationInfoKnownErrors = []codes.Code{codes.NotFound} ) @@ -322,7 +323,6 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re // enable replication only if its not primary if err = r.enableReplication(vr); err != nil { logger.Error(err, "failed to enable replication") - setFailureCondition(instance) msg := replication.GetMessageFromError(err) uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), msg) if uErr != nil { @@ -741,13 +741,19 @@ func (r *VolumeReplicationReconciler) enableReplication(vr *volumeReplicationIns resp := volumeReplication.Enable() - if resp.Error != nil { - vr.logger.Error(resp.Error, "failed to enable volume replication") + if resp.Error == nil { + return nil + } - return resp.Error + vr.logger.Error(resp.Error, "failed to enable volume replication") + + if resp.HasKnownGRPCError(enableReplicationKnownErrors) { + setFailedValidationCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + } else { + setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation) } - return nil + return resp.Error } // getVolumeReplicationInfo gets volume replication info.