Skip to content

Commit fac946a

Browse files
committed
feat: snapshot path to include src volume name/uuid
1 parent 8aad486 commit fac946a

File tree

1 file changed

+68
-20
lines changed

1 file changed

+68
-20
lines changed

pkg/nfs/controllerserver.go

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package nfs
1818

1919
import (
2020
"fmt"
21+
"io/fs"
2122
"os"
2223
"os/exec"
2324
"path/filepath"
@@ -71,10 +72,20 @@ type nfsSnapshot struct {
7172
baseDir string
7273
// Snapshot name.
7374
uuid string
75+
// Source volume.
76+
src string
77+
}
78+
79+
func (snap nfsSnapshot) archiveSubPath() string {
80+
return snap.uuid
7481
}
7582

7683
func (snap nfsSnapshot) archiveName() string {
77-
return fmt.Sprintf("%v.tar.gz", snap.uuid)
84+
return fmt.Sprintf("%v.tar.gz", snap.src)
85+
}
86+
87+
func (snap nfsSnapshot) archivePath() string {
88+
return filepath.Join(snap.archiveSubPath(), snap.archiveName())
7889
}
7990

8091
// Ordering of elements in the CSI volume id.
@@ -92,14 +103,15 @@ const (
92103
)
93104

94105
// Ordering of elements in the CSI snapshot id.
95-
// ID is of the form {server}/{baseDir}/snapshots.
106+
// ID is of the form {server}/{baseDir}/{snap_name}/{src_name}.
96107
// Adding a new element should always go at the end
97108
// before totalSnapIDElements
98109
const (
99110
idSnapServer = iota
100111
idSnapBaseDir
101112
idSnapUUID
102-
idSnapArchive
113+
idSnapArchivePath
114+
idSnapArchiveName
103115
totalIDSnapElements // Always last
104116
)
105117

@@ -309,6 +321,13 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
309321
klog.Warningf("failed to unmount snapshot nfs server: %v", err)
310322
}
311323
}()
324+
snapInternalVolPath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, snapVol), snapshot.archiveSubPath())
325+
if err = os.MkdirAll(snapInternalVolPath, 0777); err != nil {
326+
return nil, status.Errorf(codes.Internal, "failed to make subdirectory: %v", err)
327+
}
328+
if err := validateSnapshot(snapInternalVolPath, snapshot); err != nil {
329+
return nil, err
330+
}
312331

313332
if err = cs.internalMount(ctx, srcVol, nil, nil); err != nil {
314333
return nil, status.Errorf(codes.Internal, "failed to mount src nfs server: %v", err)
@@ -320,7 +339,7 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
320339
}()
321340

322341
srcPath := getInternalVolumePath(cs.Driver.workingMountDir, srcVol)
323-
dstPath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, snapVol), snapshot.archiveName())
342+
dstPath := filepath.Join(snapInternalVolPath, snapshot.archiveName())
324343
klog.V(2).Infof("archiving %v -> %v", srcPath, dstPath)
325344
out, err := exec.Command("tar", "-C", srcPath, "-czvf", dstPath, ".").CombinedOutput()
326345
if err != nil {
@@ -380,7 +399,7 @@ func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteS
380399
}()
381400

382401
// delete snapshot archive
383-
internalVolumePath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, vol), snap.archiveName())
402+
internalVolumePath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, vol), snap.archiveSubPath())
384403
klog.V(2).Infof("Removing snapshot archive at %v", internalVolumePath)
385404
if err = os.RemoveAll(internalVolumePath); err != nil {
386405
return nil, status.Errorf(codes.Internal, "failed to delete subdirectory: %v", err.Error())
@@ -397,17 +416,6 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
397416
return nil, status.Error(codes.Unimplemented, "")
398417
}
399418

