@@ -260,8 +260,11 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
260260 return nil
261261}
262262
263- // destroyVolumeIfNoLUN attempts to destroy volume if there exists a volume with no associated LUN.
264- // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN.
263+ // cleanupIncompleteLUN attempts to destroy volume if there exists a volume with no associated LUN.
264+ // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN or
265+ // the LUN exists but is associated with a different pool as it was not cleaned up properly and creation is retried
266+ // with different pool.
267+ // This can happen if volume creation succeeded but LUN creation failed in a previous Create() call.
265268// Returns (Volume State, error)
266269//
267270// Caller can check for:
@@ -271,15 +274,18 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
271274// - Could not destroy the required volume for an error.
272275// Volume state:true indicating both volume and required LUN exist.
273276// Volume state:false indicating no volume existed or cleaned up now.
274- func (d * SANStorageDriver ) destroyVolumeIfNoLUN (ctx context.Context , volConfig * storage.VolumeConfig ) (bool , error ) {
277+ func (d * SANStorageDriver ) cleanupIncompleteLUN (
278+ ctx context.Context , volConfig * storage.VolumeConfig , poolName string ,
279+ ) (bool , error ) {
275280 name := volConfig .InternalName
276281 fields := LogFields {
277- "Method" : "destroyVolumeIfNoLUN" ,
278- "Type" : "SANStorageDriver" ,
279- "name" : name ,
282+ "Method" : "cleanupIncompleteLUN" ,
283+ "Type" : "SANStorageDriver" ,
284+ "name" : name ,
285+ "poolName" : poolName ,
280286 }
281- Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> destroyVolumeIfNoLUN " )
282- defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< destroyVolumeIfNoLUN " )
287+ Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> cleanupIncompleteLUN " )
288+ defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< cleanupIncompleteLUN " )
283289
284290 volExists , err := d .API .VolumeExists (ctx , name )
285291 if err != nil {
@@ -297,20 +303,44 @@ func (d *SANStorageDriver) destroyVolumeIfNoLUN(ctx context.Context, volConfig *
297303 // Verify if LUN exists.
298304 newLUNPath := lunPath (name )
299305 extantLUN , err := d .API .LunGetByName (ctx , newLUNPath )
300- if extantLUN != nil {
301- // Volume and LUN both exist. No clean up needed.
302- return true , nil
303- }
304- if ! errors .IsNotFoundError (err ) {
306+ if err != nil && ! errors .IsNotFoundError (err ) {
305307 // Could not verify if LUN exists. Clean up pending.
306308 return false , fmt .Errorf ("error checking for existing LUN %s: %v" , newLUNPath , err )
307309 }
308- // LUN does not exist, but volume. Initiate clean-up.
309- if err = d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
310- Logc (ctx ).WithField ("volume" , name ).Errorf ("Could not clean up volume: %v" , err )
311- return true , fmt .Errorf ("could not clean up partial create of vol/lun: %v" , err )
310+
311+ var destroyReason string
312+ var destroyErrorMsg string
313+
314+ if extantLUN != nil {
315+ // Both the volume and LUN exist. Check if the last attribute set on the LUN, i.e., the pool name, matches.
316+ lunPoolName , err := d .API .LunGetAttribute (ctx , newLUNPath , "poolName" )
317+ if err != nil || lunPoolName != poolName {
318+ // If there is an error getting pool name or pool name doesn't match
319+ Logc (ctx ).WithFields (LogFields {
320+ "LUN" : newLUNPath ,
321+ "lunPoolName" : lunPoolName ,
322+ "inputPoolName" : poolName ,
323+ "error" : err ,
324+ }).Info ("Pool name not found or mismatch detected. Destroying volume." )
325+
326+ destroyReason = "Destroyed volume with mismatched pool name."
327+ destroyErrorMsg = "could not destroy volume with mismatched pool"
328+ } else {
329+ // Pool name matches or no pool name attribute. No clean up needed.
330+ return true , nil
331+ }
332+ } else {
333+ // LUN does not exist, but volume does. Initiate clean-up.
334+ destroyReason = "Cleaned up volume since LUN create failed."
335+ destroyErrorMsg = "could not clean up partial create of vol/lun"
336+ }
337+
338+ if err := d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
339+ Logc (ctx ).WithError (err ).WithField ("volume" , name ).Errorf ("Could not clean up volume" )
340+ return true , fmt .Errorf ("%s: %v" , destroyErrorMsg , err )
312341 }
313- Logc (ctx ).WithField ("volume" , name ).Debug ("Cleaned up volume since LUN create failed." )
342+ Logc (ctx ).WithField ("volume" , name ).Debug (destroyReason )
343+
314344 return false , nil
315345}
316346
@@ -332,7 +362,7 @@ func (d *SANStorageDriver) Create(
332362 defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< Create" )
333363
334364 // Early exit if volume+LUN exist. Clean up volume if no LUN exists.
335- volExists , err := d .destroyVolumeIfNoLUN (ctx , volConfig )
365+ volExists , err := d .cleanupIncompleteLUN (ctx , volConfig , storagePool . Name () )
336366 if err != nil {
337367 return fmt .Errorf ("failure checking for existence of volume and cleaning if any: %v" , err )
338368 }
@@ -574,11 +604,10 @@ func (d *SANStorageDriver) Create(
574604
575605 // Save the fstype in a LUN attribute so we know what to do in Attach. If this fails, clean up and
576606 // move on to the next pool.
577- // Save the context, fstype, and LUKS value in LUN comment
607+ // Save the context, fstype, LUKS value, and pool name in LUN comment
578608 err = d .API .LunSetAttribute (ctx , lunPath , LUNAttributeFSType , fstype , string (d .Config .DriverContext ),
579- luksEncryption , formatOptions )
609+ luksEncryption , formatOptions , storagePool . Name () )
580610 if err != nil {
581-
582611 errMessage := fmt .Sprintf ("ONTAP-SAN pool %s/%s; error saving file system type for LUN %s: %v" ,
583612 storagePool .Name (), aggregate , name , err )
584613 Logc (ctx ).Error (errMessage )
0 commit comments