Skip to content

Commit fa3422f

Browse files
authored
Merge pull request #406 from davidz627/feature/getMetric
Add NodeGetVolumeStats Capability/Implementation/Tests
2 parents f55c957 + ead3152 commit fa3422f

File tree

14 files changed

+449
-702
lines changed

14 files changed

+449
-702
lines changed

cmd/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ func handle() {
7474

7575
mounter := mountmanager.NewSafeMounter()
7676
deviceUtils := mountmanager.NewDeviceUtils()
77-
77+
statter := mountmanager.NewStatter()
7878
ms, err := metadataservice.NewMetadataService()
7979
if err != nil {
8080
klog.Fatalf("Failed to set up metadata service: %v", err)
8181
}
8282

83-
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, deviceUtils, ms, driverName, vendorVersion)
83+
err = gceDriver.SetupGCEDriver(cloudProvider, mounter, deviceUtils, ms, statter, driverName, vendorVersion)
8484
if err != nil {
8585
klog.Fatalf("Failed to initialize GCE CSI Driver: %v", err)
8686
}

pkg/gce-pd-csi-driver/gce-pd-driver.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func GetGCEDriver() *GCEDriver {
4646
}
4747

4848
func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter *mount.SafeFormatAndMount,
49-
deviceUtils mountmanager.DeviceUtils, meta metadataservice.MetadataService, name, vendorVersion string) error {
49+
deviceUtils mountmanager.DeviceUtils, meta metadataservice.MetadataService, statter mountmanager.Statter, name, vendorVersion string) error {
5050
if name == "" {
5151
return fmt.Errorf("Driver name missing")
5252
}
@@ -72,12 +72,13 @@ func (gceDriver *GCEDriver) SetupGCEDriver(cloudProvider gce.GCECompute, mounter
7272
ns := []csi.NodeServiceCapability_RPC_Type{
7373
csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
7474
csi.NodeServiceCapability_RPC_EXPAND_VOLUME,
75+
csi.NodeServiceCapability_RPC_GET_VOLUME_STATS,
7576
}
7677
gceDriver.AddNodeServiceCapabilities(ns)
7778

7879
// Set up RPC Servers
7980
gceDriver.ids = NewIdentityServer(gceDriver)
80-
gceDriver.ns = NewNodeServer(gceDriver, mounter, deviceUtils, meta)
81+
gceDriver.ns = NewNodeServer(gceDriver, mounter, deviceUtils, meta, statter)
8182
gceDriver.cs = NewControllerServer(gceDriver, cloudProvider, meta)
8283

8384
return nil
@@ -133,13 +134,14 @@ func NewIdentityServer(gceDriver *GCEDriver) *GCEIdentityServer {
133134
}
134135
}
135136

136-
func NewNodeServer(gceDriver *GCEDriver, mounter *mount.SafeFormatAndMount, deviceUtils mountmanager.DeviceUtils, meta metadataservice.MetadataService) *GCENodeServer {
137+
func NewNodeServer(gceDriver *GCEDriver, mounter *mount.SafeFormatAndMount, deviceUtils mountmanager.DeviceUtils, meta metadataservice.MetadataService, statter mountmanager.Statter) *GCENodeServer {
137138
return &GCENodeServer{
138139
Driver: gceDriver,
139140
Mounter: mounter,
140141
DeviceUtils: deviceUtils,
141142
MetadataService: meta,
142143
volumeLocks: common.NewVolumeLocks(),
144+
VolumeStatter: statter,
143145
}
144146
}
145147

pkg/gce-pd-csi-driver/gce-pd-driver_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func initBlockingGCEDriver(t *testing.T, cloudDisks []*gce.CloudDisk, readyToExe
4444
func initGCEDriverWithCloudProvider(t *testing.T, cloudProvider gce.GCECompute) *GCEDriver {
4545
vendorVersion := "test-vendor"
4646
gceDriver := GetGCEDriver()
47-
err := gceDriver.SetupGCEDriver(cloudProvider, nil, nil, metadataservice.NewFakeService(), driver, vendorVersion)
47+
err := gceDriver.SetupGCEDriver(cloudProvider, nil, nil, metadataservice.NewFakeService(), nil, driver, vendorVersion)
4848
if err != nil {
4949
t.Fatalf("Failed to setup GCE Driver: %v", err)
5050
}

pkg/gce-pd-csi-driver/identity_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
func TestGetPluginInfo(t *testing.T) {
2727
vendorVersion := "test-vendor"
2828
gceDriver := GetGCEDriver()
29-
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), driver, vendorVersion)
29+
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), nil, driver, vendorVersion)
3030
if err != nil {
3131
t.Fatalf("Failed to setup GCE Driver: %v", err)
3232
}
@@ -48,7 +48,7 @@ func TestGetPluginInfo(t *testing.T) {
4848

4949
func TestGetPluginCapabilities(t *testing.T) {
5050
gceDriver := GetGCEDriver()
51-
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), driver, "test-vendor")
51+
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), nil, driver, "test-vendor")
5252
if err != nil {
5353
t.Fatalf("Failed to setup GCE Driver: %v", err)
5454
}
@@ -80,7 +80,7 @@ func TestGetPluginCapabilities(t *testing.T) {
8080

8181
func TestProbe(t *testing.T) {
8282
gceDriver := GetGCEDriver()
83-
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), driver, "test-vendor")
83+
err := gceDriver.SetupGCEDriver(nil, nil, nil, metadataservice.NewFakeService(), nil, driver, "test-vendor")
8484
if err != nil {
8585
t.Fatalf("Failed to setup GCE Driver: %v", err)
8686
}

