Skip to content

Commit

Permalink
Copy volume from source volume
Browse files Browse the repository at this point in the history
  • Loading branch information
wozniakjan committed Mar 10, 2023
1 parent 26b1a8d commit 96c3078
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 0 deletions.
16 changes: 16 additions & 0 deletions deploy/example/pvc-volume-clone.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-nfs-clone
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-csi
dataSource:
kind: PersistentVolumeClaim
name: pvc-nfs-dynamic
57 changes: 57 additions & 0 deletions pkg/nfs/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package nfs
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
Expand Down Expand Up @@ -143,12 +144,19 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
}
}

if req.GetVolumeContentSource() != nil {
if err := cs.copyVolume(ctx, req, nfsVol); err != nil {
return nil, err
}
}

setKeyValueInMap(parameters, paramSubDir, nfsVol.subDir)
return &csi.CreateVolumeResponse{
Volume: &csi.Volume{
VolumeId: nfsVol.id,
CapacityBytes: 0, // by setting it to zero, Provisioner will use PVC requested size as PV size
VolumeContext: parameters,
ContentSource: req.GetVolumeContentSource(),
},
}, nil
}
Expand Down Expand Up @@ -307,6 +315,55 @@ func (cs *ControllerServer) internalUnmount(ctx context.Context, vol *nfsVolume)
return err
}

func (cs *ControllerServer) copyFromVolume(ctx context.Context, req *csi.CreateVolumeRequest, dstVol *nfsVolume) error {
srcVol, err := getNfsVolFromID(req.GetVolumeContentSource().GetVolume().GetVolumeId())
if err != nil {
return status.Error(codes.NotFound, err.Error())
}
srcPath := getInternalVolumePath(cs.Driver.workingMountDir, srcVol)
dstPath := getInternalVolumePath(cs.Driver.workingMountDir, dstVol)
klog.V(2).Infof("copy volume from volume %v -> %v", srcPath, dstPath)

var volCap *csi.VolumeCapability
if len(req.GetVolumeCapabilities()) > 0 {
volCap = req.GetVolumeCapabilities()[0]
}
if err = cs.internalMount(ctx, srcVol, nil, volCap); err != nil {
return status.Errorf(codes.Internal, "failed to mount src nfs server: %v", err.Error())
}
defer func() {
if err = cs.internalUnmount(ctx, srcVol); err != nil {
klog.Warningf("failed to unmount nfs server: %v", err.Error())
}
}()
if err = cs.internalMount(ctx, dstVol, nil, volCap); err != nil {
return status.Errorf(codes.Internal, "failed to mount dst nfs server: %v", err.Error())
}
defer func() {
if err = cs.internalUnmount(ctx, dstVol); err != nil {
klog.Warningf("failed to unmount dst nfs server: %v", err.Error())
}
}()
out, err := exec.Command("cp", "-a", fmt.Sprintf("%v%v.", srcPath, filepath.Separator), dstPath).CombinedOutput()
klog.V(2).Infof("copied %s -> %s output: %v", srcPath, dstPath, string(out))
if err != nil {
return status.Error(codes.Internal, err.Error())
}
return nil
}

func (cs *ControllerServer) copyVolume(ctx context.Context, req *csi.CreateVolumeRequest, vol *nfsVolume) error {
vs := req.VolumeContentSource
switch vs.Type.(type) {
case *csi.VolumeContentSource_Snapshot:
return status.Error(codes.Unimplemented, "Currently only volume copy from another volume is supported")
case *csi.VolumeContentSource_Volume:
return cs.copyFromVolume(ctx, req, vol)
default:
return status.Errorf(codes.InvalidArgument, "%v not a proper volume source", vs)
}
}

// newNFSVolume Convert VolumeCreate parameters to an nfsVolume
func newNFSVolume(name string, size int64, params map[string]string) (*nfsVolume, error) {
var server, baseDir, subDir string
Expand Down
7 changes: 7 additions & 0 deletions pkg/nfs/controllerserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ func TestControllerGetCapabilities(t *testing.T) {
},
},
},
{
Type: &csi.ControllerServiceCapability_Rpc{
Rpc: &csi.ControllerServiceCapability_RPC{
Type: csi.ControllerServiceCapability_RPC_CLONE_VOLUME,
},
},
},
},
},
expectedErr: nil,
Expand Down
1 change: 1 addition & 0 deletions pkg/nfs/nfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func NewDriver(options *DriverOptions) *Driver {
n.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
csi.ControllerServiceCapability_RPC_SINGLE_NODE_MULTI_WRITER,
csi.ControllerServiceCapability_RPC_CLONE_VOLUME,
})

n.AddNodeServiceCapabilities([]csi.NodeServiceCapability_RPC_Type{
Expand Down

0 comments on commit 96c3078

Please sign in to comment.