forked from apache/cloudstack
-
Notifications
You must be signed in to change notification settings - Fork 0
CSTACKEX-46 Create Async, Attach Cluster/Zone and Grant/Revoke Access #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
suryag1201
wants to merge
21
commits into
main
Choose a base branch
from
feature/CSTACKEX-46
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
eafc1e7
CSTACKEX-46 Create Async, Attach Cluster/Zone and Grant/Revoke Access
f43783c
CSTACKEX-46 Added Logging
ad4e526
CSTACKEX-46 Resolve Copilot review comments
54a7eef
CSTACKEX-46 Resolve review comments
815af83
CSTACKEX-46 Resolve review bot comments
15081b5
CSTACKEX-46 Change method name
65fa626
CSTACKEX-46 Resolve check styling issues
3a7d2f8
CSTACKEX-46 Testing: Resolve fetch Storage details issue
bc8e216
CSTACKEX-46 Testing: Protocol Type fetch issue
cd87640
CSTACKEX-46 Testing: Added debug log
a10981a
CSTACKEX-46 Testing: Added debug log
c4399c1
CSTACKEX-46 Testing: Corrected the URL for Create Lun and Igroup
71daee2
CSTACKEX-46 Resolve bot review comments
dfde3f8
CSTACKEX-46 Resolve review comments
bce721d
CSTACKEX-46 Resolve review comments again
8980303
CSTACKEX-46 Change log level
70c6b13
CSTACKEX-46 added valiodation for lun name
63b484b
CSTACKEX-46 resolve license issue
241d7f1
CSTACKEX-46 resolve check style issues
016601d
CSTACKEX-46 Resolve import issues
79a078f
CSTACKEX-46 Resolve copilot comments
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
254 changes: 219 additions & 35 deletions
254
...ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java
Large diffs are not rendered by default.
Oops, something went wrong.
19 changes: 19 additions & 0 deletions
19
...ge/volume/ontap/src/main/java/org/apache/cloudstack/storage/feign/FeignConfiguration.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -143,5 +143,4 @@ public int hashCode() { | |
|
|
||
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||
| public static class Links { } | ||
|
|
||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| import com.cloud.agent.api.StoragePoolInfo; | ||
| import com.cloud.dc.ClusterVO; | ||
| import com.cloud.dc.dao.ClusterDao; | ||
| import com.cloud.exception.InvalidParameterValueException; | ||
| import com.cloud.host.HostVO; | ||
| import com.cloud.hypervisor.Hypervisor; | ||
| import com.cloud.resource.ResourceManager; | ||
|
|
@@ -38,17 +39,26 @@ | |
| import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; | ||
| import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; | ||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; | ||
| import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; | ||
| import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; | ||
| import org.apache.cloudstack.storage.datastore.lifecycle.BasePrimaryDataStoreLifeCycleImpl; | ||
| import org.apache.cloudstack.storage.feign.model.Igroup; | ||
| import org.apache.cloudstack.storage.feign.model.Initiator; | ||
| import org.apache.cloudstack.storage.feign.model.OntapStorage; | ||
| import org.apache.cloudstack.storage.feign.model.Svm; | ||
| import org.apache.cloudstack.storage.provider.StorageProviderFactory; | ||
| import org.apache.cloudstack.storage.service.StorageStrategy; | ||
| import org.apache.cloudstack.storage.service.model.AccessGroup; | ||
| import org.apache.cloudstack.storage.service.model.ProtocolType; | ||
| import org.apache.cloudstack.storage.utils.Constants; | ||
| import org.apache.cloudstack.storage.utils.Utility; | ||
| import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; | ||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
|
|
||
| import javax.inject.Inject; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
|
|
@@ -59,6 +69,8 @@ public class OntapPrimaryDatastoreLifecycle extends BasePrimaryDataStoreLifeCycl | |
| @Inject private StorageManager _storageMgr; | ||
| @Inject private ResourceManager _resourceMgr; | ||
| @Inject private PrimaryDataStoreHelper _dataStoreHelper; | ||
| @Inject private PrimaryDataStoreDao storagePoolDao; | ||
| @Inject private StoragePoolDetailsDao storagePoolDetailsDao; | ||
| private static final Logger s_logger = LogManager.getLogger(OntapPrimaryDatastoreLifecycle.class); | ||
|
|
||
| // ONTAP minimum volume size is 1.56 GB (1677721600 bytes) | ||
|
|
@@ -241,16 +253,48 @@ public DataStore initialize(Map<String, Object> dsInfos) { | |
| @Override | ||
| public boolean attachCluster(DataStore dataStore, ClusterScope scope) { | ||
| logger.debug("In attachCluster for ONTAP primary storage"); | ||
| PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo)dataStore; | ||
| List<HostVO> hostsToConnect = _resourceMgr.getEligibleUpAndEnabledHostsInClusterForStorageConnection(primarystore); | ||
| if (dataStore == null) { | ||
| throw new InvalidParameterValueException("attachCluster: dataStore should not be null"); | ||
| } | ||
| if (scope == null) { | ||
| throw new InvalidParameterValueException("attachCluster: scope should not be null"); | ||
| } | ||
| List<String> hostsIdentifier = new ArrayList<>(); | ||
| StoragePoolVO storagePool = storagePoolDao.findById(dataStore.getId()); | ||
| if (storagePool == null) { | ||
| s_logger.error("attachCluster : Storage Pool not found for id: " + dataStore.getId()); | ||
| throw new CloudRuntimeException("attachCluster : Storage Pool not found for id: " + dataStore.getId()); | ||
| } | ||
| PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)dataStore; | ||
| List<HostVO> hostsToConnect = _resourceMgr.getEligibleUpAndEnabledHostsInClusterForStorageConnection(primaryStore); | ||
| // TODO- need to check if no host to connect then throw exception or just continue | ||
| logger.debug("attachCluster: Eligible Up and Enabled hosts: {} in cluster {}", hostsToConnect, primaryStore.getClusterId()); | ||
|
|
||
| logger.debug(String.format("Attaching the pool to each of the hosts %s in the cluster: %s", hostsToConnect, primarystore.getClusterId())); | ||
| Map<String, String> details = storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId()); | ||
| StorageStrategy strategy = Utility.getStrategyByStoragePoolDetails(details); | ||
| ProtocolType protocol = ProtocolType.valueOf(details.get(Constants.PROTOCOL)); | ||
| //TODO- Check if we have to handle heterogeneous host within the cluster | ||
| if (!validateProtocolSupportAndFetchHostsIdentifier(hostsToConnect, protocol, hostsIdentifier)) { | ||
| String errMsg = "attachCluster: Not all hosts in the cluster support the protocol: " + protocol.name(); | ||
| s_logger.error(errMsg); | ||
| throw new CloudRuntimeException(errMsg); | ||
| } | ||
| //TODO - check if no host to connect then also need to create access group without initiators | ||
| if (hostsIdentifier != null && hostsIdentifier.size() > 0) { | ||
| try { | ||
| AccessGroup accessGroupRequest = createAccessGroupRequestByProtocol(storagePool, scope.getScopeId(), details, hostsIdentifier); | ||
| strategy.createAccessGroup(accessGroupRequest); | ||
| } catch (Exception e) { | ||
| s_logger.error("attachCluster: Failed to create access group on storage system for cluster: " + primaryStore.getClusterId() + ". Exception: " + e.getMessage(), e); | ||
| throw new CloudRuntimeException("attachCluster: Failed to create access group on storage system for cluster: " + primaryStore.getClusterId() + ". Exception: " + e.getMessage(), e); | ||
| } | ||
| } | ||
| logger.debug("attachCluster: Attaching the pool to each of the host in the cluster: {}", primaryStore.getClusterId()); | ||
| for (HostVO host : hostsToConnect) { | ||
| // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster | ||
| try { | ||
| _storageMgr.connectHostToSharedPool(host, dataStore.getId()); | ||
| } catch (Exception e) { | ||
| logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e); | ||
| logger.warn("attachCluster: Unable to establish a connection between " + host + " and " + dataStore, e); | ||
| } | ||
| } | ||
| _dataStoreHelper.attachCluster(dataStore); | ||
|
|
@@ -265,11 +309,41 @@ public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo exis | |
| @Override | ||
| public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.HypervisorType hypervisorType) { | ||
| logger.debug("In attachZone for ONTAP primary storage"); | ||
| if (dataStore == null) { | ||
| throw new InvalidParameterValueException("attachZone: dataStore should not be null"); | ||
| } | ||
| if (scope == null) { | ||
| throw new InvalidParameterValueException("attachZone: scope should not be null"); | ||
| } | ||
| List<String> hostsIdentifier = new ArrayList<>(); | ||
| StoragePoolVO storagePool = storagePoolDao.findById(dataStore.getId()); | ||
| if (storagePool == null) { | ||
| s_logger.error("attachZone : Storage Pool not found for id: " + dataStore.getId()); | ||
| throw new CloudRuntimeException("attachZone : Storage Pool not found for id: " + dataStore.getId()); | ||
| } | ||
| List<HostVO> hostsToConnect = _resourceMgr.getEligibleUpAndEnabledHostsInZoneForStorageConnection(dataStore, scope.getScopeId(), Hypervisor.HypervisorType.KVM); | ||
| // TODO- need to check if no host to connect then throw exception or just continue | ||
| logger.debug("attachZone: Eligible Up and Enabled hosts: {}", hostsToConnect); | ||
|
|
||
| logger.debug(String.format("In createPool. Attaching the pool to each of the hosts in %s.", hostsToConnect)); | ||
| Map<String, String> details = storagePoolDetailsDao.listDetailsKeyPairs(dataStore.getId()); | ||
| StorageStrategy strategy = Utility.getStrategyByStoragePoolDetails(details); | ||
| ProtocolType protocol = ProtocolType.valueOf(details.get(Constants.PROTOCOL)); | ||
| //TODO- Check if we have to handle heterogeneous host within the zone | ||
| if (!validateProtocolSupportAndFetchHostsIdentifier(hostsToConnect, protocol, hostsIdentifier)) { | ||
| String errMsg = "attachZone: Not all hosts in the zone support the protocol: " + protocol.name(); | ||
| s_logger.error(errMsg); | ||
| throw new CloudRuntimeException(errMsg); | ||
| } | ||
| if (hostsIdentifier != null && !hostsIdentifier.isEmpty()) { | ||
| try { | ||
| AccessGroup accessGroupRequest = createAccessGroupRequestByProtocol(storagePool, scope.getScopeId(), details, hostsIdentifier); | ||
| strategy.createAccessGroup(accessGroupRequest); | ||
| } catch (Exception e) { | ||
| s_logger.error("attachZone: Failed to create access group on storage system for zone with Exception: " + e.getMessage()); | ||
| throw new CloudRuntimeException("attachZone: Failed to create access group on storage system for zone with Exception: " + e.getMessage()); | ||
| } | ||
| } | ||
| for (HostVO host : hostsToConnect) { | ||
| // TODO: Fetch the host IQN and add to the initiator group on ONTAP cluster | ||
| try { | ||
| _storageMgr.connectHostToSharedPool(host, dataStore.getId()); | ||
| } catch (Exception e) { | ||
suryag1201 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
@@ -280,6 +354,73 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper | |
| return true; | ||
| } | ||
|
|
||
| private boolean validateProtocolSupportAndFetchHostsIdentifier(List<HostVO> hosts, ProtocolType protocolType, List<String> hostIdentifiers) { | ||
| switch (protocolType) { | ||
| case ISCSI: | ||
| String protocolPrefix = Constants.IQN; | ||
| for (HostVO host : hosts) { | ||
| if (host == null || host.getStorageUrl() == null || host.getStorageUrl().trim().isEmpty() | ||
| || !host.getStorageUrl().startsWith(protocolPrefix)) { | ||
| return false; | ||
| } | ||
| hostIdentifiers.add(host.getStorageUrl()); | ||
| } | ||
| break; | ||
| default: | ||
| throw new CloudRuntimeException("validateProtocolSupportAndFetchHostsIdentifier : Unsupported protocol: " + protocolType.name()); | ||
| } | ||
| logger.info("validateProtocolSupportAndFetchHostsIdentifier: All hosts support the protocol: " + protocolType.name()); | ||
| return true; | ||
| } | ||
|
|
||
| private AccessGroup createAccessGroupRequestByProtocol(StoragePoolVO storagePool, long scopeId, Map<String, String> details, List<String> hostsIdentifier) { | ||
| ProtocolType protocol = ProtocolType.valueOf(details.get(Constants.PROTOCOL).toUpperCase()); | ||
| String svmName = details.get(Constants.SVM_NAME); | ||
| switch (protocol) { | ||
| case ISCSI: | ||
| // Access group name format: cs_svmName_scopeId | ||
| String igroupName = Utility.getIgroupName(svmName, scopeId); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This getIgroupName could rather be in some helper class instead of Utility |
||
| Hypervisor.HypervisorType hypervisorType = storagePool.getHypervisor(); | ||
| return createSANAccessGroupRequest(svmName, igroupName, hypervisorType, hostsIdentifier); | ||
| default: | ||
| s_logger.error("createAccessGroupRequestByProtocol: Unsupported protocol " + protocol); | ||
| throw new CloudRuntimeException("createAccessGroupRequestByProtocol: Unsupported protocol " + protocol); | ||
| } | ||
| } | ||
|
|
||
suryag1201 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| private AccessGroup createSANAccessGroupRequest(String svmName, String igroupName, Hypervisor.HypervisorType hypervisorType, List<String> hostsIdentifier) { | ||
| AccessGroup accessGroupRequest = new AccessGroup(); | ||
| Igroup igroup = new Igroup(); | ||
|
|
||
| if (svmName != null && !svmName.isEmpty()) { | ||
| Svm svm = new Svm(); | ||
| svm.setName(svmName); | ||
| igroup.setSvm(svm); | ||
| } | ||
|
|
||
| if (igroupName != null && !igroupName.isEmpty()) { | ||
| igroup.setName(igroupName); | ||
| } | ||
|
|
||
| if (hypervisorType != null) { | ||
| String hypervisorName = hypervisorType.name(); | ||
| igroup.setOsType(Igroup.OsTypeEnum.valueOf(Utility.getOSTypeFromHypervisor(hypervisorName))); | ||
| } | ||
|
|
||
| if (hostsIdentifier != null && hostsIdentifier.size() > 0) { | ||
| List<Initiator> initiators = new ArrayList<>(); | ||
| for (String hostIdentifier : hostsIdentifier) { | ||
| Initiator initiator = new Initiator(); | ||
| initiator.setName(hostIdentifier); | ||
| initiators.add(initiator); | ||
| } | ||
| igroup.setInitiators(initiators); | ||
| } | ||
| accessGroupRequest.setIgroup(igroup); | ||
| s_logger.debug("createSANAccessGroupRequest: request: " + accessGroupRequest); | ||
| return accessGroupRequest; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean maintain(DataStore store) { | ||
| return true; | ||
|
|
@@ -325,4 +466,3 @@ public void changeStoragePoolScopeToCluster(DataStore store, ClusterScope cluste | |
|
|
||
| } | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.