diff --git a/pkg/nfs/nfs.go b/pkg/nfs/nfs.go index 521d748e..4da4faf6 100644 --- a/pkg/nfs/nfs.go +++ b/pkg/nfs/nfs.go @@ -37,6 +37,7 @@ type Driver struct { ns *NodeServer cap map[csi.VolumeCapability_AccessMode_Mode]bool cscap []*csi.ControllerServiceCapability + nscap []*csi.NodeServiceCapability } const ( @@ -81,6 +82,11 @@ func NewNFSdriver(nodeID, endpoint string, perm *uint32) *Driver { n.AddControllerServiceCapabilities([]csi.ControllerServiceCapability_RPC_Type{ csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME, }) + + n.AddNodeServiceCapabilities([]csi.NodeServiceCapability_RPC_Type{ + csi.NodeServiceCapability_RPC_GET_VOLUME_STATS, + csi.NodeServiceCapability_RPC_UNKNOWN, + }) return n } @@ -125,6 +131,15 @@ func (n *Driver) AddControllerServiceCapabilities(cl []csi.ControllerServiceCapa n.cscap = csc } +func (n *Driver) AddNodeServiceCapabilities(nl []csi.NodeServiceCapability_RPC_Type) { + var nsc []*csi.NodeServiceCapability + for _, n := range nl { + glog.Infof("Enabling node service capability: %v", n.String()) + nsc = append(nsc, NewNodeServiceCapability(n)) + } + n.nscap = nsc +} + func IsCorruptedDir(dir string) bool { _, pathErr := mount.PathExists(dir) fmt.Printf("IsCorruptedDir(%s) returned with error: %v", dir, pathErr) diff --git a/pkg/nfs/nfs_test.go b/pkg/nfs/nfs_test.go index 243724d0..db0d0338 100644 --- a/pkg/nfs/nfs_test.go +++ b/pkg/nfs/nfs_test.go @@ -134,3 +134,54 @@ func TestRun(t *testing.T) { t.Run(tc.name, tc.testFunc) } } + +func TestNewControllerServiceCapability(t *testing.T) { + tests := []struct { + cap csi.ControllerServiceCapability_RPC_Type + }{ + { + cap: csi.ControllerServiceCapability_RPC_UNKNOWN, + }, + { + cap: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME, + }, + { + cap: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + }, + { + cap: csi.ControllerServiceCapability_RPC_LIST_VOLUMES, + }, + { + cap: csi.ControllerServiceCapability_RPC_GET_CAPACITY, + }, + } + for _, test := range tests { + resp := NewControllerServiceCapability(test.cap) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + } +} + +func TestNewNodeServiceCapability(t *testing.T) { + tests := []struct { + cap csi.NodeServiceCapability_RPC_Type + }{ + { + cap: csi.NodeServiceCapability_RPC_UNKNOWN, + }, + { + cap: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME, + }, + { + cap: csi.NodeServiceCapability_RPC_GET_VOLUME_STATS, + }, + { + cap: csi.NodeServiceCapability_RPC_EXPAND_VOLUME, + }, + } + for _, test := range tests { + resp := NewNodeServiceCapability(test.cap) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + } +} diff --git a/pkg/nfs/nodeserver.go b/pkg/nfs/nodeserver.go index 9e192351..837a5eb7 100644 --- a/pkg/nfs/nodeserver.go +++ b/pkg/nfs/nodeserver.go @@ -136,15 +136,7 @@ func (ns *NodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoReque // NodeGetCapabilities return the capabilities of the Node plugin func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { return &csi.NodeGetCapabilitiesResponse{ - Capabilities: []*csi.NodeServiceCapability{ - { - Type: &csi.NodeServiceCapability_Rpc{ - Rpc: &csi.NodeServiceCapability_RPC{ - Type: csi.NodeServiceCapability_RPC_UNKNOWN, - }, - }, - }, - }, + Capabilities: ns.Driver.nscap, }, nil } diff --git a/pkg/nfs/nodeserver_test.go b/pkg/nfs/nodeserver_test.go index 7a31c957..6a0cb633 100644 --- a/pkg/nfs/nodeserver_test.go +++ b/pkg/nfs/nodeserver_test.go @@ -30,6 +30,10 @@ import ( "google.golang.org/grpc/status" ) +const ( + targetTest = "./target_test" +) + func TestNodePublishVolume(t *testing.T) { volumeCap := csi.VolumeCapability_AccessMode{Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER} alreadyMountedTarget := testutil.GetWorkDirPath("false_is_likely_exist_target", t) @@ -166,7 +170,6 @@ func TestNodeUnpublishVolume(t *testing.T) { } func TestNodeGetInfo(t *testing.T) { - ns, err := getTestNodeServer() if err != nil { t.Fatalf(err.Error()) @@ -180,7 +183,6 @@ func TestNodeGetInfo(t *testing.T) { } func TestNodeGetCapabilities(t *testing.T) { - ns, err := getTestNodeServer() if err != nil { t.Fatalf(err.Error()) @@ -192,6 +194,11 @@ func TestNodeGetCapabilities(t *testing.T) { }, } + capList := []*csi.NodeServiceCapability{{ + Type: capType, + }} + ns.Driver.nscap = capList + // Test valid request req := csi.NodeGetCapabilitiesRequest{} resp, err := ns.NodeGetCapabilities(context.Background(), &req) @@ -211,3 +218,53 @@ func getTestNodeServer() (NodeServer, error) { mounter: mounter, }, nil } + +func TestNodeGetVolumeStats(t *testing.T) { + nonexistedPath := "/not/a/real/directory" + fakePath := "/tmp/fake-volume-path" + + tests := []struct { + desc string + req csi.NodeGetVolumeStatsRequest + expectedErr error + }{ + { + desc: "[Error] Volume ID missing", + req: csi.NodeGetVolumeStatsRequest{VolumePath: targetTest}, + expectedErr: status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume ID was empty"), + }, + { + desc: "[Error] VolumePath missing", + req: csi.NodeGetVolumeStatsRequest{VolumeId: "vol_1"}, + expectedErr: status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume path was empty"), + }, + { + desc: "[Error] Incorrect volume path", + req: csi.NodeGetVolumeStatsRequest{VolumePath: nonexistedPath, VolumeId: "vol_1"}, + expectedErr: status.Errorf(codes.NotFound, "path /not/a/real/directory does not exist"), + }, + { + desc: "[Success] Standard success", + req: csi.NodeGetVolumeStatsRequest{VolumePath: fakePath, VolumeId: "vol_1"}, + expectedErr: nil, + }, + } + + // Setup + _ = makeDir(fakePath) + ns, err := getTestNodeServer() + if err != nil { + t.Fatalf(err.Error()) + } + + for _, test := range tests { + _, err := ns.NodeGetVolumeStats(context.Background(), &test.req) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Errorf("desc: %v, expected error: %v, actual error: %v", test.desc, test.expectedErr, err) + } + } + + // Clean up + err = os.RemoveAll(fakePath) + assert.NoError(t, err) +} diff --git a/pkg/nfs/utils.go b/pkg/nfs/utils.go index 6a35fb2f..b5356697 100644 --- a/pkg/nfs/utils.go +++ b/pkg/nfs/utils.go @@ -49,6 +49,16 @@ func NewControllerServiceCapability(cap csi.ControllerServiceCapability_RPC_Type } } +func NewNodeServiceCapability(cap csi.NodeServiceCapability_RPC_Type) *csi.NodeServiceCapability { + return &csi.NodeServiceCapability{ + Type: &csi.NodeServiceCapability_Rpc{ + Rpc: &csi.NodeServiceCapability_RPC{ + Type: cap, + }, + }, + } +} + func ParseEndpoint(ep string) (string, string, error) { if strings.HasPrefix(strings.ToLower(ep), "unix://") || strings.HasPrefix(strings.ToLower(ep), "tcp://") { s := strings.SplitN(ep, "://", 2) diff --git a/test/integration/run-test.sh b/test/integration/run-test.sh index 07ec4eb6..5dd6bfb6 100755 --- a/test/integration/run-test.sh +++ b/test/integration/run-test.sh @@ -70,6 +70,10 @@ echo "publish volume test:" "$CSC_BIN" node publish --endpoint "$endpoint" --cap "$cap" --vol-context "$params" --target-path "$target_path" "$volumeid" sleep 2 +echo "node stats test:" +csc node stats --endpoint "$endpoint" "$volumeid:$target_path:$staging_target_path" +sleep 2 + echo "unpublish volume test:" "$CSC_BIN" node unpublish --endpoint "$endpoint" --target-path "$target_path" "$volumeid" sleep 2