Skip to content

Commit b6be98e

Browse files
Gupta, SuryaGupta, Surya
authored andcommitted
CSTACKEX-37 GrantAccess
1 parent b855306 commit b6be98e

8 files changed

Lines changed: 507 additions & 93 deletions

File tree

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java

Lines changed: 163 additions & 39 deletions
Large diffs are not rendered by default.

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/feign/client/SANFeignClient.java

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.cloudstack.storage.feign.client;
2020

21+
import feign.QueryMap;
2122
import org.apache.cloudstack.storage.feign.model.Igroup;
2223
import org.apache.cloudstack.storage.feign.model.Lun;
2324
import org.apache.cloudstack.storage.feign.model.LunMap;
@@ -26,6 +27,7 @@
2627
import feign.Param;
2728
import feign.RequestLine;
2829
import java.net.URI;
30+
import java.util.Map;
2931

3032
public interface SANFeignClient {
3133

@@ -53,15 +55,14 @@ OntapResponse<Lun> createLun(@Param("authHeader") String authHeader,
5355
void deleteLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid);
5456

5557
// iGroup Operation APIs
56-
@RequestLine("POST /")
58+
@RequestLine("POST /api/protocols/san/igroups")
5759
@Headers({"Authorization: {authHeader}", "return_records: {returnRecords}"})
5860
OntapResponse<Igroup> createIgroup(@Param("authHeader") String authHeader,
59-
@Param("returnRecords") boolean returnRecords,
60-
@Param("igroupRequest") Igroup igroupRequest);
61+
@Param("returnRecords") boolean returnRecords, Igroup igroupRequest);
6162

62-
@RequestLine("GET /")
63+
@RequestLine("GET /api/protocols/san/igroups")
6364
@Headers({"Authorization: {authHeader}"})
64-
OntapResponse<Igroup> getIgroupResponse(@Param("authHeader") String authHeader, @Param("uuid") String uuid);
65+
OntapResponse<Igroup> getIgroupResponse(@Param("authHeader") String authHeader, @QueryMap Map<String, Object> queryMap);
6566

6667
@RequestLine("GET /{uuid}")
6768
@Headers({"Authorization: {authHeader}"})
@@ -70,26 +71,18 @@ OntapResponse<Igroup> createIgroup(@Param("authHeader") String authHeader,
7071
@RequestLine("DELETE /{uuid}")
7172
@Headers({"Authorization: {authHeader}"})
7273
void deleteIgroup(@Param("baseUri") URI baseUri, @Param("authHeader") String authHeader, @Param("uuid") String uuid);
73-
74-
@RequestLine("POST /{uuid}/igroups")
75-
@Headers({"Authorization: {authHeader}", "return_records: {returnRecords}"})
76-
OntapResponse<Igroup> addNestedIgroups(@Param("authHeader") String authHeader,
77-
@Param("uuid") String uuid,
78-
@Param("igroupNestedRequest") Igroup igroupNestedRequest,
79-
@Param("returnRecords") boolean returnRecords);
80-
8174
// LUN Maps Operation APIs
82-
@RequestLine("POST /")
83-
@Headers({"Authorization: {authHeader}"})
84-
OntapResponse<LunMap> createLunMap(@Param("authHeader") String authHeader, @Param("lunMap") LunMap lunMap);
75+
@RequestLine("POST /api/protocols/san/lun-maps")
76+
@Headers({"Authorization: {authHeader}", "return_records: {returnRecords}"})
77+
OntapResponse<LunMap> createLunMap(@Param("authHeader") String authHeader, @Param("returnRecords") boolean returnRecords, LunMap lunMap);
8578

8679
@RequestLine("GET /")
8780
@Headers({"Authorization: {authHeader}"})
8881
OntapResponse<LunMap> getLunMapResponse(@Param("authHeader") String authHeader);
8982

90-
@RequestLine("DELETE /{lunUuid}/{igroupUuid}")
83+
@RequestLine("DELETE /api/protocols/san/lun-maps/{lunUuid}/{igroupUuid}")
9184
@Headers({"Authorization: {authHeader}"})
9285
void deleteLunMap(@Param("authHeader") String authHeader,
93-
@Param("lunUuid") String lunUuid,
94-
@Param("igroupUuid") String igroupUuid);
86+
@Param("lunUuid") String lunUUID,
87+
@Param("igroupUuid") String igroupUUID);
9588
}

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/lifecycle/OntapPrimaryDatastoreLifecycle.java

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.cloud.agent.api.StoragePoolInfo;
2424
import com.cloud.dc.ClusterVO;
2525
import com.cloud.dc.dao.ClusterDao;
26+
import com.cloud.exception.InvalidParameterValueException;
2627
import com.cloud.host.HostVO;
2728
import com.cloud.hypervisor.Hypervisor;
2829
import com.cloud.resource.ResourceManager;
@@ -38,17 +39,23 @@
3839
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
3940
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
4041
import 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;
4145
import org.apache.cloudstack.storage.datastore.lifecycle.BasePrimaryDataStoreLifeCycleImpl;
4246
import org.apache.cloudstack.storage.feign.model.OntapStorage;
4347
import org.apache.cloudstack.storage.provider.StorageProviderFactory;
4448
import org.apache.cloudstack.storage.service.StorageStrategy;
49+
import org.apache.cloudstack.storage.service.model.AccessGroup;
4550
import org.apache.cloudstack.storage.service.model.ProtocolType;
4651
import org.apache.cloudstack.storage.utils.Constants;
52+
import org.apache.cloudstack.storage.utils.Utility;
4753
import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
4854
import org.apache.logging.log4j.LogManager;
4955
import org.apache.logging.log4j.Logger;
5056

