Skip to content

Commit 974e76d

Browse files
authored
Merge pull request #191 from BenamarMk/bz2260130
Bug 2260130: Disown volsync managed pvcs upon vrg deletion
2 parents af30456 + 1cd1ece commit 974e76d

6 files changed

+90
-43
lines changed

controllers/drplacementcontrol.go

+1
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,7 @@ func (d *DRPCInstance) generateVRG(dstCluster string, repState rmn.ReplicationSt
15241524
Namespace: d.vrgNamespace,
15251525
Annotations: map[string]string{
15261526
DestinationClusterAnnotationKey: dstCluster,
1527+
DoNotDeletePVCAnnotation: d.instance.GetAnnotations()[DoNotDeletePVCAnnotation],
15271528
},
15281529
},
15291530
Spec: rmn.VolumeReplicationGroupSpec{

controllers/drplacementcontrol_controller.go

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ const (
5959
MaxPlacementDecisionConflictCount = 5
6060

6161
DestinationClusterAnnotationKey = "drplacementcontrol.ramendr.openshift.io/destination-cluster"
62+
63+
DoNotDeletePVCAnnotation = "drplacementcontrol.ramendr.openshift.io/do-not-delete-pvc"
64+
DoNotDeletePVCAnnotationVal = "true"
6265
)
6366

6467
var InitialWaitTimeForDRPCPlacementRule = errorswrapper.New("Waiting for DRPC Placement to produces placement decision")

controllers/volsync/vshandler.go

+62-24
Original file line numberDiff line numberDiff line change
@@ -521,22 +521,6 @@ func (v *VSHandler) TakePVCOwnership(pvcName string) (bool, error) {
521521
return false, err
522522
}
523523

524-
// Remove acm annotations from the PVC just as a precaution - ACM uses the annotations to track that the
525-
// pvc is owned by an application. Removing them should not be necessary now that we are adding
526-
// the do-not-delete annotation. With the do-not-delete annotation (see ACMAppSubDoNotDeleteAnnotation), ACM
527-
// should not delete the pvc when the application is removed.
528-
updatedAnnotations := map[string]string{}
529-
530-
for currAnnotationKey, currAnnotationValue := range pvc.Annotations {
531-
// We want to only preserve annotations not from ACM (i.e. remove all ACM annotations to break ownership)
532-
if !strings.HasPrefix(currAnnotationKey, "apps.open-cluster-management.io") ||
533-
currAnnotationKey == ACMAppSubDoNotDeleteAnnotation {
534-
updatedAnnotations[currAnnotationKey] = currAnnotationValue
535-
}
536-
}
537-
538-
pvc.Annotations = updatedAnnotations
539-
540524
err = v.client.Update(v.ctx, pvc)
541525
if err != nil {
542526
l.Error(err, "Error updating annotations on PVC to break appsub ownership")
@@ -578,21 +562,21 @@ func (v *VSHandler) pvcExistsAndInUse(pvcName string, inUsePodMustBeReady bool)
578562
return util.IsPVAttachedToNode(v.ctx, v.client, v.log, pvc)
579563
}
580564

581-
func (v *VSHandler) pvcExists(pvcName string) (bool, error) {
582-
_, err := v.getPVC(pvcName)
565+
func (v *VSHandler) pvcExists(pvcName string) (bool, *corev1.PersistentVolumeClaim, error) {
566+
pvc, err := v.getPVC(pvcName)
583567
if err != nil {
584568
if !kerrors.IsNotFound(err) {
585569
v.log.V(1).Info("failed to get PVC")
586570

587-
return false, err
571+
return false, pvc, err
588572
}
589573

590-
return false, nil
574+
return false, pvc, nil
591575
}
592576

593577
v.log.V(1).Info("PVC found")
594578

595-
return true, nil
579+
return true, pvc, nil
596580
}
597581

598582
func (v *VSHandler) getPVC(pvcName string) (*corev1.PersistentVolumeClaim, error) {
@@ -946,16 +930,16 @@ func (v *VSHandler) EnsurePVCforDirectCopy(ctx context.Context,
946930
return fmt.Errorf("capacity must be provided %v", rdSpec.ProtectedPVC)
947931
}
948932

949-
exists, err := v.pvcExists(rdSpec.ProtectedPVC.Name)
933+
exists, pvc, err := v.pvcExists(rdSpec.ProtectedPVC.Name)
950934
if err != nil {
951935
return err
952936
}
953937

954938
if exists {
955-
return nil
939+
return v.removeOCMAnnotationsAndUpdate(pvc)
956940
}
957941

958-
pvc := &corev1.PersistentVolumeClaim{
942+
pvc = &corev1.PersistentVolumeClaim{
959943
ObjectMeta: metav1.ObjectMeta{
960944
Name: rdSpec.ProtectedPVC.Name,
961945
Namespace: v.owner.GetNamespace(),
@@ -1043,6 +1027,17 @@ func (v *VSHandler) validateSnapshotAndEnsurePVC(rdSpec ramendrv1alpha1.VolSyncR
10431027
}
10441028
}
10451029

1030+
pvc, err := v.getPVC(rdSpec.ProtectedPVC.Name)
1031+
if err != nil {
1032+
return err
1033+
}
1034+
1035+
// Once the PVC is restored/rolled back, need to re-add the annotations from old Primary
1036+
err = v.addBackOCMAnnotationsAndUpdate(pvc, rdSpec.ProtectedPVC.Annotations)
1037+
if err != nil {
1038+
return err
1039+
}
1040+
10461041
// Add ownerRef on snapshot pointing to the vrg - if/when the VRG gets cleaned up, then GC can cleanup the snap
10471042
return v.addOwnerReferenceAndUpdate(snap, v.owner)
10481043
}
@@ -2110,3 +2105,46 @@ func (v *VSHandler) checkLastSnapshotSyncStatus(lrs *volsyncv1alpha1.Replication
21102105

21112106
return !completed
21122107
}
2108+
2109+
func (v *VSHandler) DisownVolSyncManagedPVC(pvc *corev1.PersistentVolumeClaim) error {
2110+
// TODO: Remove just the VRG ownerReference instead of blindly removing all ownerreferences.
2111+
// For now, this is fine, given that the VRG is the sole owner of the PVC after DR is enabled.
2112+
pvc.ObjectMeta.OwnerReferences = nil
2113+
v.deleteAnnotation(pvc, ACMAppSubDoNotDeleteAnnotation)
2114+
2115+
return v.client.Update(v.ctx, pvc)
2116+
}
2117+
2118+
func (v *VSHandler) deleteAnnotation(obj client.Object, annotationName string) {
2119+
annotations := obj.GetAnnotations()
2120+
delete(annotations, annotationName)
2121+
obj.SetAnnotations(annotations)
2122+
}
2123+
2124+
func (v *VSHandler) addBackOCMAnnotationsAndUpdate(obj client.Object, annotations map[string]string) error {
2125+
updatedAnnotations := obj.GetAnnotations()
2126+
2127+
for key, val := range annotations {
2128+
if strings.HasPrefix(key, "apps.open-cluster-management.io") {
2129+
updatedAnnotations[key] = val
2130+
}
2131+
}
2132+
2133+
obj.SetAnnotations(updatedAnnotations)
2134+
2135+
return v.client.Update(v.ctx, obj)
2136+
}
2137+
2138+
func (v *VSHandler) removeOCMAnnotationsAndUpdate(obj client.Object) error {
2139+
updatedAnnotations := map[string]string{}
2140+
2141+
for key, val := range obj.GetAnnotations() {
2142+
if !strings.HasPrefix(key, "apps.open-cluster-management.io") {
2143+
updatedAnnotations[key] = val
2144+
}
2145+
}
2146+
2147+
obj.SetAnnotations(updatedAnnotations)
2148+
2149+
return v.client.Update(v.ctx, obj)
2150+
}

controllers/volsync/vshandler_test.go

-19
Original file line numberDiff line numberDiff line change
@@ -1807,25 +1807,6 @@ var _ = Describe("VolSync_Handler", func() {
18071807
Expect(pvcPreparationErr).ToNot(HaveOccurred())
18081808
Expect(pvcPreparationComplete).To(BeTrue())
18091809

1810-
Eventually(func() int {
1811-
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(testPVC), testPVC)
1812-
if err != nil {
1813-
return 0
1814-
}
1815-
1816-
return len(testPVC.Annotations)
1817-
}, maxWait, interval).Should(Equal(len(initialAnnotations) - 2))
1818-
// We had 2 acm annotations in initialAnnotations
1819-
1820-
for key, val := range testPVC.Annotations {
1821-
if key != volsync.ACMAppSubDoNotDeleteAnnotation {
1822-
// Other ACM annotations should be deleted
1823-
Expect(strings.HasPrefix(key, "apps.open-cluster-management.io")).To(BeFalse())
1824-
1825-
Expect(initialAnnotations[key]).To(Equal(val)) // Other annotations should still be there
1826-
}
1827-
}
1828-
18291810
// ACM do-not-delete annotation should be added to the PVC
18301811
pvcAnnotations := testPVC.GetAnnotations()
18311812
val, ok := pvcAnnotations[volsync.ACMAppSubDoNotDeleteAnnotation]

controllers/volumereplicationgroup_controller.go

+6
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,12 @@ func (v *VRGInstance) processForDeletion() ctrl.Result {
774774

775775
defer v.log.Info("Exiting processing VolumeReplicationGroup")
776776

777+
if err := v.disownPVCs(); err != nil {
778+
v.log.Info("Disowning PVCs failed", "error", err)
779+
780+
return ctrl.Result{Requeue: true}
781+
}
782+
777783
if !containsString(v.instance.ObjectMeta.Finalizers, vrgFinalizerName) {
778784
v.log.Info("Finalizer missing from resource", "finalizer", vrgFinalizerName)
779785

controllers/vrg_volsync.go

+18
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,21 @@ func (v *VRGInstance) pvcUnprotectVolSync(pvc corev1.PersistentVolumeClaim, log
402402
// TODO Delete ReplicationSource, ReplicationDestination, etc.
403403
v.pvcStatusDeleteIfPresent(pvc.Namespace, pvc.Name, log)
404404
}
405+
406+
// disownPVCs this function is disassociating all PVCs (targeted for VolSync replication) from its owner (VRG)
407+
func (v *VRGInstance) disownPVCs() error {
408+
if v.instance.GetAnnotations()[DoNotDeletePVCAnnotation] != DoNotDeletePVCAnnotationVal {
409+
return nil
410+
}
411+
412+
for idx := range v.volSyncPVCs {
413+
pvc := &v.volSyncPVCs[idx]
414+
415+
err := v.volSyncHandler.DisownVolSyncManagedPVC(pvc)
416+
if err != nil {
417+
return err
418+
}
419+
}
420+
421+
return nil
422+
}

0 commit comments

Comments
 (0)