Skip to content

Commit 446112b

Browse files
Merge pull request #60 from NetApp/feature/CSTACKEX-191
CSTACKEX-191: logical access methods can have return type as primitive
2 parents b443d81 + d1a795b commit 446112b

9 files changed

Lines changed: 157 additions & 138 deletions

File tree

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ private void rescanIscsiSessions(String iqn, String host, int port) {
210210
}
211211

212212
private void waitForDiskToBecomeAvailable(String volumeUuid, KVMStoragePool pool) {
213-
int numberOfTries = 30;
213+
int numberOfTries = 10;
214214
int timeBetweenTries = 1000;
215215

216216
while (getPhysicalDisk(volumeUuid, pool).getSize() == 0 && numberOfTries > 0) {
@@ -294,8 +294,9 @@ private long getDeviceSize(String deviceByPath) {
294294
logger.debug("Device by-path does not exist yet: " + deviceByPath);
295295
return 0L;
296296
}
297-
} catch (Exception ignore) {
297+
} catch (Exception ex) {
298298
// If FS check fails for any reason, fall back to blockdev call
299+
logger.error("Error fetching device size for {}", deviceByPath, ex);
299300
}
300301

301302
Script iScsiAdmCmd = new Script(true, "blockdev", 0, logger);

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

Lines changed: 93 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.apache.commons.lang3.StringUtils;
7171
import org.apache.logging.log4j.LogManager;
7272
import org.apache.logging.log4j.Logger;
73+
import org.jetbrains.annotations.Nullable;
7374

7475
import javax.inject.Inject;
7576
import java.util.ArrayList;
@@ -110,7 +111,7 @@ public DataTO getTO(DataObject data) {
110111

111112
@Override
112113
public boolean volumesRequireGrantAccessWhenUsed() {
113-
logger.info("OntapPrimaryDatastoreDriver: volumesRequireGrantAccessWhenUsed: Called");
114+
logger.trace("volumesRequireGrantAccessWhenUsed invoked");
114115
return true;
115116
}
116117

@@ -389,44 +390,7 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
389390

390391
if (ProtocolType.ISCSI.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL))) {
391392
// Only retrieve LUN name for iSCSI volumes
392-
String cloudStackVolumeName = volumeDetailsDao.findDetail(volumeVO.getId(), OntapStorageConstants.LUN_DOT_NAME).getValue();
393-
UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy) OntapStorageUtils.getStrategyByStoragePoolDetails(details);
394-
String accessGroupName = OntapStorageUtils.getIgroupName(svmName, host.getName());
395-
396-
// 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
397-
Map<String, String> getAccessGroupMap = Map.of(
398-
OntapStorageConstants.NAME, accessGroupName,
399-
OntapStorageConstants.SVM_DOT_NAME, svmName
400-
);
401-
AccessGroup accessGroup = sanStrategy.getAccessGroup(getAccessGroupMap);
402-
if(accessGroup == null || accessGroup.getIgroup() == null) {
403-
logger.info("grantAccess: Igroup {} does not exist for the host {} : Need to create Igroup for the host ", accessGroupName, host.getName());
404-
// create the igroup for the host and perform lun-mapping
405-
accessGroup = new AccessGroup();
406-
List<HostVO> hosts = new ArrayList<>();
407-
hosts.add((HostVO) host);
408-
accessGroup.setHostsToConnect(hosts);
409-
accessGroup.setStoragePoolId(storagePool.getId());
410-
accessGroup = sanStrategy.createAccessGroup(accessGroup);
411-
}else{
412-
logger.info("grantAccess: Igroup {} already exist for the host {}: ", accessGroup.getIgroup().getName() ,host.getName());
413-
/* TODO Below cases will be covered later, for now they will be a pre-requisite on customer side
414-
1. Igroup exist with the same name but host initiator has been rempved
415-
2. Igroup exist with the same name but host initiator has been changed may be due to new NIC or new adapter
416-
In both cases we need to verify current host initiator is registered in the igroup before allowing access
417-
Incase it is not , add it and proceed for lun-mapping
418-
*/
419-
}
420-
logger.info("grantAccess: Igroup {} is present now with initiators {} ", accessGroup.getIgroup().getName(), accessGroup.getIgroup().getInitiators());
421-
// Create or retrieve existing LUN mapping
422-
String lunNumber = sanStrategy.ensureLunMapped(svmName, cloudStackVolumeName, accessGroupName);
423-
424-
// Update volume path if changed (e.g., after migration or re-mapping)
425-
String iscsiPath = OntapStorageConstants.SLASH + storagePool.getPath() + OntapStorageConstants.SLASH + lunNumber;
426-
if (volumeVO.getPath() == null || !volumeVO.getPath().equals(iscsiPath)) {
427-
volumeVO.set_iScsiName(iscsiPath);
428-
volumeVO.setPath(iscsiPath);
429-
}
393+
grantAccessIscsi(host, volumeVO, details, svmName, storagePool);
430394
} else if (ProtocolType.NFS3.name().equalsIgnoreCase(details.get(OntapStorageConstants.PROTOCOL))) {
431395
// For NFS, no access grant needed - file is accessible via mount
432396
logger.debug("grantAccess: NFS volume [{}], no igroup mapping required", volumeVO.getUuid());
@@ -446,6 +410,47 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
446410
}
447411
}
448412

