@@ -259,8 +259,11 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
259259 return nil
260260}
261261
262- // destroyVolumeIfNoLUN attempts to destroy volume if there exists a volume with no associated LUN.
263- // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN.
262+ // cleanupIncompleteLUN attempts to destroy volume if there exists a volume with no associated LUN.
263+ // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN or
264+ // the LUN exists but is associated with a different pool as it was not cleaned up properly and creation is retried
265+ // with different pool.
266+ // This can happen if volume creation succeeded but LUN creation failed in a previous Create() call.
264267// Returns (Volume State, error)
265268//
266269// Caller can check for:
@@ -270,15 +273,18 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
270273// - Could not destroy the required volume for an error.
271274// Volume state:true indicating both volume and required LUN exist.
272275// Volume state:false indicating no volume existed or cleaned up now.
273- func (d * SANStorageDriver ) destroyVolumeIfNoLUN (ctx context.Context , volConfig * storage.VolumeConfig ) (bool , error ) {
276+ func (d * SANStorageDriver ) cleanupIncompleteLUN (
277+ ctx context.Context , volConfig * storage.VolumeConfig , poolName string ,
278+ ) (bool , error ) {
274279 name := volConfig .InternalName
275280 fields := LogFields {
276- "Method" : "destroyVolumeIfNoLUN" ,
277- "Type" : "SANStorageDriver" ,
278- "name" : name ,
281+ "Method" : "cleanupIncompleteLUN" ,
282+ "Type" : "SANStorageDriver" ,
283+ "name" : name ,
284+ "poolName" : poolName ,
279285 }
280- Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> destroyVolumeIfNoLUN " )
281- defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< destroyVolumeIfNoLUN " )
286+ Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> cleanupIncompleteLUN " )
287+ defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< cleanupIncompleteLUN " )
282288
283289 volExists , err := d .API .VolumeExists (ctx , name )
284290 if err != nil {
@@ -296,20 +302,44 @@ func (d *SANStorageDriver) destroyVolumeIfNoLUN(ctx context.Context, volConfig *
296302 // Verify if LUN exists.
297303 newLUNPath := lunPath (name )
298304 extantLUN , err := d .API .LunGetByName (ctx , newLUNPath )
299- if extantLUN != nil {
300- // Volume and LUN both exist. No clean up needed.
301- return true , nil
302- }
303- if ! errors .IsNotFoundError (err ) {
305+ if err != nil && ! errors .IsNotFoundError (err ) {
304306 // Could not verify if LUN exists. Clean up pending.
305307 return false , fmt .Errorf ("error checking for existing LUN %s: %v" , newLUNPath , err )
306308 }
307- // LUN does not exist, but volume. Initiate clean-up.
308- if err = d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
309- Logc (ctx ).WithField ("volume" , name ).Errorf ("Could not clean up volume: %v" , err )
310- return true , fmt .Errorf ("could not clean up partial create of vol/lun: %v" , err )
309+
310+ var destroyReason string
311+ var destroyErrorMsg string
312+
313+ if extantLUN != nil {
314+ // Both the volume and LUN exist. Check if the last attribute set on the LUN, i.e., the pool name, matches.
315+ lunPoolName , err := d .API .LunGetAttribute (ctx , newLUNPath , "poolName" )
316+ if err != nil || lunPoolName != poolName {
317+ // If there is an error getting pool name or pool name doesn't match
318+ Logc (ctx ).WithFields (LogFields {
319+ "LUN" : newLUNPath ,
320+ "lunPoolName" : lunPoolName ,
321+ "inputPoolName" : poolName ,
322+ "error" : err ,
323+ }).Info ("Pool name not found or mismatch detected. Destroying volume." )
324+
325+ destroyReason = "Destroyed volume with mismatched pool name."
326+ destroyErrorMsg = "could not destroy volume with mismatched pool"
327+ } else {
328+ // Pool name matches or no pool name attribute. No clean up needed.
329+ return true , nil
330+ }
331+ } else {
332+ // LUN does not exist, but volume does. Initiate clean-up.
333+ destroyReason = "Cleaned up volume since LUN create failed."
334+ destroyErrorMsg = "could not clean up partial create of vol/lun"
311335 }
312- Logc (ctx ).WithField ("volume" , name ).Debug ("Cleaned up volume since LUN create failed." )
336+
337+ if err := d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
338+ Logc (ctx ).WithError (err ).WithField ("volume" , name ).Errorf ("Could not clean up volume" )
339+ return true , fmt .Errorf ("%s: %v" , destroyErrorMsg , err )
340+ }
341+ Logc (ctx ).WithField ("volume" , name ).Debug (destroyReason )
342+
313343 return false , nil
314344}
315345
@@ -331,7 +361,7 @@ func (d *SANStorageDriver) Create(
331361 defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< Create" )
332362
333363 // Early exit if volume+LUN exist. Clean up volume if no LUN exists.
334- volExists , err := d .destroyVolumeIfNoLUN (ctx , volConfig )
364+ volExists , err := d .cleanupIncompleteLUN (ctx , volConfig , storagePool . Name () )
335365 if err != nil {
336366 return fmt .Errorf ("failure checking for existence of volume and cleaning if any: %v" , err )
337367 }
@@ -573,9 +603,9 @@ func (d *SANStorageDriver) Create(
573603
574604 // Save the fstype in a LUN attribute so we know what to do in Attach. If this fails, clean up and
575605 // move on to the next pool.
576- // Save the context, fstype, and LUKS value in LUN comment
606+ // Save the context, fstype, LUKS value, and pool name in LUN comment
577607 err = d .API .LunSetAttribute (ctx , lunPath , LUNAttributeFSType , fstype , string (d .Config .DriverContext ),
578- luksEncryption , formatOptions )
608+ luksEncryption , formatOptions , storagePool . Name () )
579609 if err != nil {
580610
581611 errMessage := fmt .Sprintf ("ONTAP-SAN pool %s/%s; error saving file system type for LUN %s: %v" ,
0 commit comments