Skip to content

Commit fdc815e

Browse files
committed
Use watch instead of poll to check PVC/VolumeSnapshot deletion
1 parent cae0b46 commit fdc815e

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

pkg/csi/service/common/common_controller_helper.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/client/v8/clientset/versioned"
2828
apierrors "k8s.io/apimachinery/pkg/api/errors"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"k8s.io/apimachinery/pkg/fields"
3031
"k8s.io/apimachinery/pkg/util/wait"
32+
"k8s.io/apimachinery/pkg/watch"
3133
clientset "k8s.io/client-go/kubernetes"
3234

3335
"github.com/container-storage-interface/spec/lib/go/csi"
@@ -448,3 +450,103 @@ func WaitForVolumeSnapshotDeleted(ctx context.Context, client snapshotterClientS
448450

449451
return nil
450452
}
453+
454+
// WaitForVolumeSnapshotDeletedWithWatch waits for a VolumeSnapshot to get deleted using Watch API instead of polling.
455+
func WaitForVolumeSnapshotDeletedWithWatch(ctx context.Context, client snapshotterClientSet.Interface,
456+
snapshotName string, namespace string, timeout time.Duration) error {
457+
log := logger.GetLogger(ctx)
458+
timeoutSeconds := int64(timeout.Seconds())
459+
460+
log.Infof("Waiting up to %d seconds for VolumeSnapshot %s in namespace %s to be deleted using Watch API",
461+
timeoutSeconds, snapshotName, namespace)
462+
463+
// First check if VolumeSnapshot already exists
464+
_, err := client.SnapshotV1().VolumeSnapshots(namespace).Get(ctx, snapshotName, metav1.GetOptions{})
465+
if err != nil {
466+
if apierrors.IsNotFound(err) {
467+
log.Infof("VolumeSnapshot %s/%s is already deleted", namespace, snapshotName)
468+
return nil
469+
}
470+
return fmt.Errorf("unable to fetch VolumeSnapshot %s/%s with err: %+v", namespace, snapshotName, err)
471+
}
472+
473+
// Set up watch for the specific VolumeSnapshot
474+
watchSnapshot, err := client.SnapshotV1().VolumeSnapshots(namespace).Watch(
475+
ctx,
476+
metav1.ListOptions{
477+
FieldSelector: fields.OneTermEqualSelector("metadata.name", snapshotName).String(),
478+
TimeoutSeconds: &timeoutSeconds,
479+
Watch: true,
480+
})
481+
if err != nil {
482+
return fmt.Errorf("failed to watch VolumeSnapshot %s in namespace %s with Error: %+v",
483+
snapshotName, namespace, err)
484+
}
485+
defer watchSnapshot.Stop()
486+
487+
// Watch for deletion events
488+
for event := range watchSnapshot.ResultChan() {
489+
switch event.Type {
490+
case watch.Deleted:
491+
log.Infof("VolumeSnapshot %s/%s was deleted", namespace, snapshotName)
492+
return nil
493+
case watch.Error:
494+
return fmt.Errorf("error watching VolumeSnapshot %s/%s: %+v", namespace, snapshotName, event.Object)
495+
}
496+
// Continue watching for other event types (Added, Modified)
497+
}
498+
499+
// If we reach here, the watch timed out
500+
return fmt.Errorf("volumeSnapshot %s/%s was not deleted within %d seconds",
501+
namespace, snapshotName, timeoutSeconds)
502+
}
503+
504+
// WaitForPVCDeletedWithWatch waits for a PVC to get deleted using Watch API instead of polling.
505+
func WaitForPVCDeletedWithWatch(ctx context.Context, client clientset.Interface, pvcName string,
506+
namespace string, timeout time.Duration) error {
507+
log := logger.GetLogger(ctx)
508+
timeoutSeconds := int64(timeout.Seconds())
509+
510+
log.Infof("Waiting up to %d seconds for PersistentVolumeClaim %s in namespace %s to be deleted using Watch API",
511+
timeoutSeconds, pvcName, namespace)
512+
513+
// First check if PVC already exists
514+
_, err := client.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{})
515+
if err != nil {
516+
if apierrors.IsNotFound(err) {
517+
log.Infof("PersistentVolumeClaim %s/%s is already deleted", namespace, pvcName)
518+
return nil
519+
}
520+
return fmt.Errorf("unable to fetch PersistentVolumeClaim %s/%s with err: %+v", namespace, pvcName, err)
521+
}
522+
523+
// Set up watch for the specific PVC
524+
watchPVC, err := client.CoreV1().PersistentVolumeClaims(namespace).Watch(
525+
ctx,
526+
metav1.ListOptions{
527+
FieldSelector: fields.OneTermEqualSelector("metadata.name", pvcName).String(),
528+
TimeoutSeconds: &timeoutSeconds,
529+
Watch: true,
530+
})
531+
if err != nil {
532+
return fmt.Errorf("failed to watch PersistentVolumeClaim %s in namespace %s with Error: %+v",
533+
pvcName, namespace, err)
534+
}
535+
defer watchPVC.Stop()
536+
537+
// Watch for deletion events
538+
for event := range watchPVC.ResultChan() {
539+
switch event.Type {
540+
case watch.Deleted:
541+
log.Infof("PersistentVolumeClaim %s/%s was deleted", namespace, pvcName)
542+
return nil
543+
case watch.Error:
544+
return fmt.Errorf("error watching PersistentVolumeClaim %s/%s: %+v", namespace, pvcName, event.Object)
545+
}
546+
// Continue watching for other event types (Added, Modified)
547+
}
548+
549+
// If we reach here, the watch timed out
550+
return fmt.Errorf("persistentVolumeClaim %s/%s was not deleted within %d seconds",
551+
namespace, pvcName, timeoutSeconds)
552+
}

pkg/csi/service/wcpguest/controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ func (c *controller) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequ
639639
}
640640

641641
// Wait for PVC to be deleted from supervisor cluster
642-
err = common.WaitForPVCDeleted(ctx, c.supervisorClient,
642+
err = common.WaitForPVCDeletedWithWatch(ctx, c.supervisorClient,
643643
req.VolumeId, c.supervisorNamespace,
644644
time.Duration(getProvisionTimeoutInMin(ctx))*time.Minute)
645645
if err != nil {
@@ -1796,7 +1796,7 @@ func (c *controller) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshot
17961796
}
17971797

17981798
// Wait for VolumeSnapshot to be deleted from supervisor cluster
1799-
err = common.WaitForVolumeSnapshotDeleted(ctx, c.supervisorSnapshotterClient,
1799+
err = common.WaitForVolumeSnapshotDeletedWithWatch(ctx, c.supervisorSnapshotterClient,
18001800
supervisorVolumeSnapshotName, c.supervisorNamespace,
18011801
time.Duration(getSnapshotTimeoutInMin(ctx))*time.Minute)
18021802
if err != nil {

0 commit comments

Comments
 (0)