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

feat(clone): add support for creating the Clone from volume as datasource #234

Merged
merged 2 commits into from
Nov 11, 2020
Merged
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
1 change: 1 addition & 0 deletions changelogs/unreleased/234-pawanpraka1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add support for creating the Clone from volume as datasource
57 changes: 54 additions & 3 deletions pkg/driver/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,56 @@ func CreateZFSVolume(req *csi.CreateVolumeRequest) (string, error) {
return selected, nil
}

// CreateZFSClone create a clone of zfs volume
func CreateZFSClone(req *csi.CreateVolumeRequest, snapshot string) (string, error) {
// CreateVolClone creates the clone from a volume
func CreateVolClone(req *csi.CreateVolumeRequest, srcVol string) (string, error) {
volName := req.GetName()
parameters := req.GetParameters()
// lower case keys, cf CreateZFSVolume()
pool := helpers.GetInsensitiveParameter(&parameters, "poolname")
size := getRoundedCapacity(req.GetCapacityRange().RequiredBytes)
volsize := strconv.FormatInt(int64(size), 10)

vol, err := zfs.GetZFSVolume(srcVol)
if err != nil {
return "", status.Error(codes.NotFound, err.Error())
}

if vol.Spec.PoolName != pool {
return "", status.Errorf(codes.Internal,
"clone: different pool src pool %s dst pool %s",
vol.Spec.PoolName, pool)
}

if vol.Spec.Capacity != volsize {
return "", status.Error(codes.Internal, "clone: volume size is not matching")
}

selected := vol.Spec.OwnerNodeID

labels := map[string]string{zfs.ZFSSrcVolKey: vol.Name}

// create the clone from the source volume

volObj, err := volbuilder.NewBuilder().
WithName(volName).
WithVolumeStatus(zfs.ZFSStatusPending).
WithLabels(labels).Build()

volObj.Spec = vol.Spec
// use the snapshot name same as new volname
volObj.Spec.SnapName = vol.Name + "@" + volName

err = zfs.ProvisionVolume(volObj)
if err != nil {
return "", status.Errorf(codes.Internal,
"clone: not able to provision the volume %s", err.Error())
}

return selected, nil
}

// CreateSnapClone creates the clone from a snapshot
func CreateSnapClone(req *csi.CreateVolumeRequest, snapshot string) (string, error) {

volName := req.GetName()
parameters := req.GetParameters()
Expand Down Expand Up @@ -243,7 +291,10 @@ func (cs *controller) CreateVolume(
if contentSource != nil && contentSource.GetSnapshot() != nil {
snapshotID := contentSource.GetSnapshot().GetSnapshotId()

selected, err = CreateZFSClone(req, snapshotID)
selected, err = CreateSnapClone(req, snapshotID)
} else if contentSource != nil && contentSource.GetVolume() != nil {
srcVol := contentSource.GetVolume().GetVolumeId()
selected, err = CreateVolClone(req, srcVol)
} else {
selected, err = CreateZFSVolume(req)
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/zfs/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const (
ZFSFinalizer string = "zfs.openebs.io/finalizer"
// ZFSVolKey for the ZfsSnapshot CR to store Persistence Volume name
ZFSVolKey string = "openebs.io/persistent-volume"
// ZFSSrcVolKey key for the source Volume name
ZFSSrcVolKey string = "openebs.io/source-volume"
// PoolNameKey is key for ZFS pool name
PoolNameKey string = "openebs.io/poolname"
// ZFSNodeKey will be used to insert Label in ZfsVolume CR
Expand Down
41 changes: 41 additions & 0 deletions pkg/zfs/zfs_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,26 @@ func CreateVolume(vol *apis.ZFSVolume) error {
func CreateClone(vol *apis.ZFSVolume) error {
volume := vol.Spec.PoolName + "/" + vol.Name

if srcVol, ok := vol.Labels[ZFSSrcVolKey]; ok {
// datasource is volume, create the snapshot first
snap := &apis.ZFSSnapshot{}
snap.Name = vol.Name // use volname as snapname
snap.Spec = vol.Spec
// add src vol name
snap.Labels = map[string]string{ZFSVolKey: srcVol}

klog.Infof("creating snapshot %s@%s for the clone %s", srcVol, snap.Name, volume)

err := CreateSnapshot(snap)

if err != nil {
klog.Errorf(
"zfs: could not create snapshot for the clone vol %s snap %s err %v", volume, snap.Name, err,
)
return err
}
}

if err := getVolume(volume); err != nil {
var args []string
args = buildCloneCreateArgs(vol)
Expand Down Expand Up @@ -580,6 +600,27 @@ func DestroyVolume(vol *apis.ZFSVolume) error {
)
return err
}

if srcVol, ok := vol.Labels[ZFSSrcVolKey]; ok {
// datasource is volume, delete the dependent snapshot
snap := &apis.ZFSSnapshot{}
snap.Name = vol.Name // snapname is same as volname
snap.Spec = vol.Spec
// add src vol name
snap.Labels = map[string]string{ZFSVolKey: srcVol}

klog.Infof("destroying snapshot %s@%s for the clone %s", srcVol, snap.Name, volume)

err := DestroySnapshot(snap)
Copy link
Member

Choose a reason for hiding this comment

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

Here is where the source volume needs to be cleaned up, in case this was the last clone/snapshot being deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, not for the last clone/snapshot being deleted, every clone will have a corresponsing snapshot. So when we are deleting the clone volume, we should delete the corresponding snapshot here.


if err != nil {
// no need to reconcile as volume has already been deleted
klog.Errorf(
"zfs: could not destroy snapshot for the clone vol %s snap %s err %v", volume, snap.Name, err,
)
}
}

klog.Infof("destroyed volume %s", volume)

return nil
Expand Down