400-
// Volume for snapshot internal mount/unmount
401-
func volumeFromSnapshot(snap *nfsSnapshot) *nfsVolume {
402-
return &nfsVolume{
403-
id: snap.id,
404-
server: snap.server,
405-
baseDir: snap.baseDir,
406-
subDir: snap.baseDir,
407-
uuid: snap.uuid,
408-
}
409-
}
410-
411419
// Mount nfs server at base-dir
412420
func (cs *ControllerServer) internalMount(ctx context.Context, vol *nfsVolume, volumeContext map[string]string, volCap *csi.VolumeCapability) error {
413421
if volCap == nil {
@@ -485,7 +493,7 @@ func (cs *ControllerServer) copyFromSnapshot(ctx context.Context, req *csi.Creat
485493
}()
486494

487495
// untar snapshot archive to dst path
488-
snapPath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, snapVol), snap.archiveName())
496+
snapPath := filepath.Join(getInternalVolumePath(cs.Driver.workingMountDir, snapVol), snap.archivePath())
489497
dstPath := getInternalVolumePath(cs.Driver.workingMountDir, dstVol)
490498
klog.V(2).Infof("copy volume from snapshot %v -> %v", snapPath, dstPath)
491499
out, err := exec.Command("tar", "-xzvf", snapPath, "-C", dstPath).CombinedOutput()
@@ -568,6 +576,15 @@ func newNFSSnapshot(name string, params map[string]string, vol *nfsVolume) (*nfs
568576
baseDir: baseDir,
569577
uuid: name,
570578
}
579+
if vol.uuid != "" {
580+
snapshot.src = vol.uuid
581+
}
582+
if vol.subDir != "" {
583+
snapshot.src = vol.subDir
584+
}
585+
if snapshot.src == "" {
586+
return nil, fmt.Errorf("missing required source volume name")
587+
}
571588
snapshot.id = getSnapshotIDFromNfsSnapshot(snapshot)
572589
return snapshot, nil
573590
}
@@ -656,7 +673,8 @@ func getSnapshotIDFromNfsSnapshot(snap *nfsSnapshot) string {
656673
idElements[idSnapServer] = strings.Trim(snap.server, "/")
657674
idElements[idSnapBaseDir] = strings.Trim(snap.baseDir, "/")
658675
idElements[idSnapUUID] = snap.uuid
659-
idElements[idSnapArchive] = snap.archiveName()
676+
idElements[idSnapArchivePath] = snap.uuid
677+
idElements[idSnapArchiveName] = snap.src
660678
return strings.Join(idElements, separator)
661679
}
662680

@@ -702,14 +720,15 @@ func getNfsVolFromID(id string) (*nfsVolume, error) {
702720
// Given a CSI snapshot ID, return a nfsSnapshot
703721
// sample snapshot ID:
704722
//
705-
// nfs-server.default.svc.cluster.local#share#snapshot-016f784f-56f4-44d1-9041-5f59e82dbce1#snapshot-016f784f-56f4-44d1-9041-5f59e82dbce1.tar.gz
723+
// nfs-server.default.svc.cluster.local#share#snapshot-016f784f-56f4-44d1-9041-5f59e82dbce1#snapshot-016f784f-56f4-44d1-9041-5f59e82dbce1#pvc-4bcbf944-b6f7-4bd0-b50f-3c3dd00efc64
706724
func getNfsSnapFromID(id string) (*nfsSnapshot, error) {
707725
segments := strings.Split(id, separator)
708-
if len(segments) == 4 {
726+
if len(segments) == totalIDSnapElements {
709727
return &nfsSnapshot{
710728
id: id,
711729
server: segments[idSnapServer],
712730
baseDir: segments[idSnapBaseDir],
731+
src: segments[idSnapArchiveName],
713732
uuid: segments[idSnapUUID],
714733
}, nil
715734
}
@@ -729,3 +748,32 @@ func isValidVolumeCapabilities(volCaps []*csi.VolumeCapability) error {
729748
}
730749
return nil
731750
}
751+
752+
// Validate snapshot after internal mount
753+
func validateSnapshot(snapInternalVolPath string, snap *nfsSnapshot) error {
754+
return filepath.WalkDir(snapInternalVolPath, func(path string, d fs.DirEntry, err error) error {
755+
if path == snapInternalVolPath {
756+
// skip root
757+
return nil
758+
}
759+
if err != nil {
760+
return err
761+
}
762+
if d.Name() != snap.archiveName() {
763+
// there should be just one archive in the snapshot path and archive name should match
764+
return status.Errorf(codes.AlreadyExists, "snapshot with the same name but different source volume ID already exists: found %q, desired %q", d.Name(), snap.archiveName())
765+
}
766+
return nil
767+
})
768+
}
769+
770+
// Volume for snapshot internal mount/unmount
771+
func volumeFromSnapshot(snap *nfsSnapshot) *nfsVolume {
772+
return &nfsVolume{
773+
id: snap.id,
774+
server: snap.server,
775+
baseDir: snap.baseDir,
776+
subDir: snap.baseDir,
777+
uuid: snap.uuid,
778+
}
779+
}

0 commit comments

Comments
 (0)