From 4d2c3f797b158c0d39c3ea960511f172d48fac06 Mon Sep 17 00:00:00 2001 From: yati1998 Date: Tue, 15 Oct 2024 10:07:44 +0530 Subject: [PATCH] update the volumereplication condition this commit updates the volumereplication conditions to include descriptive message for every operations Signed-off-by: yati1998 --- .../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) } }