@@ -30,6 +30,8 @@ import (
30
30
31
31
csi "github.com/container-storage-interface/spec/lib/go/csi"
32
32
33
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34
+ "k8s.io/client-go/kubernetes"
33
35
"k8s.io/klog/v2"
34
36
"k8s.io/mount-utils"
35
37
@@ -41,13 +43,13 @@ import (
41
43
)
42
44
43
45
type GCENodeServer struct {
44
- Driver * GCEDriver
45
- Mounter * mount.SafeFormatAndMount
46
- DeviceUtils deviceutils.DeviceUtils
47
- VolumeStatter mountmanager.Statter
48
- MetadataService metadataservice.MetadataService
49
- EnableDataCache bool
50
- DataCacheEnabledNodePool bool
46
+ Driver * GCEDriver
47
+ Mounter * mount.SafeFormatAndMount
48
+ DeviceUtils deviceutils.DeviceUtils
49
+ VolumeStatter mountmanager.Statter
50
+ MetadataService metadataservice.MetadataService
51
+
52
+ kubeClient * kubernetes. Clientset
51
53
52
54
// A map storing all volumes with ongoing operations so that additional operations
53
55
// for that same volume (as defined by VolumeID) return an Aborted error
@@ -80,10 +82,6 @@ type NodeServerArgs struct {
80
82
EnableDeviceInUseCheck bool
81
83
82
84
DeviceInUseTimeout time.Duration
83
-
84
- EnableDataCache bool
85
-
86
- DataCacheEnabledNodePool bool
87
85
}
88
86
89
87
var _ csi.NodeServer = & GCENodeServer {}
@@ -300,7 +298,6 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
300
298
volumeID := req .GetVolumeId ()
301
299
stagingTargetPath := req .GetStagingTargetPath ()
302
300
volumeCapability := req .GetVolumeCapability ()
303
- nodeId := ns .MetadataService .GetName ()
304
301
if len (volumeID ) == 0 {
305
302
return nil , status .Error (codes .InvalidArgument , "NodeStageVolume Volume ID must be provided" )
306
303
}
@@ -334,32 +331,12 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
334
331
partition = part
335
332
}
336
333
devicePath , err := getDevicePath (ns , volumeID , partition )
334
+
337
335
if err != nil {
338
336
return nil , status .Error (codes .Internal , fmt .Sprintf ("Error when getting device path: %v" , err .Error ()))
339
337
}
340
338
341
- klog .Infof ("Successfully found attached GCE PD %q at device path %s." , volumeKey .Name , devicePath )
342
-
343
- if ns .EnableDataCache && (req .GetPublishContext ()[common .ContextDataCacheSize ] != "" || req .GetPublishContext ()[common .ContextDataCacheMode ] != "" ) {
344
- if len (nodeId ) == 0 {
345
- return nil , status .Error (codes .InvalidArgument , "NodeStageVolume Node ID must be provided" )
346
- }
347
- devFsPath , err := filepath .EvalSymlinks (devicePath )
348
- if err != nil {
349
- klog .Errorf ("filepath.EvalSymlinks(%q) failed when trying to create volume group: %v" , devicePath , err )
350
- }
351
- configError := ValidateDataCacheConfig (req .GetPublishContext ()[common .ContextDataCacheMode ], req .GetPublishContext ()[common .ContextDataCacheSize ], ctx )
352
- if configError != nil {
353
- if ns .DataCacheEnabledNodePool {
354
- return nil , status .Error (codes .DataLoss , fmt .Sprintf ("Error validate configuration for Data Cache: %v" , configError .Error ()))
355
- }
356
- return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("The Data Cache PVC is scheduled on an incompatible node pool. Please select a node pool with data cache configured: %v" , configError .Error ()))
357
- }
358
- devicePath , err = setupCaching (devFsPath , req , nodeId )
359
- if err != nil {
360
- return nil , status .Error (codes .DataLoss , fmt .Sprintf ("Error setting up cache: %v" , err .Error ()))
361
- }
362
- }
339
+ klog .V (4 ).Infof ("Successfully found attached GCE PD %q at device path %s." , volumeKey .Name , devicePath )
363
340
364
341
// Part 2: Check if mount already exists at stagingTargetPath
365
342
if ns .isVolumePathMounted (stagingTargetPath ) {
@@ -513,15 +490,6 @@ func (ns *GCENodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUns
513
490
ns .deviceInUseErrors .deleteDevice (volumeID )
514
491
}
515
492
516
- // The NodeUnstageVolume does not have any volume or publish context, we need to get the info from LVM locally
517
- // Check if cache group cache-{volumeID} exist in LVM
518
- if ns .EnableDataCache {
519
- nodeId := ns .MetadataService .GetName ()
520
- err := cleanupCache (volumeID , nodeId )
521
- if err != nil {
522
- return nil , status .Errorf (codes .DataLoss , "Failed to cleanup cache for volume %s: %v" , volumeID , err )
523
- }
524
- }
525
493
klog .V (4 ).Infof ("NodeUnstageVolume succeeded on %v from %s" , volumeID , stagingTargetPath )
526
494
return & csi.NodeUnstageVolumeResponse {}, nil
527
495
}
@@ -556,22 +524,60 @@ func (ns *GCENodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeG
556
524
}
557
525
558
526
func (ns * GCENodeServer ) NodeGetInfo (ctx context.Context , req * csi.NodeGetInfoRequest ) (* csi.NodeGetInfoResponse , error ) {
527
+ labels , err := ns .gkeTopologyLabels (ctx , ns .MetadataService .GetName ())
528
+ if err != nil {
529
+ // Perhaps we don't want to fail here. We are introducing a new
530
+ // dependency and we might be better off allowing this failure to
531
+ // happen and moving on to retrieve the zone from GCE MDS.
532
+ return nil , err
533
+ }
534
+
535
+ labels [common .TopologyKeyZone ] = ns .MetadataService .GetZone ()
536
+
537
+ // Each "Topology" struct will later be translated into an individual
538
+ // 'matchExpressions' block in the PV's NodeAffinity. Because we always
539
+ // need to match on both the zone AND the disk type, both the zone and the
540
+ // supported disks belong as segments on a single Topology.
559
541
top := & csi.Topology {
560
- Segments : map [ string ] string { common . TopologyKeyZone : ns . MetadataService . GetZone ()} ,
542
+ Segments : labels ,
561
543
}
562
544
563
545
nodeID := common .CreateNodeID (ns .MetadataService .GetProject (), ns .MetadataService .GetZone (), ns .MetadataService .GetName ())
564
-
565
546
volumeLimits , err := ns .GetVolumeLimits ()
566
547
567
548
resp := & csi.NodeGetInfoResponse {
568
549
NodeId : nodeID ,
569
550
MaxVolumesPerNode : volumeLimits ,
570
551
AccessibleTopology : top ,
571
552
}
553
+
554
+ klog .V (2 ).Infof ("Returning NodeGetInfoResponse: %+v" , resp )
555
+
572
556
return resp , err
573
557
}
574
558
559
+ // gkeTopologyLabels retrieves the node labels with the prefix
560
+ // `topology.gke.io/`.
561
+ func (ns * GCENodeServer ) gkeTopologyLabels (ctx context.Context , nodeName string ) (map [string ]string , error ) {
562
+ klog .V (2 ).Infof ("Retrieving node topology labels for node %q" , nodeName )
563
+
564
+ node , err := ns .kubeClient .CoreV1 ().Nodes ().Get (ctx , nodeName , metav1.GetOptions {})
565
+ if err != nil {
566
+ // We should retry instead. Need to figure out how much wrong-ness can be tolerated and how often CSINode gets refreshed.
567
+ return nil , err
568
+ }
569
+
570
+ topology := make (map [string ]string )
571
+ for k , v := range node .GetLabels () {
572
+ if common .IsGKETopologyLabel (k ) {
573
+ klog .V (2 ).Infof ("Including node topology label %q=%q" , k , v )
574
+ topology [k ] = v
575
+ }
576
+ }
577
+
578
+ return topology , nil
579
+ }
580
+
575
581
func (ns * GCENodeServer ) NodeGetVolumeStats (ctx context.Context , req * csi.NodeGetVolumeStatsRequest ) (* csi.NodeGetVolumeStatsResponse , error ) {
576
582
if len (req .VolumeId ) == 0 {
577
583
return nil , status .Error (codes .InvalidArgument , "NodeGetVolumeStats volume ID was empty" )
0 commit comments