22
33
44import com .cloud .agent .api .StoragePoolInfo ;
5+ import com .cloud .dc .ClusterVO ;
6+ import com .cloud .dc .dao .ClusterDao ;
7+ import com .cloud .host .HostVO ;
58import com .cloud .hypervisor .Hypervisor ;
9+ import com .cloud .resource .ResourceManager ;
10+ import com .cloud .storage .Storage ;
11+ import com .cloud .storage .StorageManager ;
612import com .cloud .storage .StoragePool ;
13+ import com .google .common .base .Preconditions ;
714import org .apache .cloudstack .engine .subsystem .api .storage .ClusterScope ;
815import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
916import org .apache .cloudstack .engine .subsystem .api .storage .HostScope ;
17+ import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreInfo ;
1018import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreLifeCycle ;
19+ import org .apache .cloudstack .engine .subsystem .api .storage .PrimaryDataStoreParameters ;
1120import org .apache .cloudstack .engine .subsystem .api .storage .ZoneScope ;
21+ import org .apache .cloudstack .storage .datastore .lifecycle .BasePrimaryDataStoreLifeCycleImpl ;
22+ import org .apache .cloudstack .storage .ontap .StorageProviderManager ;
23+ import org .apache .cloudstack .storage .volume .datastore .PrimaryDataStoreHelper ;
1224import org .apache .logging .log4j .LogManager ;
1325import org .apache .logging .log4j .Logger ;
14- import java .util .Map ;
1526
16- public class OntapPrimaryDatastoreLifecycle implements PrimaryDataStoreLifeCycle {
27+ import javax .inject .Inject ;
28+ import java .util .ArrayList ;
29+ import java .util .List ;
30+ import java .util .Map ;
31+ import java .util .UUID ;
1732
33+ public class OntapPrimaryDatastoreLifecycle extends BasePrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
34+ @ Inject private ClusterDao _clusterDao ;
35+ @ Inject private StorageManager _storageMgr ;
36+ @ Inject private ResourceManager _resourceMgr ;
37+ @ Inject private PrimaryDataStoreHelper _dataStoreHelper ;
1838 private static final Logger s_logger = (Logger )LogManager .getLogger (OntapPrimaryDatastoreLifecycle .class );
1939
2040 /**
@@ -24,14 +44,91 @@ public class OntapPrimaryDatastoreLifecycle implements PrimaryDataStoreLifeCycle
2444 */
2545 @ Override
2646 public DataStore initialize (Map <String , Object > dsInfos ) {
27-
28- return null ;
29-
47+ String url = (String ) dsInfos .get ("url" );
48+ Long zoneId = (Long ) dsInfos .get ("zoneId" );
49+ Long podId = (Long )dsInfos .get ("podId" );
50+ Long clusterId = (Long )dsInfos .get ("clusterId" );
51+ String storagePoolName = (String )dsInfos .get ("name" );
52+ String providerName = (String )dsInfos .get ("providerName" );
53+ String tags = (String )dsInfos .get ("tags" );
54+ Boolean isTagARule = (Boolean ) dsInfos .get ("isTagARule" );
55+ String protocol = (String ) dsInfos .get ("protocol" ); // TODO: Figure out the proper key for protocol
56+ // Additional details requested for ONTAP primary storage pool creation
57+ @ SuppressWarnings ("unchecked" )
58+ Map <String , String > details = (Map <String , String >)dsInfos .get ("details" );
59+ // Validations
60+ if (podId != null && clusterId == null ) {
61+ s_logger .error ("Cluster Id is null, cannot create primary storage" );
62+ return null ;
63+ } else if (podId == null && clusterId != null ) {
64+ s_logger .error ("Pod Id is null, cannot create primary storage" );
65+ return null ;
66+ }
67+
68+ if (podId == null && clusterId == null ) {
69+ if (zoneId != null ) {
70+ s_logger .info ("Both Pod Id and Cluster Id are null, Primary storage pool will be associated with a Zone" );
71+ } else {
72+ s_logger .error ("Pod Id, Cluster Id and Zone Id are all null, cannot create primary storage" );
73+ return null ;
74+ }
75+ }
76+
77+ PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters ();
78+ if (clusterId != null ) {
79+ ClusterVO clusterVO = _clusterDao .findById (clusterId );
80+ Preconditions .checkNotNull (clusterVO , "Unable to locate the specified cluster" );
81+ parameters .setHypervisorType (clusterVO .getHypervisorType ());
82+ }
83+ else {
84+ parameters .setHypervisorType (Hypervisor .HypervisorType .Any );
85+ }
86+
87+ // Validate the ONTAP details
88+ StorageProviderManager storageProviderManager = new StorageProviderManager (details , protocol );
89+ boolean isValid = storageProviderManager .connect (details );
90+ //TODO: Use the return value to decide if we should proceed with pool creation
91+
92+ if (isValid ) {
93+ String volumeName = storagePoolName + "_vol" ; //TODO: Figure out a better naming convention
94+ storageProviderManager .createVolume (volumeName , Long .parseLong (details .get ("size" ))); // TODO: size should be in bytes, so see if conversion is needed
95+ // TODO: The volume name should be stored against the StoragePool name/id in the DB
96+ } else {
97+ s_logger .error ("ONTAP details validation failed, cannot create primary storage" );
98+ return null ; // TODO: Figure out a better exception handling mechanism
99+ }
100+
101+ parameters .setTags (tags );
102+ parameters .setIsTagARule (isTagARule );
103+ parameters .setDetails (details );
104+ parameters .setType (Storage .StoragePoolType .Iscsi );
105+ parameters .setUuid (UUID .randomUUID ().toString ());
106+ parameters .setZoneId (zoneId );
107+ parameters .setPodId (podId );
108+ parameters .setClusterId (clusterId );
109+ parameters .setName (storagePoolName );
110+ parameters .setProviderName (providerName );
111+ parameters .setManaged (true );
112+
113+ return _dataStoreHelper .createPrimaryDataStore (parameters );
30114 }
31115
32116 @ Override
33- public boolean attachCluster (DataStore store , ClusterScope scope ) {
34- return false ;
117+ public boolean attachCluster (DataStore dataStore , ClusterScope scope ) {
118+ PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo )dataStore ;
119+ List <HostVO > hostsToConnect = _resourceMgr .getEligibleUpAndEnabledHostsInClusterForStorageConnection (primarystore );
120+
121+ logger .debug (String .format ("Attaching the pool to each of the hosts %s in the cluster: %s" , hostsToConnect , primarystore .getClusterId ()));
122+ for (HostVO host : hostsToConnect ) {
123+ // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
124+ try {
125+ _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
126+ } catch (Exception e ) {
127+ logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
128+ }
129+ }
130+ _dataStoreHelper .attachCluster (dataStore );
131+ return true ;
35132 }
36133
37134 @ Override
@@ -41,7 +138,24 @@ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo exis
41138
42139 @ Override
43140 public boolean attachZone (DataStore dataStore , ZoneScope scope , Hypervisor .HypervisorType hypervisorType ) {
44- return false ;
141+ List <HostVO > hostsToConnect = new ArrayList <>();
142+ Hypervisor .HypervisorType [] hypervisorTypes = {Hypervisor .HypervisorType .XenServer , Hypervisor .HypervisorType .VMware , Hypervisor .HypervisorType .KVM };
143+
144+ for (Hypervisor .HypervisorType type : hypervisorTypes ) {
145+ hostsToConnect .addAll (_resourceMgr .getEligibleUpAndEnabledHostsInZoneForStorageConnection (dataStore , scope .getScopeId (), type ));
146+ }
147+
148+ logger .debug (String .format ("In createPool. Attaching the pool to each of the hosts in %s." , hostsToConnect ));
149+ for (HostVO host : hostsToConnect ) {
150+ // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster
151+ try {
152+ _storageMgr .connectHostToSharedPool (host , dataStore .getId ());
153+ } catch (Exception e ) {
154+ logger .warn ("Unable to establish a connection between " + host + " and " + dataStore , e );
155+ }
156+ }
157+ _dataStoreHelper .attachZone (dataStore );
158+ return true ;
45159 }
46160
47161 @ Override
0 commit comments