@@ -18,8 +18,8 @@ package cinder
18
18
19
19
import (
20
20
"context"
21
- "encoding/json"
22
21
"fmt"
22
+ "slices"
23
23
"sort"
24
24
"strconv"
25
25
@@ -126,7 +126,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
126
126
127
127
// Volume Create
128
128
properties := map [string ]string {cinderCSIClusterIDKey : cs .Driver .clusterID }
129
- //Tag volume with metadata if present: https://github.com/kubernetes-csi/external-provisioner/pull/399
129
+ // Tag volume with metadata if present: https://github.com/kubernetes-csi/external-provisioner/pull/399
130
130
for _ , mKey := range sharedcsi .RecognizedCSIProvisionerParams {
131
131
if v , ok := req .Parameters [mKey ]; ok {
132
132
properties [mKey ] = v
@@ -161,7 +161,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
161
161
var back * backups.Backup
162
162
back , err = cloud .GetBackupByID (ctx , snapshotID )
163
163
if err != nil {
164
- //If there is an error getting the backup as well, fail.
164
+ // If there is an error getting the backup as well, fail.
165
165
return nil , status .Errorf (codes .NotFound , "VolumeContentSource Snapshot or Backup with ID %s not found" , snapshotID )
166
166
}
167
167
if back .Status != "available" {
@@ -402,12 +402,6 @@ func (cs *controllerServer) ControllerUnpublishVolume(ctx context.Context, req *
402
402
return & csi.ControllerUnpublishVolumeResponse {}, nil
403
403
}
404
404
405
- type CloudsStartingToken struct {
406
- CloudName string `json:"cloud"`
407
- Token string `json:"token"`
408
- isEmpty bool
409
- }
410
-
411
405
func (cs * controllerServer ) extractNodeIDs (attachments []volumes.Attachment ) []string {
412
406
nodeIDs := make ([]string , len (attachments ))
413
407
for i , attachment := range attachments {
@@ -439,123 +433,56 @@ func (cs *controllerServer) ListVolumes(ctx context.Context, req *csi.ListVolume
439
433
return nil , status .Errorf (codes .InvalidArgument , "[ListVolumes] Invalid max entries request %v, must not be negative " , req .MaxEntries )
440
434
}
441
435
maxEntries := int (req .MaxEntries )
442
-
443
436
var err error
444
- var cloudsToken = CloudsStartingToken {
445
- CloudName : "" ,
446
- Token : "" ,
447
- isEmpty : len (req .StartingToken ) == 0 ,
448
- }
449
437
450
438
cloudsNames := maps .Keys (cs .Clouds )
451
439
sort .Strings (cloudsNames )
452
440
453
- currentCloudName := cloudsNames [0 ]
441
+ var (
442
+ token string
443
+ idx int
444
+ cloudName = cloudsNames [0 ]
445
+ )
454
446
if req .StartingToken != "" {
455
- err = json .Unmarshal ([]byte (req .StartingToken ), & cloudsToken )
456
- if err != nil {
457
- return nil , status .Errorf (codes .Aborted , "[ListVolumes] Invalid request: Token invalid" )
458
- }
459
- currentCloudName = cloudsToken .CloudName
460
- }
461
-
462
- startingToken := cloudsToken .Token
463
- var cloudsVentries []* csi.ListVolumesResponse_Entry
464
- var vlist []volumes.Volume
465
- var nextPageToken string
466
-
467
- if ! cloudsToken .isEmpty && startingToken == "" {
468
- // previous call ended on last volumes from "currentCloudName" we should pass to next one
469
- for i := range cloudsNames {
470
- if cloudsNames [i ] == currentCloudName {
471
- currentCloudName = cloudsNames [i + 1 ]
472
- break
473
- }
447
+ token , cloudName = splitToken (req .StartingToken )
448
+ idx = slices .Index (cloudsNames , cloudName )
449
+ if idx < 0 {
450
+ return nil , status .Errorf (codes .Internal , "[ListVolumes] Invalid request: %s" , fmt .Errorf ("unknown cloud specified in the request: %v" , cloudName ))
474
451
}
475
452
}
476
453
477
- startIdx := 0
478
- for _ , cloudName := range cloudsNames {
479
- if cloudName == currentCloudName {
480
- break
481
- }
482
- startIdx ++
483
- }
484
- for idx := startIdx ; idx < len (cloudsNames ); idx ++ {
485
- if maxEntries > 0 {
486
- vlist , nextPageToken , err = cs.Clouds [cloudsNames [idx ]].ListVolumes (ctx , maxEntries - len (cloudsVentries ), startingToken )
487
- } else {
488
- vlist , nextPageToken , err = cs.Clouds [cloudsNames [idx ]].ListVolumes (ctx , maxEntries , startingToken )
489
- }
490
- startingToken = nextPageToken
491
- if err != nil {
492
- klog .Errorf ("Failed to ListVolumes: %v" , err )
493
- if cpoerrors .IsInvalidError (err ) {
494
- return nil , status .Errorf (codes .Aborted , "[ListVolumes] Invalid request: %v" , err )
495
- }
496
- return nil , status .Errorf (codes .Internal , "ListVolumes failed with error %v" , err )
497
- }
498
-
499
- ventries := cs .createVolumeEntries (vlist )
500
- klog .V (4 ).Infof ("ListVolumes: retrieved %d entries and %q next token from cloud %q" , len (ventries ), nextPageToken , cloudsNames [idx ])
501
-
502
- cloudsVentries = append (cloudsVentries , ventries ... )
503
-
504
- // Reach maxEntries setup nextToken with cloud identifier if needed
505
- sendEmptyToken := false
506
- if maxEntries > 0 && len (cloudsVentries ) == maxEntries {
507
- if nextPageToken == "" {
508
- if idx + 1 == len (cloudsNames ) {
509
- // no more entries and no more clouds
510
- // send no token its finished
511
- klog .V (4 ).Infof ("ListVolumes: completed with %d entries and %q next token" , len (cloudsVentries ), "" )
512
- return & csi.ListVolumesResponse {
513
- Entries : cloudsVentries ,
514
- NextToken : "" ,
515
- }, nil
516
- } else {
517
- // still clouds to process
518
- // set token to next non empty cloud
519
- i := 0
520
- for i = idx + 1 ; i < len (cloudsNames ); i ++ {
521
- vlistTmp , _ , err := cs.Clouds [cloudsNames [i ]].ListVolumes (ctx , 1 , "" )
522
- if err != nil {
523
- klog .Errorf ("Failed to ListVolumes: %v" , err )
524
- if cpoerrors .IsInvalidError (err ) {
525
- return nil , status .Errorf (codes .Aborted , "[ListVolumes] Invalid request: %v" , err )
526
- }
527
- return nil , status .Errorf (codes .Internal , "ListVolumes failed with error %v" , err )
528
- }
529
- if len (vlistTmp ) > 0 {
530
- cloudsToken .CloudName = cloudsNames [i ]
531
- cloudsToken .isEmpty = false
532
- break
533
- }
534
- }
535
- if i == len (cloudsNames ) {
536
- sendEmptyToken = true
537
- }
538
- }
539
- }
540
- cloudsToken .CloudName = cloudsNames [idx ]
541
- cloudsToken .Token = nextPageToken
542
- var data []byte
543
- data , _ = json .Marshal (cloudsToken )
544
- if sendEmptyToken {
545
- data = []byte ("" )
546
- }
547
- klog .V (4 ).Infof ("ListVolumes: completed with %d entries and %q next token" , len (cloudsVentries ), string (data ))
548
- return & csi.ListVolumesResponse {
549
- Entries : cloudsVentries ,
550
- NextToken : string (data ),
551
- }, nil
454
+ var volumeList []volumes.Volume
455
+ volumeList , token , err = cs .Clouds [cloudName ].ListVolumes (ctx , maxEntries , token )
456
+ if err != nil {
457
+ klog .Errorf ("Failed to ListVolumes: %v" , err )
458
+ if cpoerrors .IsInvalidError (err ) {
459
+ return nil , status .Errorf (codes .Aborted , "[ListVolumes] Invalid request: %v" , err )
552
460
}
461
+ return nil , status .Errorf (codes .Internal , "ListVolumes failed with error %v" , err )
462
+ }
463
+ volumeEntries := cs .createVolumeEntries (volumeList )
464
+ klog .V (4 ).Infof ("ListVolumes: retrieved %d entries and %q next token from cloud %q" , len (volumeEntries ), token , cloudName )
465
+
466
+ switch {
467
+ // if we have not finished listing all volumes from this cloud, we will continue on next call.
468
+ case token != "" :
469
+ // if we listed all volumes from this cloud but more clouds exist, return a token of the next cloud.
470
+ case idx + 1 < len (cloudsNames ):
471
+ cloudName = cloudsNames [idx + 1 ]
472
+ default :
473
+ // work is done.
474
+ klog .V (4 ).Infof ("ListVolumes: completed with %d entries and %q next token" , len (volumeEntries ), "" )
475
+ return & csi.ListVolumesResponse {
476
+ Entries : volumeEntries ,
477
+ NextToken : "" ,
478
+ }, nil
553
479
}
554
480
555
- klog .V (4 ).Infof ("ListVolumes: completed with %d entries and %q next token" , len (cloudsVentries ), "" )
481
+ nextToken := joinToken (token , cloudName )
482
+ klog .V (4 ).Infof ("ListVolumes: completed with %d entries and %q next token" , len (volumeEntries ), nextToken )
556
483
return & csi.ListVolumesResponse {
557
- Entries : cloudsVentries ,
558
- NextToken : "" ,
484
+ Entries : volumeEntries ,
485
+ NextToken : nextToken ,
559
486
}, nil
560
487
}
561
488
0 commit comments