Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(controller): prevent volume/snapshot deletion if clone exists #606

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions pkg/driver/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <volname>@<snapname>
// parsing them here
snapshotID := strings.Split(req.SnapshotId, "@")
Expand Down Expand Up @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be FAILED_PRECONDITION

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should first evaluate the issue with what happens if we delete the volume/snapshot.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verified that if we delete the volume i.e pv and pvc the underneath zfs snapshot get deleted. Even though the zfs snapshot cr is available. To rectify this i have raised the PR #607

Before deleting the pvc

root@node-0-290533:~# zfs list -t all
NAME                                                                                                USED  AVAIL     REFER  MOUNTPOINT
zfspv-pool                                                                                          186K  9.20G       24K  /zfspv-pool
zfspv-pool/pvc-dd7c6d67-8451-43c3-bc56-993e9f41b1b3                                                24.5K  4.00G     24.5K  legacy
zfspv-pool/pvc-dd7c6d67-8451-43c3-bc56-993e9f41b1b3@snapshot-cc55c781-c4d5-4f7b-ac84-1b9582b469c6     0B      -     24.5K  -
zfspv-pool/pvc-dd7c6d67-8451-43c3-bc56-993e9f41b1b3@snapshot-19b7e7d1-f81f-435f-ae88-e73aa828ced8     0B      -     24.5K  -

After deleting the pvc

root@node-0-290533:~# zfs list -t all
NAME         USED  AVAIL     REFER  MOUNTPOINT
zfspv-pool   141K  9.20G       24K  /zfspv-pool

"failed to handle delete volume request for {%s} with %d clones",
req.GetSnapshotId(),
len(cloneList.Items),
)
}

return nil
}
18 changes: 18 additions & 0 deletions pkg/zfs/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading