Skip to content

Commit 5edf03c

Browse files
committed
Copy volume from source volume
1 parent 26b1a8d commit 5edf03c

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

deploy/example/pvc-volume-clone.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: PersistentVolumeClaim
3+
metadata:
4+
name: pvc-nfs-clone
5+
namespace: default
6+
spec:
7+
accessModes:
8+
- ReadWriteMany
9+
resources:
10+
requests:
11+
storage: 10Gi
12+
storageClassName: nfs-csi
13+
dataSource:
14+
kind: PersistentVolumeClaim
15+
name: pvc-nfs-dynamic

pkg/nfs/controllerserver.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package nfs
1919
import (
2020
"fmt"
2121
"os"
22+
"os/exec"
2223
"path/filepath"
2324
"regexp"
2425
"strconv"
@@ -143,12 +144,19 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
143144
}
144145
}
145146

147+
if req.GetVolumeContentSource() != nil {
148+
if err := cs.copyVolume(ctx, req, nfsVol); err != nil {
149+
return nil, err
150+
}
151+
}
152+
146153
setKeyValueInMap(parameters, paramSubDir, nfsVol.subDir)
147154
return &csi.CreateVolumeResponse{
148155
Volume: &csi.Volume{
149156
VolumeId: nfsVol.id,
150157
CapacityBytes: 0, // by setting it to zero, Provisioner will use PVC requested size as PV size
151158
VolumeContext: parameters,
159+
ContentSource: req.GetVolumeContentSource(),
152160
},
153161
}, nil
154162
}
@@ -307,6 +315,52 @@ func (cs *ControllerServer) internalUnmount(ctx context.Context, vol *nfsVolume)
307315
return err
308316
}
309317

318+
func (cs *ControllerServer) copyFromVolume(ctx context.Context, req *csi.CreateVolumeRequest, dstVol *nfsVolume) error {
319+
srcVol, err := getNfsVolFromID(req.GetVolumeContentSource().GetVolume().GetVolumeId())
320+
if err != nil {
321+
return err
322+
}
323+
srcPath := getInternalVolumePath(cs.Driver.workingMountDir, srcVol)
324+
dstPath := getInternalVolumePath(cs.Driver.workingMountDir, dstVol)
325+
klog.V(2).Infof("copy volume from volume %v -> %v", srcPath, dstPath)
326+
327+
var volCap *csi.VolumeCapability
328+
if len(req.GetVolumeCapabilities()) > 0 {
329+
volCap = req.GetVolumeCapabilities()[0]
330+
}
331+
if err = cs.internalMount(ctx, srcVol, nil, volCap); err != nil {
332+
return status.Errorf(codes.Internal, "failed to mount src nfs server: %v", err.Error())
333+
}
334+
defer func() {
335+
if err = cs.internalUnmount(ctx, srcVol); err != nil {
336+
klog.Warningf("failed to unmount nfs server: %v", err.Error())
337+
}
338+
}()
339+
if err = cs.internalMount(ctx, dstVol, nil, volCap); err != nil {
340+
return status.Errorf(codes.Internal, "failed to mount dst nfs server: %v", err.Error())
341+
}
342+
defer func() {
343+
if err = cs.internalUnmount(ctx, dstVol); err != nil {
344+
klog.Warningf("failed to unmount dst nfs server: %v", err.Error())
345+
}
346+
}()
347+
out, err := exec.Command("cp", "-a", fmt.Sprintf("%v%v.", srcPath, filepath.Separator), dstPath).CombinedOutput()
348+
klog.V(2).Infof("copied %s -> %s output: %v", srcPath, dstPath, string(out))
349+
return err
350+
}
351+
352+
func (cs *ControllerServer) copyVolume(ctx context.Context, req *csi.CreateVolumeRequest, vol *nfsVolume) error {
353+
vs := req.VolumeContentSource
354+
switch vs.Type.(type) {
355+
case *csi.VolumeContentSource_Snapshot:
356+
return status.Error(codes.Unimplemented, "Currently only volume copy from another volume is supported")
357+
case *csi.VolumeContentSource_Volume:
358+
return cs.copyFromVolume(ctx, req, vol)
359+
default:
360+
return status.Errorf(codes.InvalidArgument, "%v not a proper volume source", vs)
361+
}
362+
}
363+
310364
// newNFSVolume Convert VolumeCreate parameters to an nfsVolume
311365
func newNFSVolume(name string, size int64, params map[string]string) (*nfsVolume, error) {
312366
var server, baseDir, subDir string

pkg/nfs/nfs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func NewDriver(options *DriverOptions) *Driver {
8484
n.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{
8585
csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
8686
csi.ControllerServiceCapability_RPC_SINGLE_NODE_MULTI_WRITER,
87+
csi.ControllerServiceCapability_RPC_CLONE_VOLUME,
8788
})
8889

8990
n.AddNodeServiceCapabilities([]csi.NodeServiceCapability_RPC_Type{

0 commit comments

Comments
 (0)