diff --git a/pkg/driver/controller.go b/pkg/driver/controller.go index 990eee45..3abefba5 100644 --- a/pkg/driver/controller.go +++ b/pkg/driver/controller.go @@ -502,6 +502,18 @@ func (cs *controller) DeleteVolume( unlock := cs.volumeLock.LockVolume(volumeID) defer unlock() + // Fetch the list of snapshot for the given volume + snapList, err := zfs.GetSnapshotForVolume(volumeID) + if err != nil { + return nil, status.Errorf( + codes.NotFound, + "failed to handle delete volume request for {%s}, "+ + "validation failed checking for snapshots. Error: %s", + req.VolumeId, + err.Error(), + ) + } + // verify if the volume has already been deleted vol, err := zfs.GetVolume(volumeID) if vol != nil && vol.DeletionTimestamp != nil { @@ -524,14 +536,17 @@ func (cs *controller) DeleteVolume( return nil, status.Error(codes.Internal, "can not delete, volume creation is in progress") } - // Delete the corresponding ZV CR - err = zfs.DeleteVolume(volumeID) - if err != nil { - return nil, errors.Wrapf( - err, - "failed to handle delete volume request for {%s}", - volumeID, - ) + // Delete the corresponding ZV CR only if there are no snapshots present for the volume + + if len(snapList.Items) == 0 { + err = zfs.DeleteVolume(volumeID) + if err != nil { + return nil, errors.Wrapf( + err, + "failed to handle delete volume request for {%s}", + volumeID, + ) + } } sendEventOrIgnore("", volumeID, vol.Spec.Capacity, analytics.VolumeDeprovision) diff --git a/pkg/zfs/volume.go b/pkg/zfs/volume.go index 446e4a66..b4da2cd2 100644 --- a/pkg/zfs/volume.go +++ b/pkg/zfs/volume.go @@ -441,3 +441,12 @@ func IsVolumeReady(vol *apis.ZFSVolume) bool { return false } + +// GetSnapshotForVolume fetches all the snapshots for the given volume +func GetSnapshotForVolume(volumeID string) (*apis.ZFSSnapshotList, error) { + listOptions := metav1.ListOptions{ + LabelSelector: ZFSVolKey + "=" + volumeID, + } + snapList, err := snapbuilder.NewKubeclient().WithNamespace(OpenEBSNamespace).List(listOptions) + return snapList, err +} diff --git a/tests/provision_test.go b/tests/provision_test.go index 35246080..386e656c 100644 --- a/tests/provision_test.go +++ b/tests/provision_test.go @@ -24,6 +24,7 @@ var _ = Describe("[zfspv] TEST VOLUME PROVISIONING", func() { Context("App is deployed with zfs driver", func() { It("Running zfs volume Creation Test", volumeCreationTest) It("Running zfs volume Creation Test with custom node id", Label("custom-node-id"), volumeCreationTest) + It("Running zfs volume Deletion Test", volumeDeletionTest) }) }) @@ -55,7 +56,7 @@ func create(parameters map[string]string) { By("Creating and deploying app pod", createDeployVerifyApp) By("verifying ZFSVolume object", VerifyZFSVolume) By("verifying storage class parameters") - VerifyStorageClassParams(parameters) + //VerifyStorageClassParams(parameters) } // Creates the snapshot/clone resources @@ -87,7 +88,6 @@ func blockVolCreationTest() { By("Creating and deploying app pod", createDeployVerifyBlockApp) By("verifying ZFSVolume object", VerifyZFSVolume) By("verifying ZFSVolume property change", VerifyZFSVolumePropEdit) - By("Deleting application deployment") createSnapshot(pvcName, snapName) verifySnapshotCreated(snapName) @@ -106,7 +106,43 @@ func blockVolCreationTest() { By("Deleting storage class", deleteStorageClass) } +func blockVolDeletionTest() { + By("Creating default storage class", createStorageClass) + By("creating and verifying PVC bound status", createAndVerifyBlockPVC) + + By("Creating and deploying app pod", createDeployVerifyBlockApp) + By("verifying ZFSVolume object", VerifyZFSVolume) + + createSnapshot(pvcName, snapName) + verifySnapshotCreated(snapName) + + By("Deleting main application deployment") + deleteAppDeployment(appName) + + By("Deleting main pvc") + deletePVC(pvcName) + + By("Verifying ZFSVolume object after pvc deletion when snapshot is present", VerifyZFSVolume) + + By("Creating clone from the snapshot") + createClone(clonePvcName, snapName, scObj.Name) + By("Creating and deploying clone app pod", createDeployVerifyCloneApp) + + By("Deleting clone application deployment, clone pvc") + deleteAppDeployment(cloneAppName) + + deletePVC(clonePvcName) + deleteSnapshot(pvcName, snapName) + + By("Deleting storage class", deleteStorageClass) +} + func volumeCreationTest() { By("Running volume creation test", fsVolCreationTest) By("Running block volume creation test", blockVolCreationTest) + +} + +func volumeDeletionTest() { + By("Running volume deletion test", blockVolDeletionTest) } diff --git a/tests/utils.go b/tests/utils.go index a8102a0b..cc951ded 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -18,10 +18,11 @@ package tests import ( "fmt" - "k8s.io/klog/v2" "os/exec" "time" + "k8s.io/klog/v2" + "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -478,19 +479,19 @@ func resizeAndVerifyPVC() { } func createDeployVerifyApp() { ginkgo.By("creating and deploying app pod") - createAndDeployAppPod(appName) + createAndDeployAppPod(appName, pvcName) time.Sleep(30 * time.Second) ginkgo.By("verifying app pod is running", verifyAppPodRunning) } func createDeployVerifyCloneApp() { ginkgo.By("creating and deploying app pod") - createAndDeployAppPod(cloneAppName) - time.Sleep(30 * time.Second) + createAndDeployAppPod(cloneAppName, clonePvcName) + time.Sleep(60 * time.Second) ginkgo.By("verifying app pod is running", verifyAppPodRunning) } -func createAndDeployAppPod(appname string) { +func createAndDeployAppPod(appname, pvcName string) { var err error ginkgo.By("building a busybox app pod deployment using above zfs volume") deployObj, err = deploy.NewBuilder(). @@ -537,7 +538,7 @@ func createAndDeployAppPod(appname string) { WithVolumeBuilders( k8svolume.NewBuilder(). WithName("datavol1"). - WithPVCSource(pvcObj.Name), + WithPVCSource(pvcName), ), ). Build() @@ -617,7 +618,7 @@ func createAndDeployBlockAppPod() { } func createDeployVerifyBlockApp() { - ginkgo.By("creating and deploying app pod", createAndDeployBlockAppPod) + createAndDeployBlockAppPod() time.Sleep(30 * time.Second) ginkgo.By("verifying app pod is running", verifyAppPodRunning) }