413+
private void grantAccessIscsi(Host host, VolumeVO volumeVO, Map<String, String> details, String svmName, StoragePoolVO storagePool) {
414+
String cloudStackVolumeName = volumeDetailsDao.findDetail(volumeVO.getId(), OntapStorageConstants.LUN_DOT_NAME).getValue();
415+
UnifiedSANStrategy sanStrategy = (UnifiedSANStrategy) OntapStorageUtils.getStrategyByStoragePoolDetails(details);
416+
String accessGroupName = OntapStorageUtils.getIgroupName(svmName, host.getName());
417+
418+
// 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
419+
Map<String, String> getAccessGroupMap = Map.of(
420+
OntapStorageConstants.NAME, accessGroupName,
421+
OntapStorageConstants.SVM_DOT_NAME, svmName
422+
);
423+
AccessGroup accessGroup = sanStrategy.getAccessGroup(getAccessGroupMap);
424+
if(accessGroup == null || accessGroup.getIgroup() == null) {
425+
logger.info("grantAccess: Igroup {} does not exist for the host {} : Need to create Igroup for the host ", accessGroupName, host.getName());
426+
// create the igroup for the host and perform lun-mapping
427+
accessGroup = new AccessGroup();
428+
List<HostVO> hosts = new ArrayList<>();
429+
hosts.add((HostVO) host);
430+
accessGroup.setHostsToConnect(hosts);
431+
accessGroup.setStoragePoolId(storagePool.getId());
432+
accessGroup = sanStrategy.createAccessGroup(accessGroup);
433+
}else{
434+
logger.info("grantAccess: Igroup {} already exist for the host {}: ", accessGroup.getIgroup().getName() , host.getName());
435+
/* TODO Below cases will be covered later, for now they will be a pre-requisite on customer side
436+
1. Igroup exist with the same name but host initiator has been removed
437+
2. Igroup exist with the same name but host initiator has been changed may be due to new NIC or new adapter
438+
In both cases we need to verify current host initiator is registered in the igroup before allowing access
439+
Incase it is not , add it and proceed for lun-mapping
440+
*/
441+
}
442+
logger.info("grantAccess: Igroup {} is present now with initiators {} ", accessGroup.getIgroup().getName(), accessGroup.getIgroup().getInitiators());
443+
// Create or retrieve existing LUN mapping
444+
String lunNumber = sanStrategy.ensureLunMapped(svmName, cloudStackVolumeName, accessGroupName);
445+
446+
// Update volume path if changed (e.g., after migration or re-mapping)
447+
String iscsiPath = OntapStorageConstants.SLASH + storagePool.getPath() + OntapStorageConstants.SLASH + lunNumber;
448+
if (volumeVO.getPath() == null || !volumeVO.getPath().equals(iscsiPath)) {
449+
volumeVO.set_iScsiName(iscsiPath);
450+
volumeVO.setPath(iscsiPath);
451+
}
452+
}
453+
449454
/**
450455
* Revokes a host's access to a volume.
451456
*/
@@ -505,42 +510,61 @@ private void revokeAccessForVolume(StoragePoolVO storagePool, VolumeVO volumeVO,
505510

506511
// Retrieve LUN name from volume details; if missing, volume may not have been fully created
507512
VolumeDetailVO lunDetail = volumeDetailsDao.findDetail(volumeVO.getId(), OntapStorageConstants.LUN_DOT_NAME);
508-
String lunName = lunDetail != null ? lunDetail.getValue() : null;
509-
if (lunName == null) {
510-
logger.warn("revokeAccessForVolume: No LUN name found for volume [{}]; skipping revoke", volumeVO.getId());
511-
return;
512-
}
513-
514-
// Verify LUN still exists on ONTAP (may have been manually deleted)
515-
CloudStackVolume cloudStackVolume = getCloudStackVolumeByName(storageStrategy, svmName, lunName);
516-
if (cloudStackVolume == null || cloudStackVolume.getLun() == null || cloudStackVolume.getLun().getUuid() == null) {
517-
logger.warn("revokeAccessForVolume: LUN for volume [{}] not found on ONTAP, skipping revoke", volumeVO.getId());
518-
return;
519-
}
520-
521-
// Verify igroup still exists on ONTAP
522-
AccessGroup accessGroup = getAccessGroupByName(storageStrategy, svmName, accessGroupName);
523-
if (accessGroup == null || accessGroup.getIgroup() == null || accessGroup.getIgroup().getUuid() == null) {
524-
logger.warn("revokeAccessForVolume: iGroup [{}] not found on ONTAP, skipping revoke", accessGroupName);
525-
return;
526-
}
527-
528-
// Verify host initiator is in the igroup before attempting to remove mapping
529-
SANStrategy sanStrategy = (UnifiedSANStrategy) storageStrategy;
530-
if (!sanStrategy.validateInitiatorInAccessGroup(host.getStorageUrl(), svmName, accessGroup.getIgroup())) {
531-
logger.warn("revokeAccessForVolume: Initiator [{}] is not in iGroup [{}], skipping revoke",
532-
host.getStorageUrl(), accessGroupName);
533-
return;
534-
}
513+
ValidateRevoke result = getValidateRevoke(volumeVO, host, lunDetail, storageStrategy, svmName, accessGroupName);
514+
if (result == null) return;
535515

536516
// Remove the LUN mapping from the igroup
537517
Map<String, String> disableLogicalAccessMap = new HashMap<>();
538-
disableLogicalAccessMap.put(OntapStorageConstants.LUN_DOT_UUID, cloudStackVolume.getLun().getUuid());
539-
disableLogicalAccessMap.put(OntapStorageConstants.IGROUP_DOT_UUID, accessGroup.getIgroup().getUuid());
518+
disableLogicalAccessMap.put(OntapStorageConstants.LUN_DOT_UUID, result.cloudStackVolume.getLun().getUuid());
519+
disableLogicalAccessMap.put(OntapStorageConstants.IGROUP_DOT_UUID, result.accessGroup.getIgroup().getUuid());
540520
storageStrategy.disableLogicalAccess(disableLogicalAccessMap);
541521

542522
logger.info("revokeAccessForVolume: Successfully revoked access to LUN [{}] for host [{}]",
543-
lunName, host.getName());
523+
result.lunName, host.getName());
524+
}
525+
}
526+
527+
@Nullable
528+
private ValidateRevoke getValidateRevoke(VolumeVO volumeVO, Host host, VolumeDetailVO lunDetail, StorageStrategy storageStrategy, String svmName, String accessGroupName) {
529+
String lunName = lunDetail != null ? lunDetail.getValue() : null;
530+
if (lunName == null) {
531+
logger.warn("revokeAccessForVolume: No LUN name found for volume [{}]; skipping revoke", volumeVO.getId());
532+
return null;
533+
}
534+
535+
// Verify LUN still exists on ONTAP (may have been manually deleted)
536+
CloudStackVolume cloudStackVolume = getCloudStackVolumeByName(storageStrategy, svmName, lunName);
537+
if (cloudStackVolume == null || cloudStackVolume.getLun() == null || cloudStackVolume.getLun().getUuid() == null) {
538+
logger.warn("revokeAccessForVolume: LUN for volume [{}] not found on ONTAP, skipping revoke", volumeVO.getId());
539+
return null;
540+
}
541+
542+
// Verify igroup still exists on ONTAP
543+
AccessGroup accessGroup = getAccessGroupByName(storageStrategy, svmName, accessGroupName);
544+
if (accessGroup == null || accessGroup.getIgroup() == null || accessGroup.getIgroup().getUuid() == null) {
545+
logger.warn("revokeAccessForVolume: iGroup [{}] not found on ONTAP, skipping revoke", accessGroupName);
546+
return null;
547+
}
548+
549+
// Verify host initiator is in the igroup before attempting to remove mapping
550+
SANStrategy sanStrategy = (UnifiedSANStrategy) storageStrategy;
551+
if (!sanStrategy.validateInitiatorInAccessGroup(host.getStorageUrl(), svmName, accessGroup.getIgroup())) {
552+
logger.warn("revokeAccessForVolume: Initiator [{}] is not in iGroup [{}], skipping revoke",
553+
host.getStorageUrl(), accessGroupName);
554+
return null;
555+
}
556+
return new ValidateRevoke(lunName, cloudStackVolume, accessGroup);
557+
}
558+
559+
private static class ValidateRevoke {
560+
public final String lunName;
561+
public final CloudStackVolume cloudStackVolume;
562+
public final AccessGroup accessGroup;
563+
564+
public ValidateRevoke(String lunName, CloudStackVolume cloudStackVolume, AccessGroup accessGroup) {
565+
this.lunName = lunName;
566+
this.cloudStackVolume = cloudStackVolume;
567+
this.accessGroup = accessGroup;
544568
}
545569
}
546570

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/feign/model/VolumeConcise.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public class VolumeConcise {
3030
private String uuid;
3131

3232
@JsonProperty("name")
33-
3433
private String name;
3534

3635
public String getUuid() {
@@ -46,5 +45,6 @@ public String getName() {
4645
}
4746

4847
public void setName(String name) {
49-
this.name = name; }
48+
this.name = name;
49+
}
5050
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ private long validateInitializeInputs(Long capacityBytes, Long podId, Long clust
231231
throw new CloudRuntimeException("Storage pool name is null or empty, cannot create primary storage");
232232
}
233233

234-
if (StringUtils.isBlank(providerName )) {
234+
if (StringUtils.isBlank(providerName)) {
235235
throw new CloudRuntimeException("Provider name is null or empty, cannot create primary storage");
236236
}
237237

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,9 @@ public abstract JobResponse revertSnapshotForCloudStackVolume(String snapshotNam
594594
* //TODO for NFS 3.0 and NFS 4.1 protocols (e.g., export rule management)
595595
* //TODO for Nvme/TCP and Nvme/FC protocols
596596
* @param values map including SVM name, LUN name, and igroup name (for SAN) or equivalent for NAS
597-
* @return map containing logical unit number for the new/existing mapping (SAN) or relevant info for NAS
597+
* @return String containing logical unit number for the new/existing mapping (SAN) or relevant info for NAS
598598
*/
599-
abstract public Map<String,String> enableLogicalAccess(Map<String,String> values);
599+
abstract public String enableLogicalAccess(Map<String,String> values);
600600

601601
/**
602602
* Method encapsulates the behavior based on the opted protocol in subclasses
@@ -609,9 +609,9 @@ public abstract JobResponse revertSnapshotForCloudStackVolume(String snapshotNam
609609
* Method encapsulates the behavior based on the opted protocol in subclasses
610610
* lunMap lookup for iSCSI/FC protocols (GET-only, no side-effects)
611611
* @param values map with SVM name, LUN name, and igroup name (for SAN) or equivalent for NAS
612-
* @return map containing logical unit number if mapping exists; otherwise null
612+
* @return String containing logical unit number if mapping exists; otherwise null
613613
*/
614-
abstract public Map<String, String> getLogicalAccess(Map<String, String> values);
614+
abstract public String getLogicalAccess(Map<String, String> values);
615615

616616
// ── FlexVolume Snapshot accessors ────────────────────────────────────────
617617

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public AccessGroup getAccessGroup(Map<String, String> values) {
202202
}
203203

204204
@Override
205-
public Map <String, String> enableLogicalAccess(Map<String, String> values) {
205+
public String enableLogicalAccess(Map<String, String> values) {
206206
return null;
207207
}
208208

@@ -211,8 +211,8 @@ public void disableLogicalAccess(Map<String, String> values) {
211211
}
212212

213213
@Override
214-
public Map<String, String> getLogicalAccess(Map<String, String> values) {
215-
return Map.of();
214+
public String getLogicalAccess(Map<String, String> values) {
215+
return null;
216216
}
217217

218218
private ExportPolicy createExportPolicy(String svmName, ExportPolicy policy) {

0 commit comments

Comments
 (0)