Skip to content

Commit c3d32fe

Browse files
committed
updated csi-cvmfs to 0.3.0
* added support for NodeStageVolume/NodeUnstageVolume * refactoring
1 parent 85505a5 commit c3d32fe

File tree

7 files changed

+248
-169
lines changed

7 files changed

+248
-169
lines changed

pkg/cvmfs/controllerserver.go

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cvmfs
22

33
import (
44
"context"
5-
"fmt"
65

76
"github.com/golang/glog"
87
"google.golang.org/grpc/codes"
@@ -16,41 +15,19 @@ type controllerServer struct {
1615
*csicommon.DefaultControllerServer
1716
}
1817

19-
func (cs *controllerServer) validateCreateVolumeRequest(req *csi.CreateVolumeRequest) error {
20-
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
21-
return fmt.Errorf("invalid CreateVolumeRequest: %v", err)
22-
}
23-
24-
if req.GetName() == "" {
25-
return fmt.Errorf("volume name cannot be empty")
26-
}
27-
28-
if req.GetVolumeCapabilities() == nil {
29-
return fmt.Errorf("volume capabilities cannot be empty")
30-
}
31-
32-
return nil
33-
}
34-
35-
func (cs *controllerServer) validateDeleteVolumeRequest(req *csi.DeleteVolumeRequest) error {
36-
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
37-
return fmt.Errorf("invalid DeleteVolumeRequest: %v", err)
38-
}
39-
40-
return nil
41-
}
42-
4318
func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) {
4419
if err := cs.validateCreateVolumeRequest(req); err != nil {
45-
glog.Errorf("CreateVolumeRequest validation failed: %v", err)
20+
glog.Errorf("failed to validate CreateVolumeRequest: %v", err)
4621
return nil, status.Error(codes.InvalidArgument, err.Error())
4722
}
4823

49-
volId := newVolumeIdentifier(req)
24+
volId := newVolumeID()
25+
26+
glog.Infof("cvmfs: successfuly created volume %s", volId)
5027

5128
return &csi.CreateVolumeResponse{
5229
Volume: &csi.Volume{
53-
Id: volId.id,
30+
Id: string(volId),
5431
Attributes: req.GetParameters(),
5532
CapacityBytes: req.GetCapacityRange().GetRequiredBytes(),
5633
},
@@ -59,16 +36,21 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
5936

6037
func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) {
6138
if err := cs.validateDeleteVolumeRequest(req); err != nil {
62-
glog.Errorf("DeleteVolumeRequest validation failed: %v", err)
39+
glog.Errorf("failed to validate DeleteVolumeRequest: %v", err)
6340
return nil, status.Error(codes.InvalidArgument, err.Error())
6441
}
6542

43+
glog.Infof("cvmfs: successfuly deleted volume %s", req.GetVolumeId())
44+
6645
return &csi.DeleteVolumeResponse{}, nil
6746
}
6847

69-
func (cs *controllerServer) ValidateVolumeCapabilities(ctx context.Context, req *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) {
48+
func (cs *controllerServer) ValidateVolumeCapabilities(
49+
ctx context.Context,
50+
req *csi.ValidateVolumeCapabilitiesRequest,
51+
) (*csi.ValidateVolumeCapabilitiesResponse, error) {
7052
for _, c := range req.GetVolumeCapabilities() {
71-
if c.AccessMode.GetMode() != csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY {
53+
if c.AccessMode.GetMode() != csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY || c.GetBlock() != nil {
7254
return &csi.ValidateVolumeCapabilitiesResponse{Supported: false}, nil
7355
}
7456
}

pkg/cvmfs/cvmfsconf.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const repoConf = `
1919
CVMFS_HTTP_PROXY={{.Proxy}}
2020
{{end}}
2121
22-
CVMFS_CACHE_BASE={{cacheBase .VolUuid}}
22+
CVMFS_CACHE_BASE={{cacheBase .VolumeId}}
2323
2424
{{if .Hash}}
2525
CVMFS_ROOT_HASH={{.Hash}}
@@ -48,13 +48,13 @@ func init() {
4848
}
4949

5050
type cvmfsConfigData struct {
51-
VolUuid string
51+
VolumeId volumeID
5252
Tag, Hash string
5353
Proxy string
5454
}
5555

5656
func (d *cvmfsConfigData) writeToFile() error {
57-
f, err := os.OpenFile(getConfigFilePath(d.VolUuid), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0755)
57+
f, err := os.OpenFile(getConfigFilePath(d.VolumeId), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0755)
5858
if err != nil {
5959
if os.IsExist(err) {
6060
return nil
@@ -67,6 +67,6 @@ func (d *cvmfsConfigData) writeToFile() error {
6767
return repoConfTempl.Execute(f, d)
6868
}
6969

70-
func getConfigFilePath(volUuid string) string {
71-
return path.Join(cvmfsConfigRoot, "config-csi-"+volUuid)
70+
func getConfigFilePath(volId volumeID) string {
71+
return path.Join(cvmfsConfigRoot, "config-csi-"+string(volId))
7272
}

pkg/cvmfs/driver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
const (
1111
PluginFolder = "/var/lib/kubelet/plugins/csi-cvmfsplugin"
12-
Version = "0.2.0"
12+
Version = "0.3.0"
1313
)
1414

1515
type cvmfsDriver struct {

pkg/cvmfs/nodeserver.go

Lines changed: 111 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cvmfs
22

33
import (
44
"context"
5-
"errors"
65
"os"
76

87
"github.com/golang/glog"
@@ -17,68 +16,82 @@ type nodeServer struct {
1716
*csicommon.DefaultNodeServer
1817
}
1918

20-
func validateNodePublishVolumeRequest(req *csi.NodePublishVolumeRequest) error {
21-
if req.GetVolumeCapability() == nil {
22-
return errors.New("Volume capability missing in request")
19+
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
20+
if err := validateNodeStageVolumeRequest(req); err != nil {
21+
glog.Errorf("failed to validate NodeStageVolumeRequest: %v", err)
22+
return nil, status.Error(codes.InvalidArgument, err.Error())
2323
}
2424

25-
if req.GetVolumeId() == "" {
26-
return errors.New("Volume ID missing in request")
27-
}
25+
// Configuration
2826

29-
if req.GetTargetPath() == "" {
30-
return errors.New("Target path missing in request")
31-
}
27+
stagingTargetPath := req.GetStagingTargetPath()
28+
volId := volumeID(req.GetVolumeId())
3229

33-
return nil
34-
}
30+
volOptions, err := newVolumeOptions(req.GetVolumeAttributes())
31+
if err != nil {
32+
glog.Errorf("invalid volume attributes for volume %s: %v", volId, err)
33+
return nil, status.Error(codes.InvalidArgument, err.Error())
34+
}
3535

36-
func validateNodeUnpublishVolumeRequest(req *csi.NodeUnpublishVolumeRequest) error {
37-
if req.GetVolumeId() == "" {
38-
return errors.New("Volume ID missing in request")
36+
if err = createMountPoint(stagingTargetPath); err != nil {
37+
glog.Errorf("failed to create staging mount point at %s for volume %s: %v", stagingTargetPath, volId, err)
38+
return nil, status.Error(codes.Internal, err.Error())
3939
}
4040

41-
if req.GetTargetPath() == "" {
42-
return errors.New("Target path missing in request")
41+
confData := cvmfsConfigData{
42+
VolumeId: volId,
43+
Tag: volOptions.Tag,
44+
Hash: volOptions.Hash,
45+
Proxy: volOptions.Proxy,
4346
}
4447

45-
return nil
46-
}
48+
if err := confData.writeToFile(); err != nil {
49+
glog.Errorf("failed to write cvmfs config for volume %s: %v", volId, err)
50+
return nil, status.Error(codes.Internal, err.Error())
51+
}
4752

48-
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
49-
if err := validateNodePublishVolumeRequest(req); err != nil {
50-
return nil, status.Error(codes.InvalidArgument, err.Error())
53+
if err := createVolumeCache(volId); err != nil {
54+
glog.Errorf("failed to create cache for volume %s: %v", volId, err)
5155
}
5256

53-
targetPath := req.GetTargetPath()
54-
volId := req.GetVolumeId()
55-
volUuid := uuidFromVolumeId(volId)
57+
// Check if the volume is already mounted
5658

57-
// Configuration
59+
isMnt, err := isMountPoint(stagingTargetPath)
5860

59-
volOptions, err := newVolumeOptions(req.GetVolumeAttributes())
6061
if err != nil {
61-
glog.Errorf("error reading volume options: %v", err)
62-
return nil, status.Error(codes.InvalidArgument, err.Error())
62+
glog.Errorf("stat failed: %v", err)
63+
return nil, status.Error(codes.Internal, err.Error())
6364
}
6465

65-
confData := cvmfsConfigData{
66-
VolUuid: volUuid,
67-
Tag: volOptions.Tag,
68-
Hash: volOptions.Hash,
69-
Proxy: volOptions.Proxy,
66+
if isMnt {
67+
glog.Infof("cvmfs: volume %s is already mounted to %s, skipping", volId, stagingTargetPath)
68+
return &csi.NodeStageVolumeResponse{}, nil
7069
}
7170

72-
if err := confData.writeToFile(); err != nil {
73-
glog.Errorf("failed to write cvmfs config for volume %s: %v", volId, err)
74-
return nil, status.Errorf(codes.Internal, err.Error())
71+
// It's not, mount now
72+
73+
if err = mountCvmfs(volOptions, volId, stagingTargetPath); err != nil {
74+
glog.Errorf("failed to mount volume %s to %s: %v", volId, stagingTargetPath, err)
75+
return nil, status.Error(codes.Internal, err.Error())
7576
}
7677

77-
if err := createVolumeCache(volUuid); err != nil {
78-
glog.Errorf("failed to create cache for volume %s: %v", volId, err)
78+
glog.Infof("cvmfs: successfuly mounted volume %s to %s", volId, stagingTargetPath)
79+
80+
return &csi.NodeStageVolumeResponse{}, nil
81+
}
82+
83+
func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
84+
if err := validateNodePublishVolumeRequest(req); err != nil {
85+
glog.Errorf("failed to validate NodePublishVolumeRequest: %v", err)
86+
return nil, status.Error(codes.InvalidArgument, err.Error())
7987
}
8088

81-
if err = createMountPoint(targetPath); err != nil {
89+
// Configuration
90+
91+
targetPath := req.GetTargetPath()
92+
volId := volumeID(req.GetVolumeId())
93+
94+
if err := createMountPoint(targetPath); err != nil {
8295
glog.Errorf("failed to create mount point for volume %s at %s: %v", volId, targetPath, err)
8396
return nil, status.Error(codes.Internal, err.Error())
8497
}
@@ -93,59 +106,94 @@ func (ns *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
93106
}
94107

95108
if isMnt {
96-
glog.V(4).Infof("cephfs: volume %s is already mounted to %s", volId, targetPath)
109+
glog.Infof("cvmfs: volume %s is already bind-mounted to %s", volId, targetPath)
97110
return &csi.NodePublishVolumeResponse{}, nil
98111
}
99112

100-
// It's not, mount now
113+
// It's not, bind-mount now
101114

102-
if err = mountVolume(targetPath, volOptions, volUuid); err != nil {
103-
glog.Errorf("failed to mount volume %s: %v", volId, err)
115+
if err = bindMount(req.GetStagingTargetPath(), targetPath); err != nil {
116+
glog.Errorf("failed to bind-mount volume %s to %s: %v", volId, targetPath, err)
104117
return nil, status.Error(codes.Internal, err.Error())
105118
}
106119

107-
glog.V(4).Infof("cvmfs: volume %s successfuly mounted to %s", volId, targetPath)
120+
glog.Infof("cvmfs: successfuly bind-mounted volume %s to %s", volId, targetPath)
108121

109122
return &csi.NodePublishVolumeResponse{}, nil
110123
}
111124

112125
func (ns *nodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) {
113126
if err := validateNodeUnpublishVolumeRequest(req); err != nil {
127+
glog.Errorf("failed to validate NodeUnpublishVolumeRequest: %v", err)
114128
return nil, status.Error(codes.InvalidArgument, err.Error())
115129
}
116130

117131
targetPath := req.GetTargetPath()
118-
volId := req.GetVolumeId()
119-
volUuid := uuidFromVolumeId(volId)
132+
volId := volumeID(req.GetVolumeId())
120133

121-
if err := unmountVolume(targetPath, volUuid); err != nil {
122-
glog.Errorf("failed to unmount volume %s: %v")
134+
// Unbind the volume
135+
136+
if err := unmountVolume(targetPath); err != nil {
137+
glog.Errorf("failed to unbind volume %s: %v")
123138
return nil, status.Error(codes.Internal, err.Error())
124139
}
125140

126-
if err := os.Remove(getVolumeRootPath(volUuid)); err != nil {
127-
glog.Error("failed to remove root for volume %s: %v", volId, err)
128-
return nil, status.Error(codes.Internal, err.Error())
141+
// Clean up
142+
143+
if err := os.Remove(targetPath); err != nil {
144+
glog.Errorf("cvmfs: cannot delete target path %s for volume %s: %v", targetPath, volId, err)
129145
}
130146

131-
if err := os.Remove(getConfigFilePath(volUuid)); err != nil {
132-
glog.Warningf("cannot remove config for volume %s: %v", volId, err)
147+
glog.Infof("cvmfs: successfuly unbinded volume %s from %s", volId, targetPath)
148+
149+
return &csi.NodeUnpublishVolumeResponse{}, nil
150+
}
151+
152+
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
153+
if err := validateNodeUnstageVolumeRequest(req); err != nil {
154+
glog.Errorf("failed to validate NodeUnstageVolumeRequest: %v", err)
155+
return nil, status.Error(codes.InvalidArgument, err.Error())
133156
}
134157

135-
if err := purgeVolumeCache(volUuid); err != nil {
136-
glog.Errorf("failed to delete cache for volume %s: %v", volId, err)
158+
stagingTargetPath := req.GetStagingTargetPath()
159+
volId := volumeID(req.GetVolumeId())
160+
161+
// Unmount the volume
162+
163+
if err := unmountVolume(stagingTargetPath); err != nil {
164+
glog.Errorf("failed unmount volume %s: %v", volId, err)
137165
return nil, status.Error(codes.Internal, err.Error())
138166
}
139167

140-
glog.V(4).Infof("cvmfs: volume %s successfuly unmounted from %s", req.GetVolumeId(), targetPath)
168+
// Clean up
141169

142-
return &csi.NodeUnpublishVolumeResponse{}, nil
143-
}
170+
if err := os.Remove(getConfigFilePath(volId)); err != nil {
171+
glog.Errorf("cvmfs: cannot remove config for volume %s: %v", volId, err)
172+
}
144173

145-
func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) {
146-
return nil, status.Error(codes.Unimplemented, "")
174+
if err := purgeVolumeCache(volId); err != nil {
175+
glog.Errorf("cvmfs: cannot delete cache for volume %s: %v", volId, err)
176+
}
177+
178+
if err := os.Remove(stagingTargetPath); err != nil {
179+
glog.Errorf("cvmfs: cannot delete staging target path %s for volume %s: %v", stagingTargetPath, volId, err)
180+
}
181+
182+
glog.Infof("cvmfs: successfuly unmounted volume %s from %s", volId, stagingTargetPath)
183+
184+
return &csi.NodeUnstageVolumeResponse{}, nil
147185
}
148186

149-
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
150-
return nil, status.Error(codes.Unimplemented, "")
187+
func (ns *nodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) {
188+
return &csi.NodeGetCapabilitiesResponse{
189+
Capabilities: []*csi.NodeServiceCapability{
190+
{
191+
Type: &csi.NodeServiceCapability_Rpc{
192+
Rpc: &csi.NodeServiceCapability_RPC{
193+
Type: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
194+
},
195+
},
196+
},
197+
},
198+
}, nil
151199
}

0 commit comments

Comments
 (0)