pkg/gce-pd-csi-driver/node.go

+60-2
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ import (
2222

2323
"context"
2424

25-
csi "github.com/container-storage-interface/spec/lib/go/csi"
2625
"google.golang.org/grpc/codes"
2726
"google.golang.org/grpc/status"
27+
28+
csi "github.com/container-storage-interface/spec/lib/go/csi"
29+
2830
"k8s.io/klog"
2931
"k8s.io/kubernetes/pkg/util/mount"
3032
"k8s.io/kubernetes/pkg/util/resizefs"
33+
3134
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common"
3235
metadataservice "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/gce-cloud-provider/metadata"
3336
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
@@ -37,6 +40,7 @@ type GCENodeServer struct {
3740
Driver *GCEDriver
3841
Mounter *mount.SafeFormatAndMount
3942
DeviceUtils mountmanager.DeviceUtils
43+
VolumeStatter mountmanager.Statter
4044
MetadataService metadataservice.MetadataService
4145

4246
// A map storing all volumes with ongoing operations so that additional operations
@@ -360,7 +364,61 @@ func (ns *GCENodeServer) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoRe
360364
}
361365

362366
func (ns *GCENodeServer) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
363-
return nil, status.Error(codes.Unimplemented, fmt.Sprintf("NodeGetVolumeStats is not yet implemented"))
367+
if len(req.VolumeId) == 0 {
368+
return nil, status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume ID was empty")
369+
}
370+
if len(req.VolumePath) == 0 {
371+
return nil, status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume path was empty")
372+
}
373+
374+
exists, err := ns.Mounter.Interface.ExistsPath(req.VolumePath)
375+
if err != nil {
376+
return nil, status.Errorf(codes.Internal, "unknown error when stat on %s: %v", req.VolumePath, err)
377+
}
378+
if !exists {
379+
return nil, status.Errorf(codes.NotFound, "path %s does not exist", req.VolumePath)
380+
}
381+
382+
isBlock, err := ns.VolumeStatter.IsBlockDevice(req.VolumePath)
383+
if err != nil {
384+
return nil, status.Errorf(codes.Internal, "failed to determine whether %s is block device: %v", req.VolumePath, err)
385+
}
386+
if isBlock {
387+
bcap, err := ns.getBlockSizeBytes(req.VolumePath)
388+
if err != nil {
389+
return nil, status.Errorf(codes.Internal, "failed to get block capacity on path %s: %v", req.VolumePath, err)
390+
}
391+
return &csi.NodeGetVolumeStatsResponse{
392+
Usage: []*csi.VolumeUsage{
393+
{
394+
Unit: csi.VolumeUsage_BYTES,
395+
Total: bcap,
396+
},
397+
},
398+
}, nil
399+
}
400+
401+
available, capacity, used, inodesFree, inodes, inodesUsed, err := ns.VolumeStatter.StatFS(req.VolumePath)
402+
if err != nil {
403+
return nil, status.Errorf(codes.Internal, "failed to get fs info on path %s: %v", req.VolumePath, err)
404+
}
405+
406+
return &csi.NodeGetVolumeStatsResponse{
407+
Usage: []*csi.VolumeUsage{
408+
{
409+
Unit: csi.VolumeUsage_BYTES,
410+
Available: available,
411+
Total: capacity,
412+
Used: used,
413+
},
414+
{
415+
Unit: csi.VolumeUsage_INODES,
416+
Available: inodesFree,
417+
Total: inodes,
418+
Used: inodesUsed,
419+
},
420+
},
421+
}, nil
364422
}
365423

