@@ -265,8 +265,11 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
265265 return nil
266266}
267267
268- // destroyVolumeIfNoLUN attempts to destroy volume if there exists a volume with no associated LUN.
269- // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN.
268+ // cleanupIncompleteLUN attempts to destroy volume if there exists a volume with no associated LUN.
269+ // This is used to make Create() idempotent by cleaning up a Flexvol with no LUN or
270+ // the LUN exists but is associated with a different pool as it was not cleaned up properly and creation is retried
271+ // with different pool.
272+ // This can happen if volume creation succeeded but LUN creation failed in a previous Create() call.
270273// Returns (Volume State, error)
271274//
272275// Caller can check for:
@@ -276,15 +279,18 @@ func (d *SANStorageDriver) validate(ctx context.Context) error {
276279// - Could not destroy the required volume for an error.
277280// Volume state:true indicating both volume and required LUN exist.
278281// Volume state:false indicating no volume existed or cleaned up now.
279- func (d * SANStorageDriver ) destroyVolumeIfNoLUN (ctx context.Context , volConfig * storage.VolumeConfig ) (bool , error ) {
282+ func (d * SANStorageDriver ) cleanupIncompleteLUN (
283+ ctx context.Context , volConfig * storage.VolumeConfig , poolName string ,
284+ ) (bool , error ) {
280285 name := volConfig .InternalName
281286 fields := LogFields {
282- "Method" : "destroyVolumeIfNoLUN" ,
283- "Type" : "SANStorageDriver" ,
284- "name" : name ,
287+ "Method" : "cleanupIncompleteLUN" ,
288+ "Type" : "SANStorageDriver" ,
289+ "name" : name ,
290+ "poolName" : poolName ,
285291 }
286- Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> destroyVolumeIfNoLUN " )
287- defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< destroyVolumeIfNoLUN " )
292+ Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace (">>>> cleanupIncompleteLUN " )
293+ defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< cleanupIncompleteLUN " )
288294
289295 volExists , err := d .API .VolumeExists (ctx , name )
290296 if err != nil {
@@ -302,20 +308,44 @@ func (d *SANStorageDriver) destroyVolumeIfNoLUN(ctx context.Context, volConfig *
302308 // Verify if LUN exists.
303309 newLUNPath := lunPath (name )
304310 extantLUN , err := d .API .LunGetByName (ctx , newLUNPath )
305- if extantLUN != nil {
306- // Volume and LUN both exist. No clean up needed.
307- return true , nil
308- }
309- if ! errors .IsNotFoundError (err ) {
311+ if err != nil && ! errors .IsNotFoundError (err ) {
310312 // Could not verify if LUN exists. Clean up pending.
311313 return false , fmt .Errorf ("error checking for existing LUN %s: %v" , newLUNPath , err )
312314 }
313- // LUN does not exist, but volume. Initiate clean-up.
314- if err = d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
315- Logc (ctx ).WithField ("volume" , name ).Errorf ("Could not clean up volume: %v" , err )
316- return true , fmt .Errorf ("could not clean up partial create of vol/lun: %v" , err )
315+
316+ var destroyReason string
317+ var destroyErrorMsg string
318+
319+ if extantLUN != nil {
320+ // Both the volume and LUN exist. Check if the last attribute set on the LUN, i.e., the pool name, matches.
321+ lunPoolName , err := d .API .LunGetAttribute (ctx , newLUNPath , "poolName" )
322+ if err != nil || lunPoolName != poolName {
323+ // If there is an error getting pool name or pool name doesn't match
324+ Logc (ctx ).WithFields (LogFields {
325+ "LUN" : newLUNPath ,
326+ "lunPoolName" : lunPoolName ,
327+ "inputPoolName" : poolName ,
328+ "error" : err ,
329+ }).Info ("Pool name not found or mismatch detected. Destroying volume." )
330+
331+ destroyReason = "Destroyed volume with mismatched pool name."
332+ destroyErrorMsg = "could not destroy volume with mismatched pool"
333+ } else {
334+ // Pool name matches or no pool name attribute. No clean up needed.
335+ return true , nil
336+ }
337+ } else {
338+ // LUN does not exist, but volume does. Initiate clean-up.
339+ destroyReason = "Cleaned up volume since LUN create failed."
340+ destroyErrorMsg = "could not clean up partial create of vol/lun"
317341 }
318- Logc (ctx ).WithField ("volume" , name ).Debug ("Cleaned up volume since LUN create failed." )
342+
343+ if err := d .API .VolumeDestroy (ctx , name , true , true ); err != nil {
344+ Logc (ctx ).WithError (err ).WithField ("volume" , name ).Errorf ("Could not clean up volume" )
345+ return true , fmt .Errorf ("%s: %v" , destroyErrorMsg , err )
346+ }
347+ Logc (ctx ).WithField ("volume" , name ).Debug (destroyReason )
348+
319349 return false , nil
320350}
321351
@@ -338,7 +368,7 @@ func (d *SANStorageDriver) Create(
338368 defer Logd (ctx , d .Name (), d .Config .DebugTraceFlags ["method" ]).WithFields (fields ).Trace ("<<<< Create" )
339369
340370 // Early exit if volume+LUN exist. Clean up volume if no LUN exists.
341- volExists , err := d .destroyVolumeIfNoLUN (ctx , volConfig )
371+ volExists , err := d .cleanupIncompleteLUN (ctx , volConfig , storagePool . Name () )
342372 if err != nil {
343373 return fmt .Errorf ("failure checking for existence of volume and cleaning if any: %v" , err )
344374 }
@@ -580,9 +610,9 @@ func (d *SANStorageDriver) Create(
580610
581611 // Save the fstype in a LUN attribute so we know what to do in Attach. If this fails, clean up and
582612 // move on to the next pool.
583- // Save the context, fstype, and LUKS value in LUN comment
613+ // Save the context, fstype, LUKS value, and pool name in LUN comment
584614 err = d .API .LunSetAttribute (ctx , lunPath , LUNAttributeFSType , fstype , string (d .Config .DriverContext ),
585- luksEncryption , formatOptions )
615+ luksEncryption , formatOptions , storagePool . Name () )
586616 if err != nil {
587617
588618 errMessage := fmt .Sprintf ("ONTAP-SAN pool %s/%s; error saving file system type for LUN %s: %v" ,
0 commit comments