@@ -23,6 +23,7 @@ import (
23
23
v1 "k8s.io/api/core/v1"
24
24
storagev1 "k8s.io/api/storage/v1"
25
25
apierrors "k8s.io/apimachinery/pkg/api/errors"
26
+ "k8s.io/apimachinery/pkg/labels"
26
27
"k8s.io/apimachinery/pkg/runtime"
27
28
"k8s.io/apimachinery/pkg/util/rand"
28
29
corelisters "k8s.io/client-go/listers/core/v1"
@@ -60,6 +61,7 @@ type CSILimits struct {
60
61
pvLister corelisters.PersistentVolumeLister
61
62
pvcLister corelisters.PersistentVolumeClaimLister
62
63
scLister storagelisters.StorageClassLister
64
+ vaLister storagelisters.VolumeAttachmentLister
63
65
64
66
randomVolumeIDPrefix string
65
67
@@ -183,6 +185,7 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v
183
185
logger .V (5 ).Info ("Could not get a CSINode object for the node" , "node" , klog .KObj (node ), "err" , err )
184
186
}
185
187
188
+ // Count CSI volumes from the new pod
186
189
newVolumes := make (map [string ]string )
187
190
if err := pl .filterAttachableVolumes (logger , pod , csiNode , true /* new pod */ , newVolumes ); err != nil {
188
191
if apierrors .IsNotFound (err ) {
@@ -203,6 +206,7 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v
203
206
return nil
204
207
}
205
208
209
+ // Count CSI volumes from existing pods
206
210
attachedVolumes := make (map [string ]string )
207
211
for _ , existingPod := range nodeInfo .Pods {
208
212
if err := pl .filterAttachableVolumes (logger , existingPod .Pod , csiNode , false /* existing pod */ , attachedVolumes ); err != nil {
@@ -217,6 +221,19 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v
217
221
attachedVolumeCount [driverName ]++
218
222
}
219
223
224
+ // Count CSI volumes from VolumeAttachments
225
+ volumeAttachments , err := pl .getNodeVolumeAttachmentInfo (logger , node .Name )
226
+ if err != nil {
227
+ return framework .AsStatus (err )
228
+ }
229
+
230
+ for volumeUniqueName , driverName := range volumeAttachments {
231
+ // Avoid double-counting volumes already used by existing pods
232
+ if _ , exists := attachedVolumes [volumeUniqueName ]; ! exists {
233
+ attachedVolumeCount [driverName ]++
234
+ }
235
+ }
236
+
220
237
// Count the new volumes count per driver
221
238
newVolumeCount := map [string ]int {}
222
239
for _ , driverName := range newVolumes {
@@ -303,7 +320,7 @@ func (pl *CSILimits) filterAttachableVolumes(
303
320
continue
304
321
}
305
322
306
- volumeUniqueName := fmt . Sprintf ( "%s/%s" , driverName , volumeHandle )
323
+ volumeUniqueName := getVolumeUniqueName ( driverName , volumeHandle )
307
324
result [volumeUniqueName ] = driverName
308
325
}
309
326
return nil
@@ -344,7 +361,7 @@ func (pl *CSILimits) checkAttachableInlineVolume(logger klog.Logger, vol *v1.Vol
344
361
if translatedPV .Spec .PersistentVolumeSource .CSI == nil {
345
362
return nil
346
363
}
347
- volumeUniqueName := fmt . Sprintf ( "%s/%s" , driverName , translatedPV .Spec .PersistentVolumeSource .CSI .VolumeHandle )
364
+ volumeUniqueName := getVolumeUniqueName ( driverName , translatedPV .Spec .PersistentVolumeSource .CSI .VolumeHandle )
348
365
result [volumeUniqueName ] = driverName
349
366
return nil
350
367
}
@@ -453,13 +470,15 @@ func NewCSI(_ context.Context, _ runtime.Object, handle framework.Handle, fts fe
453
470
pvcLister := informerFactory .Core ().V1 ().PersistentVolumeClaims ().Lister ()
454
471
csiNodesLister := informerFactory .Storage ().V1 ().CSINodes ().Lister ()
455
472
scLister := informerFactory .Storage ().V1 ().StorageClasses ().Lister ()
473
+ vaLister := informerFactory .Storage ().V1 ().VolumeAttachments ().Lister ()
456
474
csiTranslator := csitrans .New ()
457
475
458
476
return & CSILimits {
459
477
csiNodeLister : csiNodesLister ,
460
478
pvLister : pvLister ,
461
479
pvcLister : pvcLister ,
462
480
scLister : scLister ,
481
+ vaLister : vaLister ,
463
482
randomVolumeIDPrefix : rand .String (32 ),
464
483
translator : csiTranslator ,
465
484
}, nil
@@ -480,3 +499,40 @@ func getVolumeLimits(csiNode *storagev1.CSINode) map[string]int64 {
480
499
}
481
500
return nodeVolumeLimits
482
501
}
502
+
503
+ // getNodeVolumeAttachmentInfo returns a map of volumeID to driver name for the given node.
504
+ func (pl * CSILimits ) getNodeVolumeAttachmentInfo (logger klog.Logger , nodeName string ) (map [string ]string , error ) {
505
+ volumeAttachments := make (map [string ]string )
506
+ vas , err := pl .vaLister .List (labels .Everything ())
507
+ if err != nil {
508
+ return nil , err
509
+ }
510
+ for _ , va := range vas {
511
+ if va .Spec .NodeName == nodeName {
512
+ if va .Spec .Attacher == "" {
513
+ logger .V (5 ).Info ("VolumeAttachment has no attacher" , "VolumeAttachment" , klog .KObj (va ))
514
+ continue
515
+ }
516
+ if va .Spec .Source .PersistentVolumeName == nil {
517
+ logger .V (5 ).Info ("VolumeAttachment has no PV name" , "VolumeAttachment" , klog .KObj (va ))
518
+ continue
519
+ }
520
+ pv , err := pl .pvLister .Get (* va .Spec .Source .PersistentVolumeName )
521
+ if err != nil {
522
+ logger .V (5 ).Info ("Unable to get PV for VolumeAttachment" , "VolumeAttachment" , klog .KObj (va ), "err" , err )
523
+ continue
524
+ }
525
+ if pv .Spec .CSI == nil {
526
+ logger .V (5 ).Info ("PV is not a CSI volume" , "PV" , klog .KObj (pv ))
527
+ continue
528
+ }
529
+ volumeID := getVolumeUniqueName (va .Spec .Attacher , pv .Spec .CSI .VolumeHandle )
530
+ volumeAttachments [volumeID ] = va .Spec .Attacher
531
+ }
532
+ }
533
+ return volumeAttachments , nil
534
+ }
535
+
536
+ func getVolumeUniqueName (driverName , volumeHandle string ) string {
537
+ return fmt .Sprintf ("%s/%s" , driverName , volumeHandle )
538
+ }
0 commit comments