@@ -81,14 +81,17 @@ func (cs *ControllerServer) validateVolumeReq(ctx context.Context, req *csi.Crea
8181 }
8282 options := req .GetParameters ()
8383 if value , ok := options ["clusterID" ]; ! ok || value == "" {
84- return status .Error (codes .InvalidArgument , "empty cluster ID to provision volume from" )
84+ if _ , ok := options ["clusterTopologyConfigMap" ]; ! ok {
85+ return status .Error (codes .InvalidArgument , "empty cluster ID to provision volume from" )
86+ }
8587 }
8688 poolValue , poolOK := options ["pool" ]
8789 topologyConstrainedPoolsValue , topologyOK := options ["topologyConstrainedPools" ]
90+ _ , clusterTopologyOK := options ["clusterTopologyConfigMap" ]
8891 if ! poolOK {
8992 if topologyOK && topologyConstrainedPoolsValue == "" {
9093 return status .Error (codes .InvalidArgument , "empty pool name or topologyConstrainedPools to provision volume" )
91- } else if ! topologyOK {
94+ } else if ! topologyOK && ! clusterTopologyOK {
9295 return status .Error (codes .InvalidArgument , "missing or empty pool name to provision volume from" )
9396 }
9497 } else if poolValue == "" {
@@ -155,7 +158,6 @@ func validateStriping(parameters map[string]string) error {
155158func (cs * ControllerServer ) parseVolCreateRequest (
156159 ctx context.Context ,
157160 req * csi.CreateVolumeRequest ,
158- cr * util.Credentials ,
159161) (* rbdVolume , error ) {
160162 // TODO (sbezverk) Last check for not exceeding total storage capacity
161163
@@ -230,17 +232,26 @@ func (cs *ControllerServer) parseVolCreateRequest(
230232 return nil , status .Error (codes .InvalidArgument , err .Error ())
231233 }
232234
235+ // store cluster topology information from the request if present
236+ var clusterTopologyRequirement * csi.TopologyRequirement
237+ rbdVol .ClusterTopologies , clusterTopologyRequirement , err = util .GetClusterTopologiesFromRequest (req )
238+ if err != nil {
239+ return nil , status .Error (codes .InvalidArgument , err .Error ())
240+ }
241+ if rbdVol .TopologyRequirement == nil {
242+ rbdVol .TopologyRequirement = clusterTopologyRequirement
243+ }
244+
233245 // parse QOS parameters from mutable parameters
234246 err = rbdVol .SetQOS (ctx , req .GetMutableParameters ())
235247 if err != nil {
236248 return nil , status .Error (codes .InvalidArgument , err .Error ())
237249 }
238250
239- err = rbdVol .Connect (cr )
251+ // Get QosParameters from SC if qos configuration existing in SC
252+ err = rbdVol .SetQOS (ctx , req .GetParameters ())
240253 if err != nil {
241- log .ErrorLog (ctx , "failed to connect to volume %v: %v" , rbdVol .RbdImageName , err )
242-
243- return nil , status .Error (codes .Internal , err .Error ())
254+ return nil , status .Error (codes .InvalidArgument , err .Error ())
244255 }
245256
246257 // NOTE: rbdVol does not contain VolID and RbdImageName populated, everything
@@ -278,6 +289,10 @@ func (rbdVol *rbdVolume) ToCSI(ctx context.Context) (*csi.Volume, error) {
278289 vol .VolumeContext ["dataPool" ] = rbdVol .DataPool
279290 }
280291
292+ if rbdVol .ClusterSecretName != "" {
293+ vol .VolumeContext ["clusterSecretName" ] = rbdVol .ClusterSecretName
294+ }
295+
281296 if rbdVol .Topology != nil {
282297 vol .AccessibleTopology = []* csi.Topology {
283298 {
@@ -362,19 +377,48 @@ func (cs *ControllerServer) CreateVolume(
362377 return nil , err
363378 }
364379
380+ rbdVol , err := cs .parseVolCreateRequest (ctx , req )
381+ if err != nil {
382+ return nil , err
383+ }
384+ defer rbdVol .Destroy (ctx )
385+
386+ selectedCluster := util.ClusterTopology {}
387+ if rbdVol .ClusterTopologies != nil {
388+ selectedCluster , _ , err = util .FindClusterAndTopology (rbdVol .ClusterTopologies , rbdVol .TopologyRequirement )
389+ if err != nil {
390+ return nil , status .Error (codes .InvalidArgument , err .Error ())
391+ }
392+ if selectedCluster .ClusterID == "" {
393+ return nil , status .Error (codes .InvalidArgument , "no matching cluster found for provided topology requirements" )
394+ }
395+ // persist selected secret for volume context
396+ rbdVol .ClusterSecretName = selectedCluster .SecretName
397+ }
398+
399+ secrets := req .GetSecrets ()
400+ if len (secrets ) == 0 && selectedCluster .SecretName != "" {
401+ namespace , nsErr := util .GetPodNamespace ()
402+ if nsErr != nil {
403+ return nil , status .Error (codes .InvalidArgument , nsErr .Error ())
404+ }
405+ secrets , err = k8s .GetSecret (selectedCluster .SecretName , namespace )
406+ if err != nil {
407+ return nil , status .Error (codes .InvalidArgument , err .Error ())
408+ }
409+ }
410+ if len (secrets ) == 0 {
411+ return nil , status .Error (codes .InvalidArgument , "missing credentials for provisioning" )
412+ }
413+
365414 // TODO: create/get a connection from the ConnPool, and do not pass the
366415 // credentials to any of the utility functions.
367416
368- cr , err := util .NewUserCredentialsWithMigration (req . GetSecrets () )
417+ cr , err := util .NewUserCredentialsWithMigration (secrets )
369418 if err != nil {
370419 return nil , status .Error (codes .InvalidArgument , err .Error ())
371420 }
372421 defer cr .DeleteCredentials ()
373- rbdVol , err := cs .parseVolCreateRequest (ctx , req , cr )
374- if err != nil {
375- return nil , err
376- }
377- defer rbdVol .Destroy (ctx )
378422 // Existence and conflict checks
379423 if acquired := cs .VolumeLocks .TryAcquire (req .GetName ()); ! acquired {
380424 log .ErrorLog (ctx , util .VolumeOperationAlreadyExistsFmt , req .GetName ())
@@ -399,6 +443,13 @@ func (cs *ControllerServer) CreateVolume(
399443 return nil , status .Error (codes .Internal , err .Error ())
400444 }
401445
446+ err = rbdVol .Connect (cr )
447+ if err != nil {
448+ log .ErrorLog (ctx , "failed to connect to volume %v: %v" , rbdVol .RbdImageName , err )
449+
450+ return nil , status .Error (codes .Internal , err .Error ())
451+ }
452+
402453 found , err := rbdVol .Exists (ctx , parentVol )
403454 if err != nil {
404455 return nil , getGRPCErrorForCreateVolume (err )
@@ -868,8 +919,8 @@ func checkContentSource(
868919 return nil , nil , status .Error (codes .NotFound , "volume cannot be empty" )
869920 }
870921 volID := vol .GetVolumeId ()
871- if err := util . ValidateVolumeID ( volID , true ); err != nil {
872- return nil , nil , status .Error (codes .InvalidArgument , err . Error () )
922+ if volID == "" {
923+ return nil , nil , status .Errorf (codes .NotFound , "volume ID cannot be empty" )
873924 }
874925 rbdvol , err := GenVolFromVolID (ctx , volID , cr , req .GetSecrets ())
875926 if err != nil {
@@ -957,8 +1008,8 @@ func (cs *ControllerServer) DeleteVolume(
9571008
9581009 // For now the image get unconditionally deleted, but here retention policy can be checked
9591010 volumeID := req .GetVolumeId ()
960- if err := util . ValidateVolumeID ( volumeID , true ); err != nil {
961- return nil , status .Error (codes .InvalidArgument , err . Error () )
1011+ if volumeID == "" {
1012+ return nil , status .Error (codes .InvalidArgument , "empty volume ID in request" )
9621013 }
9631014
9641015 cr , err := util .NewUserCredentialsWithMigration (req .GetSecrets ())
@@ -1121,8 +1172,8 @@ func (cs *ControllerServer) ValidateVolumeCapabilities(
11211172 ctx context.Context ,
11221173 req * csi.ValidateVolumeCapabilitiesRequest ,
11231174) (* csi.ValidateVolumeCapabilitiesResponse , error ) {
1124- if err := util . ValidateVolumeID ( req .GetVolumeId (), util . IsStaticVol ( req . GetVolumeContext ())); err != nil {
1125- return nil , status .Error (codes .InvalidArgument , err . Error () )
1175+ if req .GetVolumeId () == "" {
1176+ return nil , status .Error (codes .InvalidArgument , "empty volume ID in request" )
11261177 }
11271178
11281179 if len (req .GetVolumeCapabilities ()) == 0 {
@@ -1595,8 +1646,8 @@ func (cs *ControllerServer) ControllerExpandVolume(
15951646 }
15961647
15971648 volID := req .GetVolumeId ()
1598- if err := util . ValidateVolumeID ( volID , true ); err != nil {
1599- return nil , status .Error (codes .InvalidArgument , err . Error () )
1649+ if volID == "" {
1650+ return nil , status .Error (codes .InvalidArgument , "volume ID cannot be empty" )
16001651 }
16011652
16021653 capRange := req .GetCapacityRange ()
@@ -1777,8 +1828,8 @@ func (cs *ControllerServer) ControllerUnpublishVolume(
17771828 if ! k8s .RunsOnKubernetes () {
17781829 return & csi.ControllerUnpublishVolumeResponse {}, nil
17791830 }
1780- if err := util . ValidateVolumeID ( req .GetVolumeId (), true ); err != nil {
1781- return nil , status .Error (codes .InvalidArgument , err . Error () )
1831+ if req .GetVolumeId () == "" {
1832+ return nil , status .Error (codes .InvalidArgument , "Volume ID cannot be empty" )
17821833 }
17831834
17841835 volumeId := req .GetVolumeId ()
0 commit comments