2121
2222
2323import com .cloud .agent .api .StoragePoolInfo ;
24+ import com .cloud .dc .ClusterVO ;
25+ import com .cloud .dc .dao .ClusterDao ;
26+ import com .cloud .host .HostVO ;
2427import com .cloud .hypervisor .Hypervisor ;
28+ import com .cloud .resource .ResourceManager ;
29+ import com .cloud .storage .Storage ;
30+ import com .cloud .storage .StorageManager ;
2531import com .cloud .storage .StoragePool ;
32+ import com .google .common .base .Preconditions ;
2633import org .apache .cloudstack .engine .subsystem .api .storage .ClusterScope ;
2734import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
2835import org .apache .cloudstack .engine .subsystem .api .storage .HostScope ;
36+ import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreInfo ;
2937import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreLifeCycle ;
38+ import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreParameters ;
3039import org .apache .cloudstack .engine .subsystem .api .storage .ZoneScope ;
40+ import org .apache .cloudstack .storage .datastore .lifecycle .BasePrimaryDataStoreLifeCycleImpl ;
41+ import org .apache .cloudstack .storage .ontap .StorageProviderManager ;
42+ import org .apache .cloudstack .storage .volume .datastore .PrimaryDataStoreHelper ;
3143import org .apache .logging .log4j .LogManager ;
3244import org .apache .logging .log4j .Logger ;
33- import java .util .Map ;
3445
35- public class OntapPrimaryDatastoreLifecycle implements PrimaryDataStoreLifeCycle {
46+ import javax .inject .Inject ;
47+ import java .util .ArrayList ;
48+ import java .util .List ;
49+ import java .util .Map ;
50+ import java .util .UUID ;
3651
52+ public class OntapPrimaryDatastoreLifecycle extends BasePrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
53+ @ Inject private ClusterDao _clusterDao ;
54+ @ Inject private StorageManager _storageMgr ;
55+ @ Inject private ResourceManager _resourceMgr ;
56+ @ Inject private PrimaryDataStoreHelper _dataStoreHelper ;
3757 private static final Logger s_logger = (Logger )LogManager .getLogger (OntapPrimaryDatastoreLifecycle .class );
3858
3959 /**
@@ -43,14 +63,91 @@ public class OntapPrimaryDatastoreLifecycle implements PrimaryDataStoreLifeCycle
4363 */
4464 @ Override
4565 public DataStore initialize (Map <String , Object > dsInfos ) {
46-
47- return null ;
48-
66+ String url = (String ) dsInfos .get ("url" );
67+ Long zoneId = (Long ) dsInfos .get ("zoneId" );
68+ Long podId = (Long )dsInfos .get ("podId" );
69+ Long clusterId = (Long )dsInfos .get ("clusterId" );
70+ String storagePoolName = (String )dsInfos .get ("name" );
71+ String providerName = (String )dsInfos .get ("providerName" );
72+ String tags = (String )dsInfos .get ("tags" );
73+ Boolean isTagARule = (Boolean ) dsInfos .get ("isTagARule" );
74+ String protocol = (String ) dsInfos .get ("protocol" ); // TODO: Figure out the proper key for protocol
75+ // Additional details requested for ONTAP primary storage pool creation
76+ @ SuppressWarnings ("unchecked" )
77+ Map <String , String > details = (Map <String , String >)dsInfos .get ("details" );
78+ // Validations
79+ if (podId != null && clusterId == null ) {
80+ s_logger .error ("Cluster Id is null, cannot create primary storage" );
81+ return null ;
82+ } else if (podId == null && clusterId != null ) {
83+ s_logger .error ("Pod Id is null, cannot create primary storage" );
84+ return null ;
85+ }
86+
87+ if (podId == null && clusterId == null ) {
88+ if (zoneId != null ) {
89+ s_logger .info ("Both Pod Id and Cluster Id are null, Primary storage pool will be associated with a Zone" );
90+ } else {
91+ s_logger .error ("Pod Id, Cluster Id and Zone Id are all null, cannot create primary storage" );
92+ return null ;
93+ }
94+ }
95+
96+ PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters ();
97+ if (clusterId != null ) {
98+ ClusterVO clusterVO = _clusterDao .findById (clusterId );
99+ Preconditions .checkNotNull (clusterVO , "Unable to locate the specified cluster" );
100+ parameters .setHypervisorType (clusterVO .getHypervisorType ());
101+ }
102+ else {
103+ parameters .setHypervisorType (Hypervisor .HypervisorType .Any );
104+ }
105+
106+ // Validate the ONTAP details
107+ StorageProviderManager storageProviderManager = new StorageProviderManager (details , protocol );
108+ boolean isValid = storageProviderManager .connect (details );
109+ //TODO: Use the return value to decide if we should proceed with pool creation
110+
111+ if (isValid ) {
112+ String volumeName = storagePoolName + "_vol" ; //TODO: Figure out a better naming convention
113+ storageProviderManager .createVolume (volumeName , Long .parseLong (details .get ("size" ))); // TODO: size should be in bytes, so see if conversion is needed
114+ // TODO: The volume name should be stored against the StoragePool name/id in the DB
115+ } else {
116+ s_logger .error ("ONTAP details validation failed, cannot create primary storage" );
117+ return null ; // TODO: Figure out a better exception handling mechanism
118+ }
119+
120+ parameters .setTags (tags );
121+ parameters .setIsTagARule (isTagARule );
122+ parameters .setDetails (details );
123+ parameters .setType (Storage .StoragePoolType .Iscsi );
124+ parameters .setUuid (UUID .randomUUID ().toString ());
125+ parameters .setZoneId (zoneId );
126+ parameters .setPodId (podId );
127+ parameters .setClusterId (clusterId );
128+ parameters .setName (storagePoolName );
129+ parameters .setProviderName (providerName );
130+ parameters .setManaged (true );
131+
132+ return _dataStoreHelper .createPrimaryDataStore (parameters );
49133 }
50134
51135 @ Override
52- public boolean attachCluster (DataStore store , ClusterScope scope ) {
53- return false ;
136+ public boolean attachCluster (DataStore dataStore , ClusterScope scope ) {
137+ PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo )dataStore ;
138+ List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primarystore );
139+
140+ logger .debug (String .format ("Attaching the pool to each of the hosts %s in the cluster: %s" , hostsToConnect , primarystore .getClusterId ()));
141+ for (HostVO host : hostsToConnect ) {
142+ // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
143+ try {
144+ _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
145+ } catch (Exception e ) {
146+ logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
147+ }
148+ }
149+ _dataStoreHelper .attachCluster (dataStore );
150+ return true ;
54151 }
55152
56153 @ Override
@@ -60,7 +157,24 @@ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo exis
60157
61158 @ Override
62159 public boolean attachZone (DataStore dataStore , ZoneScope scope , Hypervisor .HypervisorType hypervisorType ) {
63- return false ;
160+ List <HostVO > hostsToConnect = new ArrayList <>();
161+ Hypervisor .HypervisorType [] hypervisorTypes = {Hypervisor .HypervisorType .XenServer , Hypervisor .HypervisorType .VMware , Hypervisor .HypervisorType .KVM };
162+
163+ for (Hypervisor .HypervisorType type : hypervisorTypes ) {
164+ hostsToConnect .addAll (_resourceMgr .getEligibleUpAndEnabledHostsInZoneForStorageConnection (dataStore , scope .getScopeId (), type ));
165+ }
166+
167+ logger .debug (String .format ("In createPool. Attaching the pool to each of the hosts in %s." , hostsToConnect ));
168+ for (HostVO host : hostsToConnect ) {
169+ // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
170+ try {
171+ _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
172+ } catch (Exception e ) {
173+ logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
174+ }
175+ }
176+ _dataStoreHelper .attachZone (dataStore );
177+ return true ;
64178 }
65179
66180 @ Override
0 commit comments