@@ -128,7 +128,6 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
128128 s_logger .error ("createAsync: Storage Pool not found for id: " + dataStore .getId ());
129129 throw new CloudRuntimeException ("createAsync: Storage Pool not found for id: " + dataStore .getId ());
130130 }
131- String storagePoolUuid = dataStore .getUuid ();
132131
133132 Map <String , String > details = storagePoolDetailsDao .listDetailsKeyPairs (dataStore .getId ());
134133
@@ -145,7 +144,6 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
145144 volumeVO .setPoolId (storagePool .getId ());
146145
147146 if (ProtocolType .ISCSI .name ().equalsIgnoreCase (details .get (Constants .PROTOCOL ))) {
148- String svmName = details .get (Constants .SVM_NAME );
149147 String lunName = created != null && created .getLun () != null ? created .getLun ().getName () : null ;
150148 if (lunName == null ) {
151149 throw new CloudRuntimeException ("createAsync: Missing LUN name for volume " + volInfo .getId ());
@@ -158,17 +156,17 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
158156 volumeVO .setFolder (created .getLun ().getUuid ());
159157 }
160158
161- // Create LUN-to-igroup mapping and retrieve the assigned LUN ID
162- UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy ) Utility .getStrategyByStoragePoolDetails (details );
163- String accessGroupName = Utility .getIgroupName (svmName , storagePoolUuid );
164- String lunNumber = sanStrategy .ensureLunMapped (svmName , lunName , accessGroupName );
159+ // DO NOT map LUN to igroup here - mapping will be done in grantAccess() to per-host igroup
160+ // This ensures each host only sees LUNs mapped to its specific igroup during discovery
161+ // For per-host igroups, LUN mapping happens when VM is actually attached to a host
162+ s_logger .info ("createAsync: Created LUN [{}] for volume [{}]. LUN mapping will occur during grantAccess() to per-host igroup." ,
163+ lunName , volumeVO .getId ());
165164
166- // Construct iSCSI path: /<iqn>/<lun_id> format for KVM/libvirt attachment
167- String iscsiPath = Constants .SLASH + storagePool .getPath () + Constants .SLASH + lunNumber ;
168- volumeVO .set_iScsiName (iscsiPath );
169- volumeVO .setPath (iscsiPath );
170- s_logger .info ("createAsync: Volume [{}] iSCSI path set to {}" , volumeVO .getId (), iscsiPath );
171- createCmdResult = new CreateCmdResult (null , new Answer (null , true , null ));
165+ // Path will be set during grantAccess when LUN is mapped and we get the LUN ID
166+ // Return LUN name as identifier for CloudStack tracking
167+ volumeVO .set_iScsiName (null );
168+ volumeVO .setPath (null );
169+ createCmdResult = new CreateCmdResult (lunName , new Answer (null , true , null ));
172170
173171 } else if (ProtocolType .NFS3 .name ().equalsIgnoreCase (details .get (Constants .PROTOCOL ))) {
174172 createCmdResult = new CreateCmdResult (volInfo .getUuid (), new Answer (null , true , null ));
@@ -319,16 +317,23 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
319317 // Only retrieve LUN name for iSCSI volumes
320318 String cloudStackVolumeName = volumeDetailsDao .findDetail (volumeVO .getId (), Constants .LUN_DOT_NAME ).getValue ();
321319 UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy ) Utility .getStrategyByStoragePoolDetails (details );
322- String accessGroupName = Utility .getIgroupName (svmName , storagePoolUuid );
323-
324- // Verify host initiator is registered in the igroup before allowing access
325- if (!sanStrategy .validateInitiatorInAccessGroup (host .getStorageUrl (), svmName , accessGroupName )) {
326- throw new CloudRuntimeException ("grantAccess: Host initiator [" + host .getStorageUrl () +
327- "] is not present in iGroup [" + accessGroupName + "]" );
320+ // Use per-host igroup for this host
321+ // Each host sees only LUNs mapped to its per-host igroup, reducing discovery time
322+ String perHostIgroupName = Utility .getPerHostIgroupName (svmName , storagePoolUuid , host .getName ());
323+ s_logger .info ("grantAccess: Mapping LUN to per-host igroup [{}] for host [{}]" , perHostIgroupName , host .getName ());
324+
325+ // Validate per-host igroup exists with the host's initiator
326+ if (!sanStrategy .validateInitiatorInAccessGroup (host .getStorageUrl (), svmName , perHostIgroupName )) {
327+ String errMsg = String .format ("grantAccess: Per-host igroup [%s] does not exist or does not contain host initiator [%s]. " +
328+ "Per-host igroup must be created during host-pool attachment." ,
329+ perHostIgroupName , host .getStorageUrl ());
330+ s_logger .error (errMsg );
331+ throw new CloudRuntimeException (errMsg );
328332 }
329333
330- // Create or retrieve existing LUN mapping
331- String lunNumber = sanStrategy .ensureLunMapped (svmName , cloudStackVolumeName , accessGroupName );
334+ // Map LUN to the per-host igroup
335+ String lunNumber = sanStrategy .ensureLunMapped (svmName ,cloudStackVolumeName , perHostIgroupName );
336+ s_logger .info ("grantAccess: LUN [{}] mapped to per-host igroup [{}] with LUN ID [{}]" , cloudStackVolumeName , perHostIgroupName , lunNumber );
332337
333338 // Update volume path if changed (e.g., after migration or re-mapping)
334339 String iscsiPath = Constants .SLASH + storagePool .getPath () + Constants .SLASH + lunNumber ;
@@ -427,7 +432,9 @@ private void revokeAccessForVolume(StoragePoolVO storagePool, VolumeVO volumeVO,
427432 String storagePoolUuid = storagePool .getUuid ();
428433
429434 if (ProtocolType .ISCSI .name ().equalsIgnoreCase (details .get (Constants .PROTOCOL ))) {
430- String accessGroupName = Utility .getIgroupName (svmName , storagePoolUuid );
435+ // Use per-host igroup for unmapping
436+ String perHostIgroupName = Utility .getPerHostIgroupName (svmName , storagePoolUuid , host .getName ());
437+ s_logger .info ("revokeAccessForVolume: Using per-host igroup [{}] for host [{}]" , perHostIgroupName , host .getName ());
431438
432439 // Retrieve LUN name from volume details; if missing, volume may not have been fully created
433440 String lunName = volumeDetailsDao .findDetail (volumeVO .getId (), Constants .LUN_DOT_NAME ) != null ?
@@ -444,29 +451,29 @@ private void revokeAccessForVolume(StoragePoolVO storagePool, VolumeVO volumeVO,
444451 return ;
445452 }
446453
447- // Verify igroup still exists on ONTAP
448- AccessGroup accessGroup = getAccessGroupByName (storageStrategy , svmName , accessGroupName );
454+ // Verify per-host igroup still exists on ONTAP
455+ AccessGroup accessGroup = getAccessGroupByName (storageStrategy , svmName , perHostIgroupName );
449456 if (accessGroup == null || accessGroup .getIgroup () == null || accessGroup .getIgroup ().getUuid () == null ) {
450- s_logger .warn ("revokeAccessForVolume: iGroup [{}] not found on ONTAP, skipping revoke" , accessGroupName );
457+ s_logger .warn ("revokeAccessForVolume: Per-host iGroup [{}] not found on ONTAP, skipping revoke" , perHostIgroupName );
451458 return ;
452459 }
453460
454- // Verify host initiator is in the igroup before attempting to remove mapping
461+ // Verify host initiator is in the per-host igroup before attempting to remove mapping
455462 SANStrategy sanStrategy = (UnifiedSANStrategy ) storageStrategy ;
456463 if (!sanStrategy .validateInitiatorInAccessGroup (host .getStorageUrl (), svmName , accessGroup .getIgroup ().getName ())) {
457- s_logger .warn ("revokeAccessForVolume: Initiator [{}] is not in iGroup [{}], skipping revoke" ,
458- host .getStorageUrl (), accessGroupName );
464+ s_logger .warn ("revokeAccessForVolume: Initiator [{}] is not in per-host iGroup [{}], skipping revoke" ,
465+ host .getStorageUrl (), perHostIgroupName );
459466 return ;
460467 }
461468
462- // Remove the LUN mapping from the igroup
469+ // Remove the LUN mapping from the per-host igroup
463470 Map <String , String > disableLogicalAccessMap = new HashMap <>();
464471 disableLogicalAccessMap .put (Constants .LUN_DOT_UUID , cloudStackVolume .getLun ().getUuid ());
465472 disableLogicalAccessMap .put (Constants .IGROUP_DOT_UUID , accessGroup .getIgroup ().getUuid ());
466473 storageStrategy .disableLogicalAccess (disableLogicalAccessMap );
467474
468- s_logger .info ("revokeAccessForVolume: Successfully revoked access to LUN [{}] for host [{}]" ,
469- lunName , host .getName ());
475+ s_logger .info ("revokeAccessForVolume: Successfully revoked access to LUN [{}] from per-host igroup [{}] for host [{}]" ,
476+ lunName , perHostIgroupName , host .getName ());
470477 }
471478 }
472479
0 commit comments