5157
import javax.inject.Inject;
58+
import java.util.ArrayList;
5259
import java.util.List;
5360
import java.util.Map;
5461
import 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;

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,10 @@ public Volume getStorageVolume(Volume volume)
283283
* getLun for iSCSI, FC protocols
284284
* getFile for NFS3.0 and NFS4.1 protocols
285285
* getNameSpace for Nvme/TCP and Nvme/FC protocol
286-
* @param cloudstackVolume the CloudStack volume to retrieve
286+
* @param cloudStackVolumeMap the CloudStack volume to retrieve
287287
* @return the retrieved CloudStackVolume object
288288
*/
289-
abstract CloudStackVolume getCloudStackVolume(CloudStackVolume cloudstackVolume);
289+
abstract public CloudStackVolume getCloudStackVolume(Map<String, String> cloudStackVolumeMap);
290290

291291
/**
292292
* Method encapsulates the behavior based on the opted protocol in subclasses
@@ -296,7 +296,7 @@ public Volume getStorageVolume(Volume volume)
296296
* @param accessGroup the access group to create
297297
* @return the created AccessGroup object
298298
*/
299-
abstract AccessGroup createAccessGroup(AccessGroup accessGroup);
299+
abstract public AccessGroup createAccessGroup(AccessGroup accessGroup);
300300

301301
/**
302302
* Method encapsulates the behavior based on the opted protocol in subclasses
@@ -316,4 +316,28 @@ public Volume getStorageVolume(Volume volume)
316316
* @return the updated AccessGroup object
317317
*/
318318
abstract AccessGroup updateAccessGroup(AccessGroup accessGroup);
319+
320+
/**
321+
* Method encapsulates the behavior based on the opted protocol in subclasses
322+
@@ -306,22 +306,22 @@ public Volume getStorageVolume(Volume volume)
323+
* getNameSpace for Nvme/TCP and Nvme/FC protocols
324+
* @param values
325+
*/
326+
abstract public AccessGroup getAccessGroup(Map<String, String> values);
327+
328+
/**
329+
* Method encapsulates the behavior based on the opted protocol in subclasses
330+
* lunMap for iSCSI and FC protocols
331+
* //TODO for Nvme/TCP and Nvme/FC protocols
332+
* @param values
333+
*/
334+
abstract public void enableLogicalAccess(Map<String,String> values);
335+
336+
/**
337+
* Method encapsulates the behavior based on the opted protocol in subclasses
338+
* lunUnmap for iSCSI and FC protocols
339+
* //TODO for Nvme/TCP and Nvme/FC protocols
340+
* @param values
341+
*/
342+
abstract public void disableLogicalAccess(Map<String,String> values);
319343
}

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedNASStrategy.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void deleteCloudStackVolume(CloudStackVolume cloudstackVolume) {
7171
}
7272

7373
@Override
74-
CloudStackVolume getCloudStackVolume(CloudStackVolume cloudstackVolume) {
74+
public CloudStackVolume getCloudStackVolume(Map<String, String> cloudStackVolumeMap) {
7575
//TODO
7676
return null;
7777
}
@@ -93,17 +93,22 @@ public AccessGroup updateAccessGroup(AccessGroup accessGroup) {
9393
return null;
9494
}
9595

96+
@Override
97+
public AccessGroup getAccessGroup (Map<String, String> values) {
98+
return null;
99+
}
100+
96101
// Remove @Override - these methods don't exist in parent classes
97102
public AccessGroup getAccessGroup(AccessGroup accessGroup) {
98103
//TODO
99104
return null;
100105
}
101106

102-
void enableLogicalAccess(Map<String, String> values) {
107+
public void enableLogicalAccess(Map<String, String> values) {
103108
//TODO
104109
}
105110

106-
void disableLogicalAccess(Map<String, String> values) {
111+
public void disableLogicalAccess(Map<String, String> values) {
107112
//TODO
108113
}
109114
}

0 commit comments

Comments
 (0)