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 .Set ;
@@ -59,6 +66,8 @@ public class OntapPrimaryDatastoreLifecycle extends BasePrimaryDataStoreLifeCycl
5966 @ Inject private StorageManager _storageMgr ;
6067 @ Inject private ResourceManager _resourceMgr ;
6168 @ Inject private PrimaryDataStoreHelper _dataStoreHelper ;
69+ @ Inject private PrimaryDataStoreDao storagePoolDao ;
70+ @ Inject private StoragePoolDetailsDao storagePoolDetailsDao ;
6271 private static final Logger s_logger = LogManager .getLogger (OntapPrimaryDatastoreLifecycle .class );
6372
6473 // ONTAP minimum volume size is 1.56 GB (1677721600 bytes)
@@ -241,16 +250,42 @@ public DataStore initialize(Map<String, Object> dsInfos) {
241250 @ Override
242251 public boolean attachCluster (DataStore dataStore , ClusterScope scope ) {
243252 logger .debug ("In attachCluster for ONTAP primary storage" );
244- PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo )dataStore ;
245- List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primarystore );
253+ if (dataStore == null ) {
254+ throw new InvalidParameterValueException ("attachCluster: dataStore should not be null" );
255+ }
256+ if (scope == null ) {
257+ throw new InvalidParameterValueException ("attachCluster: scope should not be null" );
258+ }
259+ List <String > hostsIdentifier = new ArrayList <>();
260+ StoragePoolVO storagePool = storagePoolDao .findById (dataStore .getId ());
261+ if (storagePool == null ) {
262+ s_logger .error ("attachCluster : Storage Pool not found for id: " + dataStore .getId ());
263+ throw new CloudRuntimeException ("attachCluster : Storage Pool not found for id: " + dataStore .getId ());
264+ }
265+ PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo )dataStore ;
266+ List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primaryStore );
267+ // TODO- need to check if no host to connect then throw exception or just continue
268+ logger .debug ("attachCluster: Eligible Up and Enabled hosts: {} in cluster {}" , hostsToConnect , primaryStore .getClusterId ());
246269
247- logger .debug (String .format ("Attaching the pool to each of the hosts %s in the cluster: %s" , hostsToConnect , primarystore .getClusterId ()));
270+ Map <String , String > details = primaryStore .getDetails ();
271+ StorageStrategy strategy = Utility .getStrategyByStoragePoolDetails (details );
272+ ProtocolType protocol = ProtocolType .valueOf (details .get (Constants .PROTOCOL ));
273+ //TODO- Check if we have to handle heterogeneous host within the cluster
274+ if (!isProtocolSupportedByAllHosts (hostsToConnect , protocol , hostsIdentifier )) {
275+ s_logger .error ("attachCluster: Not all hosts in the cluster support the protocol: " + protocol .name ());
276+ throw new CloudRuntimeException ("attachCluster: Not all hosts in the cluster support the protocol: " + protocol .name ());
277+ }
278+ //TODO - check if no host to connect then also need to create access group without initiators
279+ if (hostsIdentifier != null && hostsIdentifier .size () > 0 ) {
280+ AccessGroup accessGroupRequest = Utility .createAccessGroupRequestByProtocol (storagePool , scope .getScopeId (), details , hostsIdentifier );
281+ strategy .createAccessGroup (accessGroupRequest );
282+ }
283+ logger .debug ("attachCluster: Attaching the pool to each of the host in the cluster: {}" , primaryStore .getClusterId ());
248284 for (HostVO host : hostsToConnect ) {
249- // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
250285 try {
251286 _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
252287 } catch (Exception e ) {
253- logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
288+ logger .warn ("attachCluster: Unable to establish a connection between " + host + " and " + dataStore , e );
254289 }
255290 }
256291 _dataStoreHelper .attachCluster (dataStore );
@@ -265,11 +300,35 @@ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo exis
265300 @ Override
266301 public boolean attachZone (DataStore dataStore , ZoneScope scope , Hypervisor .HypervisorType hypervisorType ) {
267302 logger .debug ("In attachZone for ONTAP primary storage" );
303+ if (dataStore == null ) {
304+ throw new InvalidParameterValueException ("attachZone: dataStore should not be null" );
305+ }
306+ if (scope == null ) {
307+ throw new InvalidParameterValueException ("attachZone: scope should not be null" );
308+ }
309+ List <String > hostsIdentifier = new ArrayList <>();
310+ StoragePoolVO storagePool = storagePoolDao .findById (dataStore .getId ());
311+ if (storagePool == null ) {
312+ s_logger .error ("attachZone : Storage Pool not found for id: " + dataStore .getId ());
313+ throw new CloudRuntimeException ("attachZone : Storage Pool not found for id: " + dataStore .getId ());
314+ }
268315 List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInZoneForStorageConnection (dataStore , scope .getScopeId (), Hypervisor .HypervisorType .KVM );
316+ // TODO- need to check if no host to connect then throw exception or just continue
317+ logger .debug ("attachZone: Eligible Up and Enabled hosts: {}" , hostsToConnect );
269318
270- logger .debug (String .format ("In createPool. Attaching the pool to each of the hosts in %s." , hostsToConnect ));
319+ Map <String , String > details = storagePoolDetailsDao .listDetailsKeyPairs (dataStore .getId ());
320+ StorageStrategy strategy = Utility .getStrategyByStoragePoolDetails (details );
321+ ProtocolType protocol = ProtocolType .valueOf (details .get (Constants .PROTOCOL ));
322+ //TODO- Check if we have to handle heterogeneous host within the zone
323+ if (!isProtocolSupportedByAllHosts (hostsToConnect , protocol , hostsIdentifier )) {
324+ s_logger .error ("attachZone: Not all hosts in the cluster support the protocol: " + protocol .name ());
325+ throw new CloudRuntimeException ("attachZone: Not all hosts in the zone support the protocol: " + protocol .name ());
326+ }
327+ if (hostsIdentifier != null && !hostsIdentifier .isEmpty ()) {
328+ AccessGroup accessGroupRequest = Utility .createAccessGroupRequestByProtocol (storagePool , scope .getScopeId (), details , hostsIdentifier );
329+ strategy .createAccessGroup (accessGroupRequest );
330+ }
271331 for (HostVO host : hostsToConnect ) {
272- // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
273332 try {
274333 _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
275334 } catch (Exception e ) {
@@ -280,6 +339,24 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper
280339 return true ;
281340 }
282341
342+ private boolean isProtocolSupportedByAllHosts (List <HostVO > hosts , ProtocolType protocolType , List <String > hostIdentifiers ) {
343+ switch (protocolType ) {
344+ case ISCSI :
345+ String protocolPrefix = Constants .IQN ;
346+ for (HostVO host : hosts ) {
347+ if (host == null || host .getStorageUrl () == null || host .getStorageUrl ().trim ().isEmpty ()
348+ || !host .getStorageUrl ().startsWith (protocolPrefix )) {
349+ return false ;
350+ }
351+ hostIdentifiers .add (host .getStorageUrl ());
352+ }
353+ break ;
354+ default :
355+ throw new CloudRuntimeException ("isProtocolSupportedByAllHosts : Unsupported protocol: " + protocolType .name ());
356+ }
357+ return true ;
358+ }
359+
283360 @ Override
284361 public boolean maintain (DataStore store ) {
285362 return true ;
0 commit comments