diff --git a/pkg/driver/controller.go b/pkg/driver/controller.go index e1ef8fdf..82d0f286 100644 --- a/pkg/driver/controller.go +++ b/pkg/driver/controller.go @@ -808,6 +808,10 @@ func (cs *controller) DeleteSnapshot( klog.Infof("DeleteSnapshot request for %s", req.SnapshotId) + if err := cs.validateDeleteSnapshotReq(req); err != nil { + return nil, err + } + // snapshodID is formed as @ // parsing them here snapshotID := strings.Split(req.SnapshotId, "@") @@ -1129,3 +1133,32 @@ func LabelIndexFunc(label string) cache.IndexFunc { return vs, nil } } + +func (cs *controller) validateDeleteSnapshotReq(req *csi.DeleteSnapshotRequest) error { + if req.GetSnapshotId() == "" { + return status.Errorf(codes.InvalidArgument, "DeleteSnapshot: empty snapshotID") + } + + cloneList, err := zfs.GetClonesForSnapshot(req.SnapshotId) + if err != nil { + return status.Errorf( + codes.NotFound, + "failed to handle delete snapshot request for {%s}, "+ + "validation failed checking for existing clones. Error: %s", + req.GetSnapshotId(), + err.Error(), + ) + } + + // snapshot delete is not supported if clones exist for this snapshot + if len(cloneList.Items) != 0 { + return status.Errorf( + codes.Internal, + "failed to handle delete volume request for {%s} with %d clones", + req.GetSnapshotId(), + len(cloneList.Items), + ) + } + + return nil +} diff --git a/pkg/zfs/volume.go b/pkg/zfs/volume.go index 44a75427..f9df41e2 100644 --- a/pkg/zfs/volume.go +++ b/pkg/zfs/volume.go @@ -315,6 +315,24 @@ func GetZFSSnapshotStatus(snapID string) (string, error) { return snap.Status.State, nil } +// GetClonesForSnapshot lists all the clone volumes for the given snapshot +func GetClonesForSnapshot(snapID string) (*apis.ZFSVolumeList, error) { + zfsVolList, err := volbuilder.NewKubeclient().WithNamespace(OpenEBSNamespace).List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + + listBuilder := volbuilder.ListBuilderFrom(*zfsVolList) + listBuilder.WithFilter(func(vol *volbuilder.ZFSVolume) bool { + if vol.Object.Spec.SnapName == snapID { + return true + } + return false + }) + + return listBuilder.List(), nil +} + // GetZFSSnapshotCapacity return capacity converted to int64 func GetZFSSnapshotCapacity(snap *apis.ZFSSnapshot) (int64, error) { if snap == nil {