@@ -111,6 +111,11 @@ type locationRequirements struct {
111
111
cloneReplicationType string
112
112
}
113
113
114
+ // PDCSIContext is the extracted VolumeContext from controller requests.
115
+ type PDCSIContext struct {
116
+ ForceAttach bool
117
+ }
118
+
114
119
var _ csi.ControllerServer = & GCEControllerServer {}
115
120
116
121
const (
@@ -309,7 +314,7 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
309
314
310
315
// If there is no validation error, immediately return success
311
316
klog .V (4 ).Infof ("CreateVolume succeeded for disk %v, it already exists and was compatible" , volKey )
312
- return generateCreateVolumeResponse (existingDisk , zones ), nil
317
+ return generateCreateVolumeResponse (existingDisk , zones , params ), nil
313
318
}
314
319
315
320
snapshotID := ""
@@ -424,7 +429,7 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
424
429
}
425
430
426
431
klog .V (4 ).Infof ("CreateVolume succeeded for disk %v" , volKey )
427
- return generateCreateVolumeResponse (disk , zones ), nil
432
+ return generateCreateVolumeResponse (disk , zones , params ), nil
428
433
429
434
}
430
435
@@ -483,7 +488,7 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
483
488
}
484
489
}()
485
490
// Only valid requests will be accepted
486
- _ , _ , err = gceCS .validateControllerPublishVolumeRequest (ctx , req )
491
+ _ , _ , _ , err = gceCS .validateControllerPublishVolumeRequest (ctx , req )
487
492
if err != nil {
488
493
return nil , err
489
494
}
@@ -504,32 +509,37 @@ func (gceCS *GCEControllerServer) ControllerPublishVolume(ctx context.Context, r
504
509
return resp , err
505
510
}
506
511
507
- func (gceCS * GCEControllerServer ) validateControllerPublishVolumeRequest (ctx context.Context , req * csi.ControllerPublishVolumeRequest ) (string , * meta.Key , error ) {
512
+ func (gceCS * GCEControllerServer ) validateControllerPublishVolumeRequest (ctx context.Context , req * csi.ControllerPublishVolumeRequest ) (string , * meta.Key , * PDCSIContext , error ) {
508
513
// Validate arguments
509
514
volumeID := req .GetVolumeId ()
510
515
nodeID := req .GetNodeId ()
511
516
volumeCapability := req .GetVolumeCapability ()
512
517
if len (volumeID ) == 0 {
513
- return "" , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Volume ID must be provided" )
518
+ return "" , nil , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Volume ID must be provided" )
514
519
}
515
520
if len (nodeID ) == 0 {
516
- return "" , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Node ID must be provided" )
521
+ return "" , nil , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Node ID must be provided" )
517
522
}
518
523
if volumeCapability == nil {
519
- return "" , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Volume capability must be provided" )
524
+ return "" , nil , nil , status .Error (codes .InvalidArgument , "ControllerPublishVolume Volume capability must be provided" )
520
525
}
521
526
522
527
project , volKey , err := common .VolumeIDToKey (volumeID )
523
528
if err != nil {
524
- return "" , nil , status .Errorf (codes .InvalidArgument , "ControllerPublishVolume volume ID is invalid: %v" , err .Error ())
529
+ return "" , nil , nil , status .Errorf (codes .InvalidArgument , "ControllerPublishVolume volume ID is invalid: %v" , err .Error ())
525
530
}
526
531
527
532
// TODO(#253): Check volume capability matches for ALREADY_EXISTS
528
533
if err = validateVolumeCapability (volumeCapability ); err != nil {
529
- return "" , nil , status .Errorf (codes .InvalidArgument , "VolumeCapabilities is invalid: %v" , err .Error ())
534
+ return "" , nil , nil , status .Errorf (codes .InvalidArgument , "VolumeCapabilities is invalid: %v" , err .Error ())
530
535
}
531
536
532
- return project , volKey , nil
537
+ var pdcsiContext * PDCSIContext
538
+ if pdcsiContext , err = extractVolumeContext (req .VolumeContext ); err != nil {
539
+ return "" , nil , nil , status .Errorf (codes .InvalidArgument , "Invalid volume context: %v" , err .Error ())
540
+ }
541
+
542
+ return project , volKey , pdcsiContext , nil
533
543
}
534
544
535
545
func parseMachineType (machineTypeUrl string ) string {
@@ -543,7 +553,7 @@ func parseMachineType(machineTypeUrl string) string {
543
553
544
554
func (gceCS * GCEControllerServer ) executeControllerPublishVolume (ctx context.Context , req * csi.ControllerPublishVolumeRequest ) (* csi.ControllerPublishVolumeResponse , error , string ) {
545
555
diskType := ""
546
- project , volKey , err := gceCS .validateControllerPublishVolumeRequest (ctx , req )
556
+ project , volKey , pdcsiContext , err := gceCS .validateControllerPublishVolumeRequest (ctx , req )
547
557
if err != nil {
548
558
return nil , err , diskType
549
559
}
@@ -615,7 +625,7 @@ func (gceCS *GCEControllerServer) executeControllerPublishVolume(ctx context.Con
615
625
if err != nil {
616
626
return nil , status .Errorf (codes .InvalidArgument , "could not split nodeID: %v" , err .Error ()), diskType
617
627
}
618
- err = gceCS .CloudProvider .AttachDisk (ctx , project , volKey , readWrite , attachableDiskTypePersistent , instanceZone , instanceName )
628
+ err = gceCS .CloudProvider .AttachDisk (ctx , project , volKey , readWrite , attachableDiskTypePersistent , instanceZone , instanceName , pdcsiContext . ForceAttach )
619
629
if err != nil {
620
630
var udErr * gce.UnsupportedDiskError
621
631
if errors .As (err , & udErr ) {
@@ -788,11 +798,6 @@ func (gceCS *GCEControllerServer) ValidateVolumeCapabilities(ctx context.Context
788
798
return nil , common .LoggedError ("Failed to getDisk: " , err )
789
799
}
790
800
791
- // Check Volume Context is Empty
792
- if len (req .GetVolumeContext ()) != 0 {
793
- return generateFailedValidationMessage ("VolumeContext expected to be empty but got %v" , req .GetVolumeContext ()), nil
794
- }
795
-
796
801
// Check volume capabilities supported by PD. These are the same for any PD
797
802
if err := validateVolumeCapabilities (req .GetVolumeCapabilities ()); err != nil {
798
803
return generateFailedValidationMessage ("VolumeCapabilities not valid: %v" , err .Error ()), nil
@@ -1667,7 +1672,35 @@ func getDefaultZonesInRegion(ctx context.Context, gceCS *GCEControllerServer, ex
1667
1672
return ret , nil
1668
1673
}
1669
1674
1670
- func generateCreateVolumeResponse (disk * gce.CloudDisk , zones []string ) * csi.CreateVolumeResponse {
1675
+ func paramsToVolumeContext (params common.DiskParameters ) map [string ]string {
1676
+ context := map [string ]string {}
1677
+ if params .ForceAttach {
1678
+ context [common .ParameterForceAttach ] = "true"
1679
+ }
1680
+ if len (context ) > 0 {
1681
+ return context
1682
+ }
1683
+ return nil
1684
+ }
1685
+
1686
+ func extractVolumeContext (context map [string ]string ) (* PDCSIContext , error ) {
1687
+ info := & PDCSIContext {}
1688
+ for key , val := range context {
1689
+ switch key {
1690
+ case common .ParameterForceAttach :
1691
+ b , err := common .ConvertStringToBool (val )
1692
+ if err != nil {
1693
+ return nil , fmt .Errorf ("Bad volume context force attach: %v" , err )
1694
+ }
1695
+ info .ForceAttach = b
1696
+ default :
1697
+ return nil , fmt .Errorf ("Unknown VolumeContext key %v" , key )
1698
+ }
1699
+ }
1700
+ return info , nil
1701
+ }
1702
+
1703
+ func generateCreateVolumeResponse (disk * gce.CloudDisk , zones []string , params common.DiskParameters ) * csi.CreateVolumeResponse {
1671
1704
tops := []* csi.Topology {}
1672
1705
for _ , zone := range zones {
1673
1706
tops = append (tops , & csi.Topology {
@@ -1679,7 +1712,7 @@ func generateCreateVolumeResponse(disk *gce.CloudDisk, zones []string) *csi.Crea
1679
1712
Volume : & csi.Volume {
1680
1713
CapacityBytes : realDiskSizeBytes ,
1681
1714
VolumeId : cleanSelfLink (disk .GetSelfLink ()),
1682
- VolumeContext : nil ,
1715
+ VolumeContext : paramsToVolumeContext ( params ) ,
1683
1716
AccessibleTopology : tops ,
1684
1717
},
1685
1718
}
0 commit comments