366424
func (ns *GCENodeServer) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) {

pkg/gce-pd-csi-driver/node_test.go

+65-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func getTestGCEDriverWithCustomMounter(t *testing.T, mounter *mount.SafeFormatAn
4444

4545
func getCustomTestGCEDriver(t *testing.T, mounter *mount.SafeFormatAndMount, deviceUtils mountmanager.DeviceUtils, metaService metadataservice.MetadataService) *GCEDriver {
4646
gceDriver := GetGCEDriver()
47-
err := gceDriver.SetupGCEDriver(nil, mounter, deviceUtils, metaService, driver, "test-vendor")
47+
err := gceDriver.SetupGCEDriver(nil, mounter, deviceUtils, metaService, mountmanager.NewFakeStatter(), driver, "test-vendor")
4848
if err != nil {
4949
t.Fatalf("Failed to setup GCE Driver: %v", err)
5050
}
@@ -53,13 +53,76 @@ func getCustomTestGCEDriver(t *testing.T, mounter *mount.SafeFormatAndMount, dev
5353

5454
func getTestBlockingGCEDriver(t *testing.T, readyToExecute chan chan struct{}) *GCEDriver {
5555
gceDriver := GetGCEDriver()
56-
err := gceDriver.SetupGCEDriver(nil, mountmanager.NewFakeSafeBlockingMounter(readyToExecute), mountmanager.NewFakeDeviceUtils(), metadataservice.NewFakeService(), driver, "test-vendor")
56+
err := gceDriver.SetupGCEDriver(nil, mountmanager.NewFakeSafeBlockingMounter(readyToExecute), mountmanager.NewFakeDeviceUtils(), metadataservice.NewFakeService(), nil, driver, "test-vendor")
5757
if err != nil {
5858
t.Fatalf("Failed to setup GCE Driver: %v", err)
5959
}
6060
return gceDriver
6161
}
6262

63+
func TestNodeGetVolumeStats(t *testing.T) {
64+
gceDriver := getTestGCEDriver(t)
65+
ns := gceDriver.ns
66+
67+
req := &csi.NodePublishVolumeRequest{
68+
VolumeId: defaultVolumeID,
69+
TargetPath: defaultTargetPath,
70+
StagingTargetPath: defaultStagingPath,
71+
Readonly: false,
72+
VolumeCapability: stdVolCap,
73+
}
74+
_, err := ns.NodePublishVolume(context.Background(), req)
75+
if err != nil {
76+
t.Fatalf("Failed to set up test by publishing default vol: %v", err)
77+
}
78+
79+
testCases := []struct {
80+
name string
81+
volumeID string
82+
volumePath string
83+
expectErr bool
84+
}{
85+
{
86+
name: "normal",
87+
volumeID: defaultVolumeID,
88+
volumePath: defaultTargetPath,
89+
},
90+
{
91+
name: "no vol id",
92+
volumePath: defaultTargetPath,
93+
expectErr: true,
94+
},
95+
{
96+
name: "no vol path",
97+
volumeID: defaultVolumeID,
98+
expectErr: true,
99+
},
100+
{
101+
name: "bad vol path",
102+
volumeID: defaultVolumeID,
103+
volumePath: "/mnt/fake",
104+
expectErr: true,
105+
},
106+
}
107+
108+
for _, tc := range testCases {
109+
t.Run(tc.name, func(t *testing.T) {
110+
111+
req := &csi.NodeGetVolumeStatsRequest{
112+
VolumeId: tc.volumeID,
113+
VolumePath: tc.volumePath,
114+
}
115+
_, err := ns.NodeGetVolumeStats(context.Background(), req)
116+
if err != nil && !tc.expectErr {
117+
t.Fatalf("Got unexpected err: %v", err)
118+
}
119+
if err == nil && tc.expectErr {
120+
t.Fatal("Did not get error but expected one")
121+
}
122+
})
123+
}
124+
}
125+
63126
func TestNodeGetVolumeLimits(t *testing.T) {
64127

65128
gceDriver := getTestGCEDriver(t)

0 commit comments

Comments
 (0)