1818 */
1919package org .apache .cloudstack .storage .driver ;
2020
21- import org .apache .cloudstack .storage .utils .OntapStorageConstants ;
22- import com .cloud .agent .api .Answer ;
23- import com .cloud .agent .api .to .DataObjectType ;
24- import com .cloud .agent .api .to .DataStoreTO ;
25- import com .cloud .agent .api .to .DataTO ;
26- import com .cloud .exception .InvalidParameterValueException ;
27- import com .cloud .host .Host ;
28- import com .cloud .host .HostVO ;
29- import com .cloud .storage .Storage ;
30- import com .cloud .storage .StoragePool ;
31- import com .cloud .storage .Volume ;
32- import com .cloud .storage .VolumeDetailVO ;
33- import com .cloud .storage .VolumeVO ;
34- import com .cloud .storage .ScopeType ;
35- import com .cloud .storage .dao .SnapshotDetailsDao ;
36- import com .cloud .storage .dao .SnapshotDetailsVO ;
37- import com .cloud .storage .dao .VolumeDao ;
38- import com .cloud .storage .dao .VolumeDetailsDao ;
39- import com .cloud .utils .Pair ;
40- import com .cloud .utils .exception .CloudRuntimeException ;
21+ import java .util .ArrayList ;
22+ import java .util .HashMap ;
23+ import java .util .List ;
24+ import java .util .Map ;
25+
26+ import javax .inject .Inject ;
27+
4128import org .apache .cloudstack .engine .subsystem .api .storage .ChapInfo ;
4229import org .apache .cloudstack .engine .subsystem .api .storage .CopyCommandResult ;
4330import org .apache .cloudstack .engine .subsystem .api .storage .CreateCmdResult ;
6653import org .apache .cloudstack .storage .service .model .CloudStackVolume ;
6754import org .apache .cloudstack .storage .service .model .ProtocolType ;
6855import org .apache .cloudstack .storage .to .SnapshotObjectTO ;
56+ import org .apache .cloudstack .storage .utils .OntapStorageConstants ;
6957import org .apache .cloudstack .storage .utils .OntapStorageUtils ;
7058import org .apache .commons .lang3 .StringUtils ;
7159import org .apache .logging .log4j .LogManager ;
7260import org .apache .logging .log4j .Logger ;
7361import org .jetbrains .annotations .Nullable ;
7462
75- import javax .inject .Inject ;
76- import java .util .ArrayList ;
77- import java .util .HashMap ;
78- import java .util .List ;
79- import java .util .Map ;
63+ import com .cloud .agent .api .Answer ;
64+ import com .cloud .agent .api .to .DataObjectType ;
65+ import com .cloud .agent .api .to .DataStoreTO ;
66+ import com .cloud .agent .api .to .DataTO ;
67+ import com .cloud .exception .InvalidParameterValueException ;
68+ import com .cloud .exception .StorageConflictException ;
69+ import com .cloud .exception .StorageUnavailableException ;
70+ import com .cloud .host .Host ;
71+ import com .cloud .host .HostVO ;
72+ import com .cloud .storage .ScopeType ;
73+ import com .cloud .storage .Storage ;
74+ import com .cloud .storage .StorageManager ;
75+ import com .cloud .storage .StoragePool ;
76+ import com .cloud .storage .StoragePoolHostVO ;
77+ import com .cloud .storage .Volume ;
78+ import com .cloud .storage .VolumeDetailVO ;
79+ import com .cloud .storage .VolumeVO ;
80+ import com .cloud .storage .dao .SnapshotDetailsDao ;
81+ import com .cloud .storage .dao .SnapshotDetailsVO ;
82+ import com .cloud .storage .dao .VolumeDao ;
83+ import com .cloud .storage .dao .VolumeDetailsDao ;
84+ import com .cloud .utils .Pair ;
85+ import com .cloud .utils .exception .CloudRuntimeException ;
8086
8187/**
8288 * Primary datastore driver for NetApp ONTAP storage systems.
@@ -91,6 +97,7 @@ public class OntapPrimaryDatastoreDriver implements PrimaryDataStoreDriver {
9197 @ Inject private VolumeDao volumeDao ;
9298 @ Inject private VolumeDetailsDao volumeDetailsDao ;
9399 @ Inject private SnapshotDetailsDao snapshotDetailsDao ;
100+ @ Inject private StorageManager storageManager ;
94101
95102 @ Override
96103 public Map <String , String > getCapabilities () {
@@ -392,8 +399,9 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
392399 // Only retrieve LUN name for iSCSI volumes
393400 grantAccessIscsi (host , volumeVO , details , svmName , storagePool );
394401 } else if (ProtocolType .NFS3 .name ().equalsIgnoreCase (details .get (OntapStorageConstants .PROTOCOL ))) {
395- // For NFS, no access grant needed - file is accessible via mount
396- logger .debug ("grantAccess: NFS volume [{}], no igroup mapping required" , volumeVO .getUuid ());
402+ // For NFS, ensure export policy has host rule and host is connected to pool.
403+ ensureNfsHostAccess (host , storagePool , details );
404+ logger .debug ("grantAccess: NFS volume [{}], ensured host access to storage pool [{}]" , volumeVO .getUuid (), storagePool .getId ());
397405 return true ;
398406 }
399407 volumeVO .setPoolType (storagePool .getPoolType ());
@@ -410,6 +418,43 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
410418 }
411419 }
412420
421+ private void ensureNfsHostAccess (Host host , StoragePoolVO storagePool , Map <String , String > details ) {
422+ boolean hostConnectedToPool = false ;
423+ List <StoragePoolHostVO > connectedPools = storageManager .findStoragePoolsConnectedToHost (host .getId ());
424+ if (connectedPools != null ) {
425+ for (StoragePoolHostVO connectedPoolRef : connectedPools ) {
426+ if (connectedPoolRef .getPoolId () == storagePool .getId ()) {
427+ hostConnectedToPool = true ;
428+ break ;
429+ }
430+ }
431+ }
432+
433+ if (!hostConnectedToPool ) {
434+ try {
435+ logger .info ("grantAccess: Host [{}] is not connected to NFS pool [{}], reconnecting host to pool" , host .getId (), storagePool .getId ());
436+ boolean connected = storageManager .connectHostToSharedPool (host , storagePool .getId ());
437+ if (!connected ) {
438+ throw new CloudRuntimeException ("Failed to connect host " + host .getId () + " to NFS pool " + storagePool .getId ());
439+ }
440+ } catch (StorageUnavailableException | StorageConflictException e ) {
441+ throw new CloudRuntimeException ("Unable to connect host " + host .getId () + " to NFS pool " + storagePool .getId (), e );
442+ }
443+ return ;
444+ }
445+
446+ if (!(host instanceof HostVO )) {
447+ throw new CloudRuntimeException ("Host object is not of type HostVO for host id: " + host .getId ());
448+ }
449+
450+ AccessGroup accessGroup = new AccessGroup ();
451+ accessGroup .setStoragePoolId (storagePool .getId ());
452+ accessGroup .setHostsToConnect (List .of ((HostVO ) host ));
453+
454+ StorageStrategy strategy = OntapStorageUtils .getStrategyByStoragePoolDetails (details );
455+ strategy .updateAccessGroup (accessGroup );
456+ }
457+
413458 private void grantAccessIscsi (Host host , VolumeVO volumeVO , Map <String , String > details , String svmName , StoragePoolVO storagePool ) {
414459 String cloudStackVolumeName = volumeDetailsDao .findDetail (volumeVO .getId (), OntapStorageConstants .LUN_DOT_NAME ).getValue ();
415460 UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy ) OntapStorageUtils .getStrategyByStoragePoolDetails (details );
0 commit comments