Skip to content

Commit

Permalink
Use PVC name and namespace for changing PVC conditions
Browse files Browse the repository at this point in the history
Previously we used VolumeReplication name and namespace for updating PVC conditions due to the fact
that we had one-to-one relationship between VolumeReplication and PVC. Now when we are going to use
consistency group this handling will not be right anymore, because several PVCs can be related to
one VolumeReplication. So, we need to use PVC name and namespace for updating PVC conditions.

Signed-off-by: Elena Gershkovich <[email protected]>
  • Loading branch information
ELENAGER committed Aug 26, 2024
1 parent eff856f commit 7c0e847
Showing 1 changed file with 53 additions and 43 deletions.
96 changes: 53 additions & 43 deletions internal/controller/vrg_volrep.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (v *VRGInstance) reconcileVolRepsAsPrimary() {
}

// If VR did not reach primary state, it is fine to still upload the PV and continue processing
requeueResult, _, err := v.processVRAsPrimary(pvcNamespacedName, log)
requeueResult, _, err := v.processVRAsPrimary(pvcNamespacedName, pvc, log)
if requeueResult {
v.requeue()
}
Expand Down Expand Up @@ -159,7 +159,7 @@ func (v *VRGInstance) reconcileVRAsSecondary(pvc *corev1.PersistentVolumeClaim,

pvcNamespacedName := types.NamespacedName{Name: pvc.Name, Namespace: pvc.Namespace}

requeueResult, ready, err := v.processVRAsSecondary(pvcNamespacedName, log)
requeueResult, ready, err := v.processVRAsSecondary(pvcNamespacedName, pvc, log)
if err != nil {
log.Info("Failure in getting or creating VolumeReplication resource for PersistentVolumeClaim",
"errorValue", err)
Expand Down Expand Up @@ -846,7 +846,7 @@ func (v *VRGInstance) reconcileVRForDeletion(pvc *corev1.PersistentVolumeClaim,
return !requeue
}
} else {
requeueResult, ready, err := v.processVRAsPrimary(pvcNamespacedName, log)
requeueResult, ready, err := v.processVRAsPrimary(pvcNamespacedName, pvc, log)
switch {
case err != nil:
log.Info("Requeuing due to failure in getting or creating VolumeReplication resource for PersistentVolumeClaim",
Expand Down Expand Up @@ -1010,9 +1010,11 @@ func (v *VRGInstance) s3StoreDo(do func(ObjectStorer) error, msg, s3ProfileName
// - a boolean indicating if a reconcile requeue is required
// - a boolean indicating if VR is already at the desired state
// - any errors during processing
func (v *VRGInstance) processVRAsPrimary(vrNamespacedName types.NamespacedName, log logr.Logger) (bool, bool, error) {
func (v *VRGInstance) processVRAsPrimary(vrNamespacedName types.NamespacedName,
pvc *corev1.PersistentVolumeClaim, log logr.Logger,
) (bool, bool, error) {
if v.instance.Spec.Async != nil {
return v.createOrUpdateVR(vrNamespacedName, volrep.Primary, log)
return v.createOrUpdateVR(vrNamespacedName, pvc, volrep.Primary, log)
}

// TODO: createOrUpdateVR does two things. It modifies the VR and also
Expand Down Expand Up @@ -1042,9 +1044,11 @@ func (v *VRGInstance) processVRAsPrimary(vrNamespacedName types.NamespacedName,
// - a boolean indicating if a reconcile requeue is required
// - a boolean indicating if VR is already at the desired state
// - any errors during processing
func (v *VRGInstance) processVRAsSecondary(vrNamespacedName types.NamespacedName, log logr.Logger) (bool, bool, error) {
func (v *VRGInstance) processVRAsSecondary(vrNamespacedName types.NamespacedName,
pvc *corev1.PersistentVolumeClaim, log logr.Logger,
) (bool, bool, error) {
if v.instance.Spec.Async != nil {
return v.createOrUpdateVR(vrNamespacedName, volrep.Secondary, log)
return v.createOrUpdateVR(vrNamespacedName, pvc, volrep.Secondary, log)
}

// TODO: createOrUpdateVR does two things. It modifies the VR and also
Expand Down Expand Up @@ -1081,7 +1085,7 @@ func (v *VRGInstance) processVRAsSecondary(vrNamespacedName types.NamespacedName
// - a boolean indicating if VR is already at the desired state
// - any errors during processing
func (v *VRGInstance) createOrUpdateVR(vrNamespacedName types.NamespacedName,
state volrep.ReplicationState, log logr.Logger,
pvc *corev1.PersistentVolumeClaim, state volrep.ReplicationState, log logr.Logger,
) (bool, bool, error) {
const requeue = true

Expand Down Expand Up @@ -1125,7 +1129,7 @@ func (v *VRGInstance) createOrUpdateVR(vrNamespacedName types.NamespacedName,
return !requeue, false, nil
}

return v.updateVR(volRep, state, log)
return v.updateVR(pvc, volRep, state, log)
}

func (v *VRGInstance) autoResync(state volrep.ReplicationState) bool {
Expand All @@ -1144,7 +1148,7 @@ func (v *VRGInstance) autoResync(state volrep.ReplicationState) bool {
// - a boolean indicating if a reconcile requeue is required
// - a boolean indicating if VR is already at the desired state
// - any errors during the process of updating the resource
func (v *VRGInstance) updateVR(volRep *volrep.VolumeReplication,
func (v *VRGInstance) updateVR(pvc *corev1.PersistentVolumeClaim, volRep *volrep.VolumeReplication,
state volrep.ReplicationState, log logr.Logger,
) (bool, bool, error) {
const requeue = true
Expand All @@ -1153,7 +1157,7 @@ func (v *VRGInstance) updateVR(volRep *volrep.VolumeReplication,
if volRep.Spec.ReplicationState == state && volRep.Spec.AutoResync == v.autoResync(state) {
log.Info("VolumeReplication and VolumeReplicationGroup state and autoresync match. Proceeding to status check")

return !requeue, v.checkVRStatus(volRep), nil
return !requeue, v.checkVRStatus(pvc, volRep), nil
}

volRep.Spec.ReplicationState = state
Expand All @@ -1167,7 +1171,7 @@ func (v *VRGInstance) updateVR(volRep *volrep.VolumeReplication,
rmnutil.EventReasonVRUpdateFailed, err.Error())

msg := "Failed to update VolumeReplication resource"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg)

return requeue, false, fmt.Errorf("failed to update VolumeReplication resource"+
" (%s/%s) as %s, belonging to VolumeReplicationGroup (%s/%s), %w",
Expand All @@ -1179,7 +1183,7 @@ func (v *VRGInstance) updateVR(volRep *volrep.VolumeReplication,
volRep.GetName(), volRep.GetNamespace(), state))
// Just updated the state of the VolRep. Mark it as progressing.
msg := "Updated VolumeReplication resource for PVC"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonProgressing, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonProgressing, msg)

return !requeue, false, nil
}
Expand Down Expand Up @@ -1374,30 +1378,30 @@ func (v *VRGInstance) getStorageClass(namespacedName types.NamespacedName) (*sto

// checkVRStatus checks if the VolumeReplication resource has the desired status for the
// current generation and returns true if so, false otherwise
func (v *VRGInstance) checkVRStatus(volRep *volrep.VolumeReplication) bool {
func (v *VRGInstance) checkVRStatus(pvc *corev1.PersistentVolumeClaim, volRep *volrep.VolumeReplication) bool {
// When the generation in the status is updated, VRG would get a reconcile
// as it owns VolumeReplication resource.
if volRep.GetGeneration() != volRep.Status.ObservedGeneration {
v.log.Info(fmt.Sprintf("Generation mismatch in status for VolumeReplication resource (%s/%s)",
volRep.GetName(), volRep.GetNamespace()))

msg := "VolumeReplication generation not updated in status"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonProgressing, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonProgressing, msg)

return false
}

switch {
case v.instance.Spec.ReplicationState == ramendrv1alpha1.Primary:
return v.validateVRStatus(volRep, ramendrv1alpha1.Primary)
return v.validateVRStatus(pvc, volRep, ramendrv1alpha1.Primary)
case v.instance.Spec.ReplicationState == ramendrv1alpha1.Secondary:
return v.validateVRStatus(volRep, ramendrv1alpha1.Secondary)
return v.validateVRStatus(pvc, volRep, ramendrv1alpha1.Secondary)
default:
v.log.Info(fmt.Sprintf("invalid Replication State %s for VolumeReplicationGroup (%s:%s)",
string(v.instance.Spec.ReplicationState), v.instance.Name, v.instance.Namespace))

msg := "VolumeReplicationGroup state invalid"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg)

return false
}
Expand All @@ -1408,7 +1412,9 @@ func (v *VRGInstance) checkVRStatus(volRep *volrep.VolumeReplication) bool {
// - When replication state is Primary, only Completed condition is checked.
// - When replication state is Secondary, all 3 conditions for Completed/Degraded/Resyncing is
// checked and ensured healthy.
func (v *VRGInstance) validateVRStatus(volRep *volrep.VolumeReplication, state ramendrv1alpha1.ReplicationState) bool {
func (v *VRGInstance) validateVRStatus(pvc *corev1.PersistentVolumeClaim, volRep *volrep.VolumeReplication,
state ramendrv1alpha1.ReplicationState,
) bool {
var (
stateString string
action string
Expand All @@ -1427,10 +1433,10 @@ func (v *VRGInstance) validateVRStatus(volRep *volrep.VolumeReplication, state r
conditionMet, msg := isVRConditionMet(volRep, volrepController.ConditionCompleted, metav1.ConditionTrue)
if !conditionMet {
defaultMsg := fmt.Sprintf("VolumeReplication resource for pvc not %s to %s", action, stateString)
v.updatePVCDataReadyConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataReadyConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.updatePVCDataProtectedConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataProtectedConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.log.Info(fmt.Sprintf("%s (VolRep: %s/%s)", defaultMsg, volRep.GetName(), volRep.GetNamespace()))
Expand All @@ -1440,15 +1446,15 @@ func (v *VRGInstance) validateVRStatus(volRep *volrep.VolumeReplication, state r

// if primary, all checks are completed
if state == ramendrv1alpha1.Secondary {
return v.validateAdditionalVRStatusForSecondary(volRep)
return v.validateAdditionalVRStatusForSecondary(pvc, volRep)
}

msg = "PVC in the VolumeReplicationGroup is ready for use"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonReady, msg)
v.updatePVCDataProtectedCondition(volRep.Namespace, volRep.Name, VRGConditionReasonReady, msg)
v.updatePVCLastSyncTime(volRep.Namespace, volRep.Name, volRep.Status.LastSyncTime)
v.updatePVCLastSyncDuration(volRep.Namespace, volRep.Name, volRep.Status.LastSyncDuration)
v.updatePVCLastSyncBytes(volRep.Namespace, volRep.Name, volRep.Status.LastSyncBytes)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonReady, msg)
v.updatePVCDataProtectedCondition(pvc.Namespace, pvc.Name, VRGConditionReasonReady, msg)
v.updatePVCLastSyncTime(pvc.Namespace, pvc.Name, volRep.Status.LastSyncTime)
v.updatePVCLastSyncDuration(pvc.Namespace, pvc.Name, volRep.Status.LastSyncDuration)
v.updatePVCLastSyncBytes(pvc.Namespace, pvc.Name, volRep.Status.LastSyncBytes)
v.log.Info(fmt.Sprintf("VolumeReplication resource %s/%s is ready for use", volRep.GetName(),
volRep.GetNamespace()))

Expand All @@ -1472,22 +1478,24 @@ func (v *VRGInstance) validateVRStatus(volRep *volrep.VolumeReplication, state r
// With 2nd condition being met,
// ProtectedPVC.Conditions[DataReady] = True
// ProtectedPVC.Conditions[DataProtected] = True
func (v *VRGInstance) validateAdditionalVRStatusForSecondary(volRep *volrep.VolumeReplication) bool {
v.updatePVCLastSyncTime(volRep.Namespace, volRep.Name, nil)
v.updatePVCLastSyncDuration(volRep.Namespace, volRep.Name, nil)
v.updatePVCLastSyncBytes(volRep.Namespace, volRep.Name, nil)
func (v *VRGInstance) validateAdditionalVRStatusForSecondary(pvc *corev1.PersistentVolumeClaim,
volRep *volrep.VolumeReplication,
) bool {
v.updatePVCLastSyncTime(pvc.Namespace, pvc.Name, nil)
v.updatePVCLastSyncDuration(pvc.Namespace, pvc.Name, nil)
v.updatePVCLastSyncBytes(pvc.Namespace, pvc.Name, nil)

conditionMet, _ := isVRConditionMet(volRep, volrepController.ConditionResyncing, metav1.ConditionTrue)
if !conditionMet {
return v.checkResyncCompletionAsSecondary(volRep)
return v.checkResyncCompletionAsSecondary(pvc, volRep)
}

conditionMet, msg := isVRConditionMet(volRep, volrepController.ConditionDegraded, metav1.ConditionTrue)
if !conditionMet {
v.updatePVCDataProtectedConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataProtectedConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
"VolumeReplication resource for pvc is not in Degraded condition while resyncing")

v.updatePVCDataReadyConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataReadyConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
"VolumeReplication resource for pvc is not in Degraded condition while resyncing")

v.log.Info(fmt.Sprintf("VolumeReplication resource is not in degraded condition while"+
Expand All @@ -1497,8 +1505,8 @@ func (v *VRGInstance) validateAdditionalVRStatusForSecondary(volRep *volrep.Volu
}

msg = "VolumeReplication resource for the pvc is syncing as Secondary"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonReplicating, msg)
v.updatePVCDataProtectedCondition(volRep.Namespace, volRep.Name, VRGConditionReasonReplicating, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonReplicating, msg)
v.updatePVCDataProtectedCondition(pvc.Namespace, pvc.Name, VRGConditionReasonReplicating, msg)

v.log.Info(fmt.Sprintf("VolumeReplication resource for the pvc is syncing as Secondary (%s/%s)",
volRep.GetName(), volRep.GetNamespace()))
Expand All @@ -1507,14 +1515,16 @@ func (v *VRGInstance) validateAdditionalVRStatusForSecondary(volRep *volrep.Volu
}

// checkResyncCompletionAsSecondary returns true if resync status is complete as secondary, false otherwise
func (v *VRGInstance) checkResyncCompletionAsSecondary(volRep *volrep.VolumeReplication) bool {
func (v *VRGInstance) checkResyncCompletionAsSecondary(pvc *corev1.PersistentVolumeClaim,
volRep *volrep.VolumeReplication,
) bool {
conditionMet, msg := isVRConditionMet(volRep, volrepController.ConditionResyncing, metav1.ConditionFalse)
if !conditionMet {
defaultMsg := "VolumeReplication resource for pvc not syncing as Secondary"
v.updatePVCDataReadyConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataReadyConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.updatePVCDataProtectedConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataProtectedConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.log.Info(fmt.Sprintf("%s (VolRep: %s/%s)", defaultMsg, volRep.GetName(), volRep.GetNamespace()))
Expand All @@ -1525,10 +1535,10 @@ func (v *VRGInstance) checkResyncCompletionAsSecondary(volRep *volrep.VolumeRepl
conditionMet, msg = isVRConditionMet(volRep, volrepController.ConditionDegraded, metav1.ConditionFalse)
if !conditionMet {
defaultMsg := "VolumeReplication resource for pvc is not syncing and is degraded as Secondary"
v.updatePVCDataReadyConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataReadyConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.updatePVCDataProtectedConditionHelper(volRep.Namespace, volRep.Name, VRGConditionReasonError, msg,
v.updatePVCDataProtectedConditionHelper(pvc.Namespace, pvc.Name, VRGConditionReasonError, msg,
defaultMsg)

v.log.Info(fmt.Sprintf("%s (VolRep: %s/%s)", defaultMsg, volRep.GetName(), volRep.GetNamespace()))
Expand All @@ -1537,8 +1547,8 @@ func (v *VRGInstance) checkResyncCompletionAsSecondary(volRep *volrep.VolumeRepl
}

msg = "VolumeReplication resource for the pvc as Secondary is in sync with Primary"
v.updatePVCDataReadyCondition(volRep.Namespace, volRep.Name, VRGConditionReasonReplicated, msg)
v.updatePVCDataProtectedCondition(volRep.Namespace, volRep.Name, VRGConditionReasonDataProtected, msg)
v.updatePVCDataReadyCondition(pvc.Namespace, pvc.Name, VRGConditionReasonReplicated, msg)
v.updatePVCDataProtectedCondition(pvc.Namespace, pvc.Name, VRGConditionReasonDataProtected, msg)

v.log.Info(fmt.Sprintf("data sync completed as both degraded and resyncing are false for"+
" secondary VolRep (%s/%s)", volRep.GetName(), volRep.GetNamespace()))
Expand Down

0 comments on commit 7c0e847

Please sign in to comment.