2323import com .cloud .agent .api .StoragePoolInfo ;
2424import com .cloud .dc .ClusterVO ;
2525import com .cloud .dc .dao .ClusterDao ;
26+ import com .cloud .exception .InvalidParameterValueException ;
2627import com .cloud .host .HostVO ;
2728import com .cloud .hypervisor .Hypervisor ;
2829import com .cloud .resource .ResourceManager ;
3839import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreLifeCycle ;
3940import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreParameters ;
4041import org .apache .cloudstack .engine .subsystem .api .storage .ZoneScope ;
42+ import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
43+ import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
44+ import org .apache .cloudstack .storage .datastore .db .StoragePoolDetailsDao ;
4145import org .apache .cloudstack .storage .datastore .lifecycle .BasePrimaryDataStoreLifeCycleImpl ;
4246import org .apache .cloudstack .storage .feign .model .OntapStorage ;
4347import org .apache .cloudstack .storage .provider .StorageProviderFactory ;
4448import org .apache .cloudstack .storage .service .StorageStrategy ;
49+ import org .apache .cloudstack .storage .service .model .AccessGroup ;
4550import org .apache .cloudstack .storage .service .model .ProtocolType ;
4651import org .apache .cloudstack .storage .utils .Constants ;
52+ import org .apache .cloudstack .storage .utils .Utility ;
4753import org .apache .cloudstack .storage .volume .datastore .PrimaryDataStoreHelper ;
4854import org .apache .logging .log4j .LogManager ;
4955import org .apache .logging .log4j .Logger ;
5056
5157import javax .inject .Inject ;
58+ import java .util .ArrayList ;
5259import java .util .List ;
5360import java .util .Map ;
5461import java .util .UUID ;
@@ -58,6 +65,8 @@ public class OntapPrimaryDatastoreLifecycle extends BasePrimaryDataStoreLifeCycl
5865 @ Inject private StorageManager _storageMgr ;
5966 @ Inject private ResourceManager _resourceMgr ;
6067 @ Inject private PrimaryDataStoreHelper _dataStoreHelper ;
68+ @ Inject private PrimaryDataStoreDao storagePoolDao ;
69+ @ Inject private StoragePoolDetailsDao storagePoolDetailsDao ;
6170 private static final Logger s_logger = LogManager .getLogger (OntapPrimaryDatastoreLifecycle .class );
6271
6372 /**
@@ -209,16 +218,42 @@ public DataStore initialize(Map<String, Object> dsInfos) {
209218 @ Override
210219 public boolean attachCluster (DataStore dataStore , ClusterScope scope ) {
211220 logger .debug ("In attachCluster for ONTAP primary storage" );
212- PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo )dataStore ;
213- List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primarystore );
221+ if (dataStore == null ) {
222+ throw new InvalidParameterValueException ("attachCluster: dataStore should not be null" );
223+ }
224+ if (scope == null ) {
225+ throw new InvalidParameterValueException ("attachCluster: scope should not be null" );
226+ }
227+ List <String > hostsIdentifier = new ArrayList <>();
228+ StoragePoolVO storagePool = storagePoolDao .findById (dataStore .getId ());
229+ if (storagePool == null ) {
230+ s_logger .error ("attachCluster : Storage Pool not found for id: " + dataStore .getId ());
231+ throw new CloudRuntimeException ("attachCluster : Storage Pool not found for id: " + dataStore .getId ());
232+ }
233+ PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo )dataStore ;
234+ List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primaryStore );
235+ // TODO- need to check if no host to connect then throw exception or just continue
236+ logger .debug ("attachCluster: Eligible Up and Enabled hosts: {} in cluster {}" , hostsToConnect , primaryStore .getClusterId ());
214237
215- logger .debug (String .format ("Attaching the pool to each of the hosts %s in the cluster: %s" , hostsToConnect , primarystore .getClusterId ()));
238+ Map <String , String > details = primaryStore .getDetails ();
239+ StorageStrategy strategy = Utility .getStrategyByStoragePoolDetails (details );
240+ ProtocolType protocol = ProtocolType .valueOf (details .get (Constants .PROTOCOL ));
241+ //TODO- Check if we have to handle heterogeneous host within the cluster
242+ if (!isProtocolSupportedByAllHosts (hostsToConnect , protocol , hostsIdentifier )) {
243+ s_logger .error ("attachCluster: Not all hosts in the cluster support the protocol: " + protocol .name ());
244+ throw new CloudRuntimeException ("attachCluster: Not all hosts in the cluster support the protocol: " + protocol .name ());
245+ }
246+ //TODO - check if no host to connect then also need to create access group without initiators
247+ if (hostsIdentifier != null && hostsIdentifier .size () > 0 ) {
248+ AccessGroup accessGroupRequest = Utility .createAccessGroupRequestByProtocol (storagePool , scope .getScopeId (), details , hostsIdentifier );
249+ strategy .createAccessGroup (accessGroupRequest );
250+ }
251+ logger .debug ("attachCluster: Attaching the pool to each of the host in the cluster: {}" , primaryStore .getClusterId ());
216252 for (HostVO host : hostsToConnect ) {
217- // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
218253 try {
219254 _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
220255 } catch (Exception e ) {
221- logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
256+ logger .warn ("attachCluster: Unable to establish a connection between " + host + " and " + dataStore , e );
222257 }
223258 }
224259 _dataStoreHelper .attachCluster (dataStore );
@@ -233,11 +268,35 @@ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo exis
233268 @ Override
234269 public boolean attachZone (DataStore dataStore , ZoneScope scope , Hypervisor .HypervisorType hypervisorType ) {
235270 logger .debug ("In attachZone for ONTAP primary storage" );
271+ if (dataStore == null ) {
272+ throw new InvalidParameterValueException ("attachZone: dataStore should not be null" );
273+ }
274+ if (scope == null ) {
275+ throw new InvalidParameterValueException ("attachZone: scope should not be null" );
276+ }
277+ List <String > hostsIdentifier = new ArrayList <>();
278+ StoragePoolVO storagePool = storagePoolDao .findById (dataStore .getId ());
279+ if (storagePool == null ) {
280+ s_logger .error ("attachZone : Storage Pool not found for id: " + dataStore .getId ());
281+ throw new CloudRuntimeException ("attachZone : Storage Pool not found for id: " + dataStore .getId ());
282+ }
236283 List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInZoneForStorageConnection (dataStore , scope .getScopeId (), Hypervisor .HypervisorType .KVM );
284+ // TODO- need to check if no host to connect then throw exception or just continue
285+ logger .debug ("attachZone: Eligible Up and Enabled hosts: {}" , hostsToConnect );
237286
238- logger .debug (String .format ("In createPool. Attaching the pool to each of the hosts in %s." , hostsToConnect ));
287+ Map <String , String > details = storagePoolDetailsDao .listDetailsKeyPairs (dataStore .getId ());
288+ StorageStrategy strategy = Utility .getStrategyByStoragePoolDetails (details );
289+ ProtocolType protocol = ProtocolType .valueOf (details .get (Constants .PROTOCOL ));
290+ //TODO- Check if we have to handle heterogeneous host within the zone
291+ if (!isProtocolSupportedByAllHosts (hostsToConnect , protocol , hostsIdentifier )) {
292+ s_logger .error ("attachZone: Not all hosts in the cluster support the protocol: " + protocol .name ());
293+ throw new CloudRuntimeException ("attachZone: Not all hosts in the zone support the protocol: " + protocol .name ());
294+ }
295+ if (hostsIdentifier != null && !hostsIdentifier .isEmpty ()) {
296+ AccessGroup accessGroupRequest = Utility .createAccessGroupRequestByProtocol (storagePool , scope .getScopeId (), details , hostsIdentifier );
297+ strategy .createAccessGroup (accessGroupRequest );
298+ }
239299 for (HostVO host : hostsToConnect ) {
240- // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
241300 try {
242301 _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
243302 } catch (Exception e ) {
@@ -248,6 +307,24 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper
248307 return true ;
249308 }
250309
310+ private boolean isProtocolSupportedByAllHosts (List <HostVO > hosts , ProtocolType protocolType , List <String > hostIdentifiers ) {
311+ switch (protocolType ) {
312+ case ISCSI :
313+ String protocolPrefix = Constants .IQN ;
314+ for (HostVO host : hosts ) {
315+ if (host == null || host .getStorageUrl () == null || host .getStorageUrl ().trim ().isEmpty ()
316+ || !host .getStorageUrl ().startsWith (protocolPrefix )) {
317+ return false ;
318+ }
319+ hostIdentifiers .add (host .getStorageUrl ());
320+ }
321+ break ;
322+ default :
323+ throw new CloudRuntimeException ("isProtocolSupportedByAllHosts : Unsupported protocol: " + protocolType .name ());
324+ }
325+ return true ;
326+ }
327+
251328 @ Override
252329 public boolean maintain (DataStore store ) {
253330 return true ;
0 commit comments