@@ -42,6 +42,10 @@ type GCEControllerServer struct {
42
42
Driver * GCEDriver
43
43
CloudProvider gce.GCECompute
44
44
MetadataService metadataservice.MetadataService
45
+
46
+ // A map storing all volumes with ongoing operations so that additional operations
47
+ // for that same volume (as defined by Volume Key) return an Aborted error
48
+ volumeLocks * common.VolumeLocks
45
49
}
46
50
47
51
var _ csi.ControllerServer = & GCEControllerServer {}
@@ -139,6 +143,15 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
139
143
return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("CreateVolume replication type '%s' is not supported" , replicationType ))
140
144
}
141
145
146
+ volumeID , err := common .KeyToVolumeID (volKey , gceCS .MetadataService .GetProject ())
147
+ if err != nil {
148
+ return nil , status .Errorf (codes .Internal , "Failed to convert volume key to volume ID: %v" , err )
149
+ }
150
+ if acquired := gceCS .volumeLocks .TryAcquire (volumeID ); ! acquired {
151
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , volumeID )
152
+ }
153
+ defer gceCS .volumeLocks .Release (volumeID )
154
+
142
155
// Validate if disk already exists
143
156
existingDisk , err := gceCS .CloudProvider .GetDisk (ctx , volKey )
144
157
if err != nil {
@@ -222,6 +235,11 @@ func (gceCS *GCEControllerServer) DeleteVolume(ctx context.Context, req *csi.Del
222
235
return nil , status .Error (codes .NotFound , fmt .Sprintf ("Could not find volume with ID %v: %v" , volumeID , err ))
223
236
}
224
237
238
+ if acquired := gceCS .volumeLocks .TryAcquire (volumeID ); ! acquired {
239
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , volumeID )
240
+ }
241
+ defer gceCS .volumeLocks .Release (volumeID )
242
+
225
243
err = gceCS .CloudProvider .DeleteDisk (ctx , volKey )
226
244
if err != nil {
227
245
return nil , status .Error (codes .Internal , fmt .Sprintf ("unknown Delete disk error: %v" , err ))
@@ -258,6 +276,14 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
258
276
return nil , status .Error (codes .NotFound , fmt .Sprintf ("Could not find volume with ID %v: %v" , volumeID , err ))
259
277
}
260
278
279
+ // Acquires the lock for the volume on that node only, because we need to support the ability
280
+ // to publish the same volume onto different nodes concurrently
281
+ lockingVolumeID := fmt .Sprintf ("%s/%s" , nodeID , volumeID )
282
+ if acquired := gceCS .volumeLocks .TryAcquire (lockingVolumeID ); ! acquired {
283
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , lockingVolumeID )
284
+ }
285
+ defer gceCS .volumeLocks .Release (lockingVolumeID )
286
+
261
287
// TODO(#253): Check volume capability matches for ALREADY_EXISTS
262
288
if err = validateVolumeCapability (volumeCapability ); err != nil {
263
289
return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("VolumeCapabilities is invalid: %v" , err ))
@@ -343,6 +369,14 @@ func (gceCS *GCEControllerServer) ControllerUnpublishVolume(ctx context.Context,
343
369
return nil , err
344
370
}
345
371
372
+ // Acquires the lock for the volume on that node only, because we need to support the ability
373
+ // to unpublish the same volume from different nodes concurrently
374
+ lockingVolumeID := fmt .Sprintf ("%s/%s" , nodeID , volumeID )
375
+ if acquired := gceCS .volumeLocks .TryAcquire (lockingVolumeID ); ! acquired {
376
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , lockingVolumeID )
377
+ }
378
+ defer gceCS .volumeLocks .Release (lockingVolumeID )
379
+
346
380
instanceZone , instanceName , err := common .NodeIDToZoneAndName (nodeID )
347
381
if err != nil {
348
382
return nil , status .Error (codes .InvalidArgument , fmt .Sprintf ("could not split nodeID: %v" , err ))
@@ -389,6 +423,12 @@ func (gceCS *GCEControllerServer) ValidateVolumeCapabilities(ctx context.Context
389
423
if err != nil {
390
424
return nil , status .Error (codes .NotFound , fmt .Sprintf ("Volume ID is of improper format, got %v" , volumeID ))
391
425
}
426
+
427
+ if acquired := gceCS .volumeLocks .TryAcquire (volumeID ); ! acquired {
428
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , volumeID )
429
+ }
430
+ defer gceCS .volumeLocks .Release (volumeID )
431
+
392
432
_ , err = gceCS .CloudProvider .GetDisk (ctx , volKey )
393
433
if err != nil {
394
434
if gce .IsGCEError (err , "notFound" ) {
@@ -496,6 +536,11 @@ func (gceCS *GCEControllerServer) CreateSnapshot(ctx context.Context, req *csi.C
496
536
return nil , status .Error (codes .NotFound , fmt .Sprintf ("Could not find volume with ID %v: %v" , volumeID , err ))
497
537
}
498
538
539
+ if acquired := gceCS .volumeLocks .TryAcquire (volumeID ); ! acquired {
540
+ return nil , status .Errorf (codes .Aborted , common .VolumeOperationAlreadyExistsFmt , volumeID )
541
+ }
542
+ defer gceCS .volumeLocks .Release (volumeID )
543
+
499
544
// Check if snapshot already exists
500
545
var snapshot * compute.Snapshot
501
546
snapshot , err = gceCS .CloudProvider .GetSnapshot (ctx , req .Name )
0 commit comments