From 54274fc27531c08f1516fb7e6942732a923b051b Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Wed, 21 Aug 2024 15:56:11 +0200 Subject: [PATCH 1/3] replication: move conditions to api The consumers of the Replication API are expecting the conditions to be something imported and comparable from the other repo's. For the same reason moving the conditions to replication types. fixes: #649 Signed-off-by: Madhu Rajanna (cherry picked from commit 89d4c5b45a3258587d2e8054183470093385308c) Signed-off-by: Niels de Vos --- .../v1alpha1/volumereplication_types.go | 37 ++++++ .../controller/replication.storage/status.go | 106 +++++++----------- 2 files changed, 78 insertions(+), 65 deletions(-) diff --git a/api/replication.storage/v1alpha1/volumereplication_types.go b/api/replication.storage/v1alpha1/volumereplication_types.go index d9fca40ad..17377fece 100644 --- a/api/replication.storage/v1alpha1/volumereplication_types.go +++ b/api/replication.storage/v1alpha1/volumereplication_types.go @@ -25,6 +25,43 @@ const ( VolumeReplicationNameAnnotation = "replication.storage.openshift.io/volume-replication-name" ) +// These are valid condition statuses. +// "ConditionCompleted" means the condition is fulfilled. +// "ConditionDegraded" means the condition is not fulfilled. +// "ConditionResyncing" means the condition is resyncing. +const ( + ConditionCompleted = "Completed" + ConditionDegraded = "Degraded" + ConditionResyncing = "Resyncing" +) + +// These are valid conditions. + +const ( + // Success condition represents the successful completion of the operation. + Success = "Success" + // Promoted condition represents the successful promotion of the volume. + Promoted = "Promoted" + // Demoted condition represents the successful demotion of the volume. + Demoted = "Demoted" + // FailedToPromote condition represents the failure to promote the volume. + FailedToPromote = "FailedToPromote" + // FailedToDemote condition represents the failure to demote the volume. + FailedToDemote = "FailedToDemote" + // Error condition represents the error in the operation. + Error = "Error" + // VolumeDegraded condition represents the volume is degraded. + VolumeDegraded = "VolumeDegraded" + // Healthy condition represents the volume is healthy. + Healthy = "Healthy" + // ResyncTriggered condition represents the resync operation is triggered. + ResyncTriggered = "ResyncTriggered" + // FailedToResync condition represents the failure to resync the volume. + FailedToResync = "FailedToResync" + // NotResyncing condition represents the volume is not resyncing. + NotResyncing = "NotResyncing" +) + // ReplicationState represents the replication operations to be performed on the volume. // +kubebuilder:validation:Enum=primary;secondary;resync type ReplicationState string diff --git a/internal/controller/replication.storage/status.go b/internal/controller/replication.storage/status.go index 56c7bfe51..764a84fcf 100644 --- a/internal/controller/replication.storage/status.go +++ b/internal/controller/replication.storage/status.go @@ -19,51 +19,27 @@ package controller import ( "time" + "github.com/csi-addons/kubernetes-csi-addons/api/replication.storage/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const ( - ConditionCompleted = "Completed" - ConditionDegraded = "Degraded" - ConditionResyncing = "Resyncing" - ConditionValidated = "Validated" -) - -const ( - Success = "Success" - Promoted = "Promoted" - Demoted = "Demoted" - FailedToPromote = "FailedToPromote" - FailedToDemote = "FailedToDemote" - Error = "Error" - VolumeDegraded = "VolumeDegraded" - Healthy = "Healthy" - ResyncTriggered = "ResyncTriggered" - FailedToResync = "FailedToResync" - NotResyncing = "NotResyncing" - // PrerequisiteMet condition represents that the prerequisite is met. - PrerequisiteMet = "PrerequisiteMet" - // PrerequisiteNotMet condition represents that the prerequisite is not met. - PrerequisiteNotMet = "PrerequisiteNotMet" -) - // sets conditions when volume was promoted successfully. func setPromotedCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: Promoted, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.Promoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Healthy, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Healthy, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) @@ -72,20 +48,20 @@ func setPromotedCondition(conditions *[]metav1.Condition, observedGeneration int // sets conditions when volume promotion was failed. func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: FailedToPromote, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.FailedToPromote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Error, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) @@ -128,14 +104,14 @@ func setFailedValidationCondition(conditions *[]metav1.Condition, observedGenera // sets conditions when volume is demoted and ready to use (resync completed). func setNotDegradedCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Healthy, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Healthy, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) @@ -144,20 +120,20 @@ func setNotDegradedCondition(conditions *[]metav1.Condition, observedGeneration // sets conditions when volume was demoted successfully. func setDemotedCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: Demoted, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.Demoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: VolumeDegraded, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.VolumeDegraded, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) @@ -166,20 +142,20 @@ func setDemotedCondition(conditions *[]metav1.Condition, observedGeneration int6 // sets conditions when volume demotion was failed. func setFailedDemotionCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: FailedToDemote, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.FailedToDemote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Error, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) @@ -188,20 +164,20 @@ func setFailedDemotionCondition(conditions *[]metav1.Condition, observedGenerati // sets conditions when volume resync was triggered successfully. func setResyncCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: Demoted, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.Demoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: VolumeDegraded, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.VolumeDegraded, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: ResyncTriggered, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.ResyncTriggered, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) @@ -210,20 +186,20 @@ func setResyncCondition(conditions *[]metav1.Condition, observedGeneration int64 // sets conditions when volume resync failed. func setFailedResyncCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: FailedToResync, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.FailedToResync, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Error, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: FailedToResync, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.FailedToResync, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) From 53bf36ddd8af6400ccbbba230c309758ecc6fe36 Mon Sep 17 00:00:00 2001 From: Rakshith R Date: Wed, 11 Sep 2024 15:28:48 +0530 Subject: [PATCH 2/3] replication: add new Validated condition This commit adds new Validated condition. This is initially used to indicate the csi driver responded with FailedPrecondition grpc code for EnableReplication request using `PrerequisiteNotMet` reason. Signed-off-by: Rakshith R (cherry picked from commit 9f416da4f1d99b3d30b07ff9cd6176c19dc43a68) Signed-off-by: Niels de Vos --- .../v1alpha1/volumereplication_types.go | 5 +++++ .../controller/replication.storage/status.go | 20 +++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) 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 764a84fcf..d8c1de8f3 100644 --- a/internal/controller/replication.storage/status.go +++ b/internal/controller/replication.storage/status.go @@ -66,8 +66,8 @@ func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGenerat Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionValidated, - Reason: PrerequisiteMet, + Type: v1alpha1.ConditionValidated, + Reason: v1alpha1.PrerequisiteMet, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) @@ -76,26 +76,26 @@ func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGenerat // sets conditions when volume promotion was failed due to failed validation. func setFailedValidationCondition(conditions *[]metav1.Condition, observedGeneration int64) { setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionCompleted, - Reason: FailedToPromote, + Type: v1alpha1.ConditionCompleted, + Reason: v1alpha1.FailedToPromote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionDegraded, - Reason: Error, + Type: v1alpha1.ConditionDegraded, + Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionResyncing, - Reason: NotResyncing, + Type: v1alpha1.ConditionResyncing, + Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ - Type: ConditionValidated, - Reason: PrerequisiteNotMet, + Type: v1alpha1.ConditionValidated, + Reason: v1alpha1.PrerequisiteNotMet, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) From 0e298929d1d6f99b03a31f4b91a50913b37220ef Mon Sep 17 00:00:00 2001 From: yati1998 Date: Tue, 15 Oct 2024 10:07:44 +0530 Subject: [PATCH 3/3] update the volumereplication condition this commit updates the volumereplication conditions to include descriptive message for every operations Signed-off-by: yati1998 (cherry picked from commit 8b610a14a6b33512ae0ab38ef84b47da33a17001) Signed-off-by: Niels de Vos --- .../v1alpha1/volumereplication_types.go | 22 +++++++ .../controller/replication.storage/status.go | 61 ++++++++++++++++--- .../volumereplication_controller.go | 43 +++++++------ 3 files changed, 96 insertions(+), 30 deletions(-) diff --git a/api/replication.storage/v1alpha1/volumereplication_types.go b/api/replication.storage/v1alpha1/volumereplication_types.go index 0e777409b..bfa84b925 100644 --- a/api/replication.storage/v1alpha1/volumereplication_types.go +++ b/api/replication.storage/v1alpha1/volumereplication_types.go @@ -36,6 +36,28 @@ const ( ConditionValidated = "Validated" ) +// These are valid messages for various conditions and states of volume replication. +const ( + MessagePromoted = "is promoted to primary and replicating to secondary" + MessageHealthy = "is healthy" + MessageNotResyncing = "is not resyncing" + MessageValidated = "is validated and met all prerequisites" + MessageFailedPromoted = "failed to promote" + MessageFailedDemoted = "failed to demote" + MessageFailedPreCondition = "failed to meet prerequisite" + MessageDemoted = "is demoted to secondary" + MessageDegraded = "is degraded" + MessageResyncTriggered = "is resyncing changes from primary to secondary" + MessageResyncFailed = "failed to resync" +) + +type Source string + +const ( + Volume Source = "volume" + VolumeGroup Source = "volume group" +) + // These are valid conditions. const ( diff --git a/internal/controller/replication.storage/status.go b/internal/controller/replication.storage/status.go index d8c1de8f3..a4563896b 100644 --- a/internal/controller/replication.storage/status.go +++ b/internal/controller/replication.storage/status.go @@ -17,27 +17,42 @@ limitations under the License. package controller import ( + "fmt" "time" "github.com/csi-addons/kubernetes-csi-addons/api/replication.storage/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func getSource(dataSource string) v1alpha1.Source { + if dataSource == pvcDataSource { + return v1alpha1.Volume + } else if dataSource == volumeGroupReplicationDataSource { + return v1alpha1.VolumeGroup + } else { + return "" + } +} + // sets conditions when volume was promoted successfully. -func setPromotedCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setPromotedCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessagePromoted), Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.Promoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageHealthy), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Healthy, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, @@ -46,26 +61,31 @@ func setPromotedCondition(conditions *[]metav1.Condition, observedGeneration int } // sets conditions when volume promotion was failed. -func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource, completedMessage, degradedDetailedMessage string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: completedMessage, Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.FailedToPromote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s: %s", source, v1alpha1.MessageFailedPromoted, degradedDetailedMessage), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageValidated), Type: v1alpha1.ConditionValidated, Reason: v1alpha1.PrerequisiteMet, ObservedGeneration: observedGeneration, @@ -74,26 +94,31 @@ func setFailedPromotionCondition(conditions *[]metav1.Condition, observedGenerat } // sets conditions when volume promotion was failed due to failed validation. -func setFailedValidationCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setFailedValidationCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource, degradedMessage, validationDetailedMessage string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageFailedPromoted), Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.FailedToPromote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: degradedMessage, Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s: %s", v1alpha1.MessageFailedPreCondition, validationDetailedMessage), Type: v1alpha1.ConditionValidated, Reason: v1alpha1.PrerequisiteNotMet, ObservedGeneration: observedGeneration, @@ -102,14 +127,17 @@ func setFailedValidationCondition(conditions *[]metav1.Condition, observedGenera } // sets conditions when volume is demoted and ready to use (resync completed). -func setNotDegradedCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setNotDegradedCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageDemoted), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Healthy, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, @@ -118,20 +146,24 @@ func setNotDegradedCondition(conditions *[]metav1.Condition, observedGeneration } // sets conditions when volume was demoted successfully. -func setDemotedCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setDemotedCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageDemoted), Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.Demoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageDegraded), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.VolumeDegraded, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, @@ -140,20 +172,24 @@ func setDemotedCondition(conditions *[]metav1.Condition, observedGeneration int6 } // sets conditions when volume demotion was failed. -func setFailedDemotionCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setFailedDemotionCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource, completedMessage, degradedDetailedMessage string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: completedMessage, Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.FailedToDemote, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s: %s", source, v1alpha1.MessageFailedDemoted, degradedDetailedMessage), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.NotResyncing, ObservedGeneration: observedGeneration, @@ -162,20 +198,24 @@ func setFailedDemotionCondition(conditions *[]metav1.Condition, observedGenerati } // sets conditions when volume resync was triggered successfully. -func setResyncCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setResyncCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageDemoted), Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.Demoted, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageDegraded), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.VolumeDegraded, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageResyncTriggered), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.ResyncTriggered, ObservedGeneration: observedGeneration, @@ -184,20 +224,24 @@ func setResyncCondition(conditions *[]metav1.Condition, observedGeneration int64 } // sets conditions when volume resync failed. -func setFailedResyncCondition(conditions *[]metav1.Condition, observedGeneration int64) { +func setFailedResyncCondition(conditions *[]metav1.Condition, observedGeneration int64, dataSource, completedMessage, degradedDetailedMessage string) { + source := getSource(dataSource) setStatusCondition(conditions, &metav1.Condition{ + Message: completedMessage, Type: v1alpha1.ConditionCompleted, Reason: v1alpha1.FailedToResync, ObservedGeneration: observedGeneration, Status: metav1.ConditionFalse, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s: %s", source, v1alpha1.MessageResyncFailed, degradedDetailedMessage), Type: v1alpha1.ConditionDegraded, Reason: v1alpha1.Error, ObservedGeneration: observedGeneration, Status: metav1.ConditionTrue, }) setStatusCondition(conditions, &metav1.Condition{ + Message: fmt.Sprintf("%s %s", source, v1alpha1.MessageNotResyncing), Type: v1alpha1.ConditionResyncing, Reason: v1alpha1.FailedToResync, ObservedGeneration: observedGeneration, @@ -223,6 +267,7 @@ func setStatusCondition(existingConditions *[]metav1.Condition, newCondition *me existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) } + existingCondition.Message = newCondition.Message existingCondition.Reason = newCondition.Reason existingCondition.ObservedGeneration = newCondition.ObservedGeneration } diff --git a/internal/controller/replication.storage/volumereplication_controller.go b/internal/controller/replication.storage/volumereplication_controller.go index c69fd8e40..c96e43d9a 100644 --- a/internal/controller/replication.storage/volumereplication_controller.go +++ b/internal/controller/replication.storage/volumereplication_controller.go @@ -112,7 +112,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re // Get VolumeReplicationClass vrcObj, err := r.getVolumeReplicationClass(logger, instance.Spec.VolumeReplicationClass) if err != nil { - setFailureCondition(instance) + setFailureCondition(instance, "failed to get volumeReplication class", err.Error(), instance.Spec.DataSource.Kind) uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), err.Error()) if uErr != nil { logger.Error(uErr, "failed to update volumeReplication status", "VRName", instance.Name) @@ -124,7 +124,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re err = validatePrefixedParameters(vrcObj.Spec.Parameters) if err != nil { logger.Error(err, "failed to validate parameters of volumeReplicationClass", "VRCName", instance.Spec.VolumeReplicationClass) - setFailureCondition(instance) + setFailureCondition(instance, "failed to validate parameters of volumeReplicationClass", err.Error(), instance.Spec.DataSource.Kind) uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), err.Error()) if uErr != nil { logger.Error(uErr, "failed to update volumeReplication status", "VRName", instance.Name) @@ -160,7 +160,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re pvc, pv, pvErr = r.getPVCDataSource(logger, nameSpacedName) if pvErr != nil { logger.Error(pvErr, "failed to get PVC", "PVCName", instance.Spec.DataSource.Name) - setFailureCondition(instance) + setFailureCondition(instance, "failed to find PVC", pvErr.Error(), instance.Spec.DataSource.Name) uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), pvErr.Error()) if uErr != nil { logger.Error(uErr, "failed to update volumeReplication status", "VRName", instance.Name) @@ -175,7 +175,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re vgr, vgrc, vgrErr = r.getVolumeGroupReplicationDataSource(logger, nameSpacedName) if vgrErr != nil { logger.Error(vgrErr, "failed to get VolumeGroupReplication", "VGRName", instance.Spec.DataSource.Name) - setFailureCondition(instance) + setFailureCondition(instance, "failed to get VolumeGroupReplication", vgrErr.Error(), instance.Spec.DataSource.Name) uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), vgrErr.Error()) if uErr != nil { logger.Error(uErr, "failed to update volumeReplication status", "VRName", instance.Name) @@ -187,7 +187,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re default: err = fmt.Errorf("unsupported datasource kind") logger.Error(err, "given kind not supported", "Kind", instance.Spec.DataSource.Kind) - setFailureCondition(instance) + setFailureCondition(instance, "unsupported datasource", err.Error(), "") uErr := r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), err.Error()) if uErr != nil { logger.Error(uErr, "failed to update volumeReplication status", "VRName", instance.Name) @@ -371,7 +371,7 @@ func (r *VolumeReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Re default: replicationErr = fmt.Errorf("unsupported volume state") logger.Error(replicationErr, "given volume state is not supported", "ReplicationState", instance.Spec.ReplicationState) - setFailureCondition(instance) + setFailureCondition(instance, "unsupported volume state", replicationErr.Error(), instance.Spec.DataSource.Kind) err = r.updateReplicationStatus(instance, logger, getCurrentReplicationState(instance), replicationErr.Error()) if err != nil { logger.Error(err, "failed to update volumeReplication status", "VRName", instance.Name) @@ -632,7 +632,7 @@ func (r *VolumeReplicationReconciler) markVolumeAsPrimary(vr *volumeReplicationI if !isKnownError { if resp.Error != nil { vr.logger.Error(resp.Error, "failed to promote volume") - setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to promote volume", resp.Error.Error()) return resp.Error } @@ -643,14 +643,14 @@ func (r *VolumeReplicationReconciler) markVolumeAsPrimary(vr *volumeReplicationI resp := volumeReplication.Promote() if resp.Error != nil { vr.logger.Error(resp.Error, "failed to force promote volume") - setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to force promote volume", resp.Error.Error()) return resp.Error } } } - setPromotedCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setPromotedCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind) return nil } @@ -665,12 +665,12 @@ func (r *VolumeReplicationReconciler) markVolumeAsSecondary(vr *volumeReplicatio if resp.Error != nil { vr.logger.Error(resp.Error, "failed to demote volume") - setFailedDemotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedDemotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to demote volume", resp.Error.Error()) return resp.Error } - setDemotedCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setDemotedCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind) return nil } @@ -686,7 +686,7 @@ func (r *VolumeReplicationReconciler) resyncVolume(vr *volumeReplicationInstance if resp.Error != nil { vr.logger.Error(resp.Error, "failed to resync volume") - setFailedResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to resync volume", resp.Error.Error()) return false, resp.Error } @@ -694,19 +694,19 @@ func (r *VolumeReplicationReconciler) resyncVolume(vr *volumeReplicationInstance if !ok { err := fmt.Errorf("received response of unexpected type") vr.logger.Error(err, "unable to parse response") - setFailedResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "unable to parse resync response", "received response of unexpected type") return false, err } - setResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setResyncCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind) if !resyncResponse.GetReady() { return true, nil } // No longer degraded, as volume is fully synced - setNotDegradedCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setNotDegradedCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind) return false, nil } @@ -748,11 +748,10 @@ func (r *VolumeReplicationReconciler) enableReplication(vr *volumeReplicationIns vr.logger.Error(resp.Error, "failed to enable volume replication") if resp.HasKnownGRPCError(enableReplicationKnownErrors) { - setFailedValidationCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedValidationCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to enable volume replication", resp.Error.Error()) } else { - setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation) + setFailedPromotionCondition(&vr.instance.Status.Conditions, vr.instance.Generation, vr.instance.Spec.DataSource.Kind, "failed to enable volume replication", resp.Error.Error()) } - return resp.Error } @@ -805,14 +804,14 @@ func getCurrentReplicationState(instance *replicationv1alpha1.VolumeReplication) return instance.Status.State } -func setFailureCondition(instance *replicationv1alpha1.VolumeReplication) { +func setFailureCondition(instance *replicationv1alpha1.VolumeReplication, errMessage string, errFromCephCSI string, dataSource string) { switch instance.Spec.ReplicationState { case replicationv1alpha1.Primary: - setFailedPromotionCondition(&instance.Status.Conditions, instance.Generation) + setFailedPromotionCondition(&instance.Status.Conditions, instance.Generation, dataSource, errMessage, errFromCephCSI) case replicationv1alpha1.Secondary: - setFailedDemotionCondition(&instance.Status.Conditions, instance.Generation) + setFailedDemotionCondition(&instance.Status.Conditions, instance.Generation, dataSource, errMessage, errFromCephCSI) case replicationv1alpha1.Resync: - setFailedResyncCondition(&instance.Status.Conditions, instance.Generation) + setFailedResyncCondition(&instance.Status.Conditions, instance.Generation, dataSource, errMessage, errFromCephCSI) } }