nvazquez commented on code in PR #13053:
URL: https://github.com/apache/cloudstack/pull/13053#discussion_r3377381328
##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java:
##########
@@ -158,8 +159,58 @@ public boolean connectPhysicalDisk(String volumeUuid,
KVMStoragePool pool, Map<S
return true;
}
+ /**
+ * Checks the result of an iscsiadm node-create command.
+ * Returns true if the node was created or already exists, false on
failure.
+ */
+ boolean handleNodeCreateResult(String result, String volumeUuid) {
+ if (result == null) {
+ logger.debug("Successfully added iSCSI node for target {}",
volumeUuid);
+ return true;
+ }
+ String msg = result.toLowerCase();
+ if (msg.contains("already exists") || msg.contains("database exists")
|| msg.contains("exists")) {
Review Comment:
As an improvement, non-blocking comment, would it be possible to check the
exit status code instead of the returned message?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java:
##########
@@ -65,14 +108,222 @@ public DataTO getTO(DataObject data) {
@Override
public DataStoreTO getStoreTO(DataStore store) { return null; }
+ @Override
+ public boolean volumesRequireGrantAccessWhenUsed() {
+ logger.info("OntapPrimaryDatastoreDriver:
volumesRequireGrantAccessWhenUsed: Called");
Review Comment:
Does it need to be at INFO level?
##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java:
##########
@@ -158,8 +159,58 @@ public boolean connectPhysicalDisk(String volumeUuid,
KVMStoragePool pool, Map<S
return true;
}
+ /**
+ * Checks the result of an iscsiadm node-create command.
+ * Returns true if the node was created or already exists, false on
failure.
+ */
+ boolean handleNodeCreateResult(String result, String volumeUuid) {
+ if (result == null) {
+ logger.debug("Successfully added iSCSI node for target {}",
volumeUuid);
+ return true;
+ }
+ String msg = result.toLowerCase();
+ if (msg.contains("already exists") || msg.contains("database exists")
|| msg.contains("exists")) {
+ logger.debug("iSCSI node already exists for target {},
proceeding", volumeUuid);
+ return true;
+ }
+ logger.debug("Failed to add iSCSI node for target {}: {}", volumeUuid,
result);
+ return false;
+ }
+
+ /**
+ * Checks the result of an iscsiadm login command.
+ * Returns true if the login succeeded or session already exists, false on
failure.
+ */
+ boolean handleLoginResult(String result, String volumeUuid) {
+ if (result == null) {
+ logger.debug("Successfully logged in to iSCSI target {}",
volumeUuid);
+ return true;
+ }
+ String msg = result.toLowerCase();
+ if (msg.contains("already present") || msg.contains("already logged
in") || msg.contains("session exists")) {
Review Comment:
Similar here?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java:
##########
@@ -98,14 +349,231 @@ public ChapInfo getChapInfo(DataObject dataObject) {
return null;
}
+ /**
+ * Grants a host access to a volume.
+ */
@Override
public boolean grantAccess(DataObject dataObject, Host host, DataStore
dataStore) {
- return false;
+ try {
+ if (dataStore == null) {
+ throw new InvalidParameterValueException("dataStore should not
be null");
+ }
+ if (dataObject == null) {
+ throw new InvalidParameterValueException("dataObject should
not be null");
+ }
+ if (host == null) {
+ throw new InvalidParameterValueException("host should not be
null");
+ }
Review Comment:
Similarly here
##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java:
##########
@@ -238,6 +289,15 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid,
KVMStoragePool pool) {
}
private long getDeviceSize(String deviceByPath) {
+ try {
+ if (!Files.exists(Paths.get(deviceByPath))) {
+ logger.debug("Device by-path does not exist yet: " +
deviceByPath);
+ return 0L;
+ }
+ } catch (Exception ignore) {
+ // If FS check fails for any reason, fall back to blockdev call
Review Comment:
I think this deserves a log line
##########
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java:
##########
@@ -158,8 +159,58 @@ public boolean connectPhysicalDisk(String volumeUuid,
KVMStoragePool pool, Map<S
return true;
}
+ /**
+ * Checks the result of an iscsiadm node-create command.
+ * Returns true if the node was created or already exists, false on
failure.
+ */
+ boolean handleNodeCreateResult(String result, String volumeUuid) {
+ if (result == null) {
+ logger.debug("Successfully added iSCSI node for target {}",
volumeUuid);
+ return true;
+ }
+ String msg = result.toLowerCase();
+ if (msg.contains("already exists") || msg.contains("database exists")
|| msg.contains("exists")) {
+ logger.debug("iSCSI node already exists for target {},
proceeding", volumeUuid);
+ return true;
+ }
+ logger.debug("Failed to add iSCSI node for target {}: {}", volumeUuid,
result);
+ return false;
+ }
+
+ /**
+ * Checks the result of an iscsiadm login command.
+ * Returns true if the login succeeded or session already exists, false on
failure.
+ */
+ boolean handleLoginResult(String result, String volumeUuid) {
+ if (result == null) {
+ logger.debug("Successfully logged in to iSCSI target {}",
volumeUuid);
+ return true;
+ }
+ String msg = result.toLowerCase();
+ if (msg.contains("already present") || msg.contains("already logged
in") || msg.contains("session exists")) {
+ logger.debug("iSCSI session already exists for target {},
proceeding", volumeUuid);
+ return true;
+ }
+ logger.debug("Failed to log in to iSCSI target {}: {}", volumeUuid,
result);
+ return false;
+ }
+
+ private void rescanIscsiSessions(String iqn, String host, int port) {
+ Script rescanCmd = new Script(true, "iscsiadm", 0, logger);
+ rescanCmd.add("-m", "node");
+ rescanCmd.add("-T", iqn);
+ rescanCmd.add("-p", host + ":" + port);
+ rescanCmd.add("--rescan");
+ String rescanResult = rescanCmd.execute();
+ if (rescanResult != null) {
+ logger.warn("iSCSI session rescan returned: {}", rescanResult);
+ } else {
+ logger.debug("iSCSI session rescan completed successfully for
{}@{}:{}", iqn, host, port);
+ }
+ }
+
private void waitForDiskToBecomeAvailable(String volumeUuid,
KVMStoragePool pool) {
- int numberOfTries = 10;
+ int numberOfTries = 30;
Review Comment:
Is it worth being configurable by administrators?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java:
##########
@@ -65,14 +108,222 @@ public DataTO getTO(DataObject data) {
@Override
public DataStoreTO getStoreTO(DataStore store) { return null; }
+ @Override
+ public boolean volumesRequireGrantAccessWhenUsed() {
+ logger.info("OntapPrimaryDatastoreDriver:
volumesRequireGrantAccessWhenUsed: Called");
+ return true;
+ }
+
+ /**
+ * Creates a volume on the ONTAP storage system.
+ */
@Override
public void createAsync(DataStore dataStore, DataObject dataObject,
AsyncCompletionCallback<CreateCmdResult> callback) {
- throw new UnsupportedOperationException("Create operation is not
supported for ONTAP primary storage.");
+ CreateCmdResult createCmdResult = null;
+ String errMsg;
+
+ if (dataObject == null) {
+ throw new InvalidParameterValueException("dataObject should not be
null");
+ }
+ if (dataStore == null) {
+ throw new InvalidParameterValueException("dataStore should not be
null");
+ }
+ if (callback == null) {
+ throw new InvalidParameterValueException("callback should not be
null");
+ }
Review Comment:
What about something like this?
```suggestion
if (ObjectUtils.anyNull(dataObject, dataStore, callback)) {
throw new InvalidParameterValueException("dataObject, dataStore
and callback must not be null");
}
```
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/UnifiedSANStrategy.java:
##########
@@ -286,24 +370,226 @@ public AccessGroup getAccessGroup(Map<String, String>
values) {
AccessGroup accessGroup = new AccessGroup();
accessGroup.setIgroup(igroup);
return accessGroup;
- } catch (Exception e) {
- String errMsg = e.getMessage();
- if (errMsg != null && errMsg.contains("not found")) {
- logger.warn("getAccessGroup: Igroup '{}' not found on SVM '{}'
({}). Returning null.", igroupName, svmName, errMsg);
+ } catch (FeignException e) {
+ if (e.status() == 404) {
+ logger.warn("getAccessGroup: Igroup '{}' not found on SVM '{}'
(status 404). Returning null.", igroupName, svmName);
return null;
}
- logger.error("Exception occurred while fetching Igroup, Exception:
{}", errMsg);
- throw new CloudRuntimeException("Failed to fetch Igroup details: "
+ errMsg);
+ logger.error("FeignException occurred while fetching Igroup,
Status: {}, Exception: {}", e.status(), e.getMessage());
+ throw new CloudRuntimeException("Failed to fetch Igroup details: "
+ e.getMessage());
+ } catch (Exception e) {
+ logger.error("Exception occurred while fetching Igroup, Exception:
{}", e.getMessage());
+ throw new CloudRuntimeException("Failed to fetch Igroup details: "
+ e.getMessage());
}
}
- public Map<String, String> enableLogicalAccess(Map<String, String> values)
{
- return null;
+ public String enableLogicalAccess(Map<String, String> values) {
+ logger.info("enableLogicalAccess : Create LunMap");
Review Comment:
Are both consecutive log lines needed? Similar pattern is also present in
other methods as well
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java:
##########
@@ -98,14 +349,231 @@ public ChapInfo getChapInfo(DataObject dataObject) {
return null;
}
+ /**
+ * Grants a host access to a volume.
+ */
@Override
public boolean grantAccess(DataObject dataObject, Host host, DataStore
dataStore) {
- return false;
+ try {
+ if (dataStore == null) {
+ throw new InvalidParameterValueException("dataStore should not
be null");
+ }
+ if (dataObject == null) {
+ throw new InvalidParameterValueException("dataObject should
not be null");
+ }
+ if (host == null) {
+ throw new InvalidParameterValueException("host should not be
null");
+ }
+
+ StoragePoolVO storagePool =
storagePoolDao.findById(dataStore.getId());
+ if (storagePool == null) {
+ logger.error("grantAccess: Storage Pool not found for id: " +
dataStore.getId());
+ throw new CloudRuntimeException("Storage Pool not found for
id: " + dataStore.getId());
+ }
+
+ // ONTAP managed storage only supports cluster and zone scoped
pools
+ if (storagePool.getScope() != ScopeType.CLUSTER &&
storagePool.getScope() != ScopeType.ZONE) {
+ logger.error("grantAccess: Only Cluster and Zone scoped
primary storage is supported for storage Pool: " + storagePool.getName());
+ throw new CloudRuntimeException("Only Cluster and Zone scoped
primary storage is supported for Storage Pool: " + storagePool.getName());
+ }
+
+ if (dataObject.getType() == DataObjectType.VOLUME) {
+ VolumeVO volumeVO = volumeDao.findById(dataObject.getId());
+ if (volumeVO == null) {
+ logger.error("grantAccess: CloudStack Volume not found for
id: " + dataObject.getId());
+ throw new CloudRuntimeException("CloudStack Volume not
found for id: " + dataObject.getId());
+ }
+
+ Map<String, String> details =
storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId());
+ String svmName = details.get(OntapStorageConstants.SVM_NAME);
+
+ if
(ProtocolType.ISCSI.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL)))
{
+ // Only retrieve LUN name for iSCSI volumes
+ String cloudStackVolumeName =
volumeDetailsDao.findDetail(volumeVO.getId(),
OntapStorageConstants.LUN_DOT_NAME).getValue();
+ UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy)
OntapStorageUtils.getStrategyByStoragePoolDetails(details);
+ String accessGroupName =
OntapStorageUtils.getIgroupName(svmName, host.getName());
+
+ // Validate if Igroup exist ONTAP for this host as we may
be using delete_on_unmap= true and igroup may be deleted by ONTAP automatically
+ Map<String, String> getAccessGroupMap = Map.of(
+ OntapStorageConstants.NAME, accessGroupName,
+ OntapStorageConstants.SVM_DOT_NAME, svmName
+ );
+ AccessGroup accessGroup =
sanStrategy.getAccessGroup(getAccessGroupMap);
+ if(accessGroup == null || accessGroup.getIgroup() == null)
{
+ logger.info("grantAccess: Igroup {} does not exist for
the host {} : Need to create Igroup for the host ", accessGroupName,
host.getName());
+ // create the igroup for the host and perform
lun-mapping
+ accessGroup = new AccessGroup();
+ List<HostVO> hosts = new ArrayList<>();
+ hosts.add((HostVO) host);
+ accessGroup.setHostsToConnect(hosts);
+ accessGroup.setStoragePoolId(storagePool.getId());
+ accessGroup =
sanStrategy.createAccessGroup(accessGroup);
+ }else{
+ logger.info("grantAccess: Igroup {} already exist for
the host {}: ", accessGroup.getIgroup().getName() ,host.getName());
+ /* TODO Below cases will be covered later, for now
they will be a pre-requisite on customer side
+ 1. Igroup exist with the same name but host
initiator has been rempved
+ 2. Igroup exist with the same name but host
initiator has been changed may be due to new NIC or new adapter
+ In both cases we need to verify current host
initiator is registered in the igroup before allowing access
+ Incase it is not , add it and proceed for lun-mapping
+ */
+ }
+ logger.info("grantAccess: Igroup {} is present now with
initiators {} ", accessGroup.getIgroup().getName(),
accessGroup.getIgroup().getInitiators());
+ // Create or retrieve existing LUN mapping
+ String lunNumber = sanStrategy.ensureLunMapped(svmName,
cloudStackVolumeName, accessGroupName);
+
+ // Update volume path if changed (e.g., after migration or
re-mapping)
+ String iscsiPath = OntapStorageConstants.SLASH +
storagePool.getPath() + OntapStorageConstants.SLASH + lunNumber;
+ if (volumeVO.getPath() == null ||
!volumeVO.getPath().equals(iscsiPath)) {
+ volumeVO.set_iScsiName(iscsiPath);
+ volumeVO.setPath(iscsiPath);
+ }
Review Comment:
Can these lines be extracted to a method?
##########
plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/driver/OntapPrimaryDatastoreDriver.java:
##########
@@ -98,14 +349,231 @@ public ChapInfo getChapInfo(DataObject dataObject) {
return null;
}
+ /**
+ * Grants a host access to a volume.
+ */
@Override
public boolean grantAccess(DataObject dataObject, Host host, DataStore
dataStore) {
- return false;
+ try {
+ if (dataStore == null) {
+ throw new InvalidParameterValueException("dataStore should not
be null");
+ }
+ if (dataObject == null) {
+ throw new InvalidParameterValueException("dataObject should
not be null");
+ }
+ if (host == null) {
+ throw new InvalidParameterValueException("host should not be
null");
+ }
+
+ StoragePoolVO storagePool =
storagePoolDao.findById(dataStore.getId());
+ if (storagePool == null) {
+ logger.error("grantAccess: Storage Pool not found for id: " +
dataStore.getId());
+ throw new CloudRuntimeException("Storage Pool not found for
id: " + dataStore.getId());
+ }
+
+ // ONTAP managed storage only supports cluster and zone scoped
pools
+ if (storagePool.getScope() != ScopeType.CLUSTER &&
storagePool.getScope() != ScopeType.ZONE) {
+ logger.error("grantAccess: Only Cluster and Zone scoped
primary storage is supported for storage Pool: " + storagePool.getName());
+ throw new CloudRuntimeException("Only Cluster and Zone scoped
primary storage is supported for Storage Pool: " + storagePool.getName());
+ }
+
+ if (dataObject.getType() == DataObjectType.VOLUME) {
+ VolumeVO volumeVO = volumeDao.findById(dataObject.getId());
+ if (volumeVO == null) {
+ logger.error("grantAccess: CloudStack Volume not found for
id: " + dataObject.getId());
+ throw new CloudRuntimeException("CloudStack Volume not
found for id: " + dataObject.getId());
+ }
+
+ Map<String, String> details =
storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId());
+ String svmName = details.get(OntapStorageConstants.SVM_NAME);
+
+ if
(ProtocolType.ISCSI.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL)))
{
+ // Only retrieve LUN name for iSCSI volumes
+ String cloudStackVolumeName =
volumeDetailsDao.findDetail(volumeVO.getId(),
OntapStorageConstants.LUN_DOT_NAME).getValue();
+ UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy)
OntapStorageUtils.getStrategyByStoragePoolDetails(details);
+ String accessGroupName =
OntapStorageUtils.getIgroupName(svmName, host.getName());
+
+ // Validate if Igroup exist ONTAP for this host as we may
be using delete_on_unmap= true and igroup may be deleted by ONTAP automatically
+ Map<String, String> getAccessGroupMap = Map.of(
+ OntapStorageConstants.NAME, accessGroupName,
+ OntapStorageConstants.SVM_DOT_NAME, svmName
+ );
+ AccessGroup accessGroup =
sanStrategy.getAccessGroup(getAccessGroupMap);
+ if(accessGroup == null || accessGroup.getIgroup() == null)
{
+ logger.info("grantAccess: Igroup {} does not exist for
the host {} : Need to create Igroup for the host ", accessGroupName,
host.getName());
+ // create the igroup for the host and perform
lun-mapping
+ accessGroup = new AccessGroup();
+ List<HostVO> hosts = new ArrayList<>();
+ hosts.add((HostVO) host);
+ accessGroup.setHostsToConnect(hosts);
+ accessGroup.setStoragePoolId(storagePool.getId());
+ accessGroup =
sanStrategy.createAccessGroup(accessGroup);
+ }else{
+ logger.info("grantAccess: Igroup {} already exist for
the host {}: ", accessGroup.getIgroup().getName() ,host.getName());
+ /* TODO Below cases will be covered later, for now
they will be a pre-requisite on customer side
+ 1. Igroup exist with the same name but host
initiator has been rempved
+ 2. Igroup exist with the same name but host
initiator has been changed may be due to new NIC or new adapter
+ In both cases we need to verify current host
initiator is registered in the igroup before allowing access
+ Incase it is not , add it and proceed for lun-mapping
+ */
+ }
+ logger.info("grantAccess: Igroup {} is present now with
initiators {} ", accessGroup.getIgroup().getName(),
accessGroup.getIgroup().getInitiators());
+ // Create or retrieve existing LUN mapping
+ String lunNumber = sanStrategy.ensureLunMapped(svmName,
cloudStackVolumeName, accessGroupName);
+
+ // Update volume path if changed (e.g., after migration or
re-mapping)
+ String iscsiPath = OntapStorageConstants.SLASH +
storagePool.getPath() + OntapStorageConstants.SLASH + lunNumber;
+ if (volumeVO.getPath() == null ||
!volumeVO.getPath().equals(iscsiPath)) {
+ volumeVO.set_iScsiName(iscsiPath);
+ volumeVO.setPath(iscsiPath);
+ }
+ } else if
(ProtocolType.NFS3.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL)))
{
+ // For NFS, no access grant needed - file is accessible
via mount
+ logger.debug("grantAccess: NFS volume [{}], no igroup
mapping required", volumeVO.getUuid());
+ return true;
+ }
+ volumeVO.setPoolType(storagePool.getPoolType());
+ volumeVO.setPoolId(storagePool.getId());
+ volumeDao.update(volumeVO.getId(), volumeVO);
+ } else {
+ logger.error("Invalid DataObjectType (" + dataObject.getType()
+ ") passed to grantAccess");
+ throw new CloudRuntimeException("Invalid DataObjectType (" +
dataObject.getType() + ") passed to grantAccess");
+ }
+ return true;
+ } catch (Exception e) {
+ logger.error("grantAccess: Failed for dataObject [{}]: {}",
dataObject, e.getMessage());
+ throw new CloudRuntimeException("Failed with error: " +
e.getMessage(), e);
+ }
}
+ /**
+ * Revokes a host's access to a volume.
+ */
@Override
public void revokeAccess(DataObject dataObject, Host host, DataStore
dataStore) {
- throw new UnsupportedOperationException("Revoke access operation is
not supported for ONTAP primary storage.");
+ try {
+ if (dataStore == null) {
+ throw new InvalidParameterValueException("dataStore should not
be null");
+ }
+ if (dataObject == null) {
+ throw new InvalidParameterValueException("dataObject should
not be null");
+ }
+ if (host == null) {
+ throw new InvalidParameterValueException("host should not be
null");
+ }
+
+ StoragePoolVO storagePool =
storagePoolDao.findById(dataStore.getId());
+ if (storagePool == null) {
+ logger.error("revokeAccess: Storage Pool not found for id: " +
dataStore.getId());
+ throw new CloudRuntimeException("Storage Pool not found for
id: " + dataStore.getId());
+ }
+
+ if (storagePool.getScope() != ScopeType.CLUSTER &&
storagePool.getScope() != ScopeType.ZONE) {
+ logger.error("revokeAccess: Only Cluster and Zone scoped
primary storage is supported for storage Pool: " + storagePool.getName());
+ throw new CloudRuntimeException("Only Cluster and Zone scoped
primary storage is supported for Storage Pool: " + storagePool.getName());
+ }
+
+ if (dataObject.getType() == DataObjectType.VOLUME) {
+ VolumeVO volumeVO = volumeDao.findById(dataObject.getId());
+ if (volumeVO == null) {
+ logger.error("revokeAccess: CloudStack Volume not found
for id: " + dataObject.getId());
+ throw new CloudRuntimeException("CloudStack Volume not
found for id: " + dataObject.getId());
+ }
+ revokeAccessForVolume(storagePool, volumeVO, host);
+ } else {
+ logger.error("revokeAccess: Invalid DataObjectType (" +
dataObject.getType() + ") passed to revokeAccess");
+ throw new CloudRuntimeException("Invalid DataObjectType (" +
dataObject.getType() + ") passed to revokeAccess");
+ }
+ } catch (Exception e) {
+ logger.error("revokeAccess: Failed for dataObject [{}]: {}",
dataObject, e.getMessage());
+ throw new CloudRuntimeException("Failed with error: " +
e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Revokes volume access for the specified host.
+ */
+ private void revokeAccessForVolume(StoragePoolVO storagePool, VolumeVO
volumeVO, Host host) {
+ logger.info("revokeAccessForVolume: Revoking access to volume [{}] for
host [{}]", volumeVO.getName(), host.getName());
+
+ Map<String, String> details =
storagePoolDetailsDao.listDetailsKeyPairs(storagePool.getId());
+ StorageStrategy storageStrategy =
OntapStorageUtils.getStrategyByStoragePoolDetails(details);
+ String svmName = details.get(OntapStorageConstants.SVM_NAME);
+
+ if
(ProtocolType.ISCSI.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL)))
{
+ String accessGroupName = OntapStorageUtils.getIgroupName(svmName,
host.getName());
+
+ // Retrieve LUN name from volume details; if missing, volume may
not have been fully created
+ VolumeDetailVO lunDetail =
volumeDetailsDao.findDetail(volumeVO.getId(),
OntapStorageConstants.LUN_DOT_NAME);
+ String lunName = lunDetail != null ? lunDetail.getValue() : null;
+ if (lunName == null) {
+ logger.warn("revokeAccessForVolume: No LUN name found for
volume [{}]; skipping revoke", volumeVO.getId());
+ return;
+ }
+
+ // Verify LUN still exists on ONTAP (may have been manually
deleted)
+ CloudStackVolume cloudStackVolume =
getCloudStackVolumeByName(storageStrategy, svmName, lunName);
+ if (cloudStackVolume == null || cloudStackVolume.getLun() == null
|| cloudStackVolume.getLun().getUuid() == null) {
+ logger.warn("revokeAccessForVolume: LUN for volume [{}] not
found on ONTAP, skipping revoke", volumeVO.getId());
+ return;
+ }
+
+ // Verify igroup still exists on ONTAP
+ AccessGroup accessGroup = getAccessGroupByName(storageStrategy,
svmName, accessGroupName);
+ if (accessGroup == null || accessGroup.getIgroup() == null ||
accessGroup.getIgroup().getUuid() == null) {
+ logger.warn("revokeAccessForVolume: iGroup [{}] not found on
ONTAP, skipping revoke", accessGroupName);
+ return;
+ }
+
+ // Verify host initiator is in the igroup before attempting to
remove mapping
+ SANStrategy sanStrategy = (UnifiedSANStrategy) storageStrategy;
+ if
(!sanStrategy.validateInitiatorInAccessGroup(host.getStorageUrl(), svmName,
accessGroup.getIgroup())) {
+ logger.warn("revokeAccessForVolume: Initiator [{}] is not in
iGroup [{}], skipping revoke",
+ host.getStorageUrl(), accessGroupName);
+ return;
+ }
+
+ // Remove the LUN mapping from the igroup
+ Map<String, String> disableLogicalAccessMap = new HashMap<>();
+ disableLogicalAccessMap.put(OntapStorageConstants.LUN_DOT_UUID,
cloudStackVolume.getLun().getUuid());
+ disableLogicalAccessMap.put(OntapStorageConstants.IGROUP_DOT_UUID,
accessGroup.getIgroup().getUuid());
+ storageStrategy.disableLogicalAccess(disableLogicalAccessMap);
+
+ logger.info("revokeAccessForVolume: Successfully revoked access to
LUN [{}] for host [{}]",
+ lunName, host.getName());
Review Comment:
Similarly here
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]