@@ -22,12 +22,15 @@ import (
22
22
23
23
"context"
24
24
25
- csi "github.com/container-storage-interface/spec/lib/go/csi"
26
25
"google.golang.org/grpc/codes"
27
26
"google.golang.org/grpc/status"
27
+
28
+ csi "github.com/container-storage-interface/spec/lib/go/csi"
29
+
28
30
"k8s.io/klog"
29
31
"k8s.io/kubernetes/pkg/util/mount"
30
32
"k8s.io/kubernetes/pkg/util/resizefs"
33
+
31
34
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common"
32
35
metadataservice "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/gce-cloud-provider/metadata"
33
36
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
@@ -37,6 +40,7 @@ type GCENodeServer struct {
37
40
Driver * GCEDriver
38
41
Mounter * mount.SafeFormatAndMount
39
42
DeviceUtils mountmanager.DeviceUtils
43
+ VolumeStatter mountmanager.Statter
40
44
MetadataService metadataservice.MetadataService
41
45
42
46
// 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
360
364
}
361
365
362
366
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
364
422
}
365
423
366
424
func (ns * GCENodeServer ) NodeExpandVolume (ctx context.Context , req * csi.NodeExpandVolumeRequest ) (* csi.NodeExpandVolumeResponse , error ) {
0 commit comments