Skip to content

Commit 121bbfe

Browse files
Srivastava, PiyushSrivastava, Piyush
authored andcommitted
feature/CSTACKEX-122: Comments resolution
1 parent 25cd46c commit 121bbfe

File tree

8 files changed

+48
-57
lines changed

8 files changed

+48
-57
lines changed

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ public class VolumeServiceImpl implements VolumeService {
222222
@Inject
223223
protected DiskOfferingDao diskOfferingDao;
224224

225+
private static final String ONTAP_PROVIDER_NAME = "NetApp ONTAP";
226+
225227
public VolumeServiceImpl() {
226228
}
227229

@@ -731,16 +733,12 @@ protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher<VolumeServic
731733
TemplateObjectTO templateObjectTo = (TemplateObjectTO)answer.getNewData();
732734

733735
// For NFS managed storage, preserve the volume UUID path to avoid file collision
734-
// For iSCSI, update path as before (iSCSI uses _iScsiName field for actual LUN access)
735736
PrimaryDataStore primaryDataStore = (PrimaryDataStore) volumeInfo.getDataStore();
736-
if (primaryDataStore != null && primaryDataStore.getPoolType() == StoragePoolType.NetworkFilesystem) {
737-
if (logger.isDebugEnabled()) {
738-
logger.debug("NFS managed storage - preserving volume path: " + volume.getPath() + " (not overwriting with template path: " + templateObjectTo.getPath() + ")");
739-
}
740-
} else {
737+
if (primaryDataStore.isManaged() && ONTAP_PROVIDER_NAME.equals(primaryDataStore.getStorageProviderName()) && primaryDataStore.getPoolType() == StoragePoolType.NetworkFilesystem) {
738+
logger.debug("NFS managed storage - preserving volume path: " + volume.getPath() + " (not overwriting with template path: " + templateObjectTo.getPath() + ")");
739+
}else {
741740
volume.setPath(templateObjectTo.getPath());
742741
}
743-
744742
if (templateObjectTo.getFormat() != null) {
745743
volume.setFormat(templateObjectTo.getFormat());
746744
}

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

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,8 @@ public void createAsync(DataStore dataStore, DataObject dataObject, AsyncComplet
163163

164164
s_logger.info("createAsync: Created LUN [{}] for volume [{}]. LUN mapping will occur during grantAccess() to per-host igroup.",
165165
lunName, volumeVO.getId());
166-
167-
// Path will be set during grantAccess when LUN is mapped and we get the LUN ID
168-
// Return LUN name as identifier for CloudStack tracking
169-
volumeVO.set_iScsiName(null);
170-
volumeVO.setPath(null);
171166
createCmdResult = new CreateCmdResult(lunName, new Answer(null, true, null));
172167
} else if (ProtocolType.NFS3.name().equalsIgnoreCase(details.get(Constants.PROTOCOL))) {
173-
// For NFS, set path to volume UUID to ensure uniqueness
174-
// This prevents multiple VMs from using the same template file path
175-
volumeVO.setPath(volInfo.getUuid());
176168
createCmdResult = new CreateCmdResult(volInfo.getUuid(), new Answer(null, true, null));
177169
s_logger.info("createAsync: Managed NFS volume [{}] with path [{}] associated with pool {}",
178170
volumeVO.getId(), volInfo.getUuid(), storagePool.getId());
@@ -331,7 +323,7 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
331323
Igroup igroup = new Igroup();
332324
AccessGroup accessGroup = sanStrategy.getAccessGroup(getAccessGroupMap);
333325
if(accessGroup == null || accessGroup.getIgroup() == null) {
334-
s_logger.info("grantAccess: Igroup does not exist for the host: Need to create Igroup " + host.getName());
326+
s_logger.info("grantAccess: Igroup {} does not exist for the host {} : Need to create Igroup for the host ", accessGroupName, host.getName());
335327
// create the igroup for the host and perform lun-mapping
336328
accessGroup = new AccessGroup();
337329
List<HostVO> hosts = new ArrayList<>();
@@ -342,14 +334,14 @@ public boolean grantAccess(DataObject dataObject, Host host, DataStore dataStore
342334
}else{
343335
s_logger.info("grantAccess: Igroup {} already exist for the host {}: ", accessGroup.getIgroup().getName() ,host.getName());
344336
igroup = accessGroup.getIgroup();
345-
// TODO
346-
// Verify host initiator is registered in the igroup before allowing access
347-
// if (sanStrategy.validateInitiatorInAccessGroup(host.getStorageUrl(), svmName, accessGroup.getIgroup())) {
348-
// // add host initiator to the igroup ? or fail here ?
349-
// }
350-
// Use the existing igroup and perform lun-mapping
337+
/* TODO Below cases will be covered later, for now they will be a pre-requisite on customer side
338+
1. Igroup exist with the same name but host initiator has been rempved
339+
2. Igroup exist with the same name but host initiator has been changed may be due to new NIC or new adapter
340+
In both cases we need to verify current host initiator is registered in the igroup before allowing access
341+
Incase it is not , add it and proceed for lun-mapping
342+
*/
351343
}
352-
344+
s_logger.info("grantAccess: Igroup {} is present now with initiators {} ", accessGroup.getIgroup().getName(), accessGroup.getIgroup().getInitiators());
353345
// Create or retrieve existing LUN mapping
354346
String lunNumber = sanStrategy.ensureLunMapped(svmName, cloudStackVolumeName, accessGroupName);
355347

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,6 @@ public boolean attachCluster(DataStore dataStore, ClusterScope scope) {
282282
PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)dataStore;
283283
List<HostVO> hostsToConnect = _resourceMgr.getEligibleUpAndEnabledHostsInClusterForStorageConnection(primaryStore);
284284
logger.debug("attachCluster: Eligible Up and Enabled hosts: {} in cluster {}", hostsToConnect, primaryStore.getClusterId());
285-
if(hostsToConnect.isEmpty()) {
286-
s_logger.info("attachCluster: No hosts found for primary storage");
287-
throw new CloudRuntimeException("attachCluster: No hosts found for primary storage");
288-
}
289-
290285
Map<String, String> details = storagePoolDetailsDao.listDetailsKeyPairs(primaryStore.getId());
291286
StorageStrategy strategy = Utility.getStrategyByStoragePoolDetails(details);
292287

@@ -300,12 +295,12 @@ public boolean attachCluster(DataStore dataStore, ClusterScope scope) {
300295
logger.debug("attachCluster: Attaching the pool to each of the host in the cluster: {}", primaryStore.getClusterId());
301296
// We need to create export policy at pool level and igroup at host level(in grantAccess)
302297
if (ProtocolType.NFS3.name().equalsIgnoreCase(details.get(Constants.PROTOCOL))) {
298+
// If there are no eligible host, export policy or igroup will not be created and will be taken as part of HostListener
303299
if (!hostsIdentifier.isEmpty()) {
304300
try {
305301
AccessGroup accessGroupRequest = new AccessGroup();
306302
accessGroupRequest.setHostsToConnect(hostsToConnect);
307303
accessGroupRequest.setScope(scope);
308-
primaryStore.setDetails(details);// setting details as it does not come from cloudstack
309304
accessGroupRequest.setStoragePoolId(storagePool.getId());
310305
strategy.createAccessGroup(accessGroupRequest);
311306
} catch (Exception e) {
@@ -352,11 +347,6 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper
352347
PrimaryDataStoreInfo primaryStore = (PrimaryDataStoreInfo)dataStore;
353348
List<HostVO> hostsToConnect = _resourceMgr.getEligibleUpAndEnabledHostsInZoneForStorageConnection(dataStore, scope.getScopeId(), Hypervisor.HypervisorType.KVM);
354349
logger.debug(String.format("In createPool. Attaching the pool to each of the hosts in %s.", hostsToConnect));
355-
if(hostsToConnect.isEmpty()) {
356-
s_logger.info("attachCluster: No hosts found for primary storage");
357-
throw new CloudRuntimeException("attachCluster: No hosts found for primary storage");
358-
}
359-
360350
Map<String, String> details = storagePoolDetailsDao.listDetailsKeyPairs(primaryStore.getId());
361351
StorageStrategy strategy = Utility.getStrategyByStoragePoolDetails(details);
362352

@@ -370,12 +360,12 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper
370360

371361
// We need to create export policy at pool level and igroup at host level
372362
if (ProtocolType.NFS3.name().equalsIgnoreCase(details.get(Constants.PROTOCOL))) {
363+
// If there are no eligible host, export policy or igroup will not be created and will be taken as part of HostListener
373364
if (!hostsIdentifier.isEmpty()) {
374365
try {
375366
AccessGroup accessGroupRequest = new AccessGroup();
376367
accessGroupRequest.setHostsToConnect(hostsToConnect);
377368
accessGroupRequest.setScope(scope);
378-
primaryStore.setDetails(details); // setting details as it does not come from cloudstack
379369
accessGroupRequest.setStoragePoolId(storagePool.getId());
380370
strategy.createAccessGroup(accessGroupRequest);
381371
} catch (Exception e) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public SANStrategy(OntapStorage ontapStorage) {
4848
*
4949
* @param hostInitiator the host initiator IQN
5050
* @param svmName the SVM name
51-
* @param accessGroupName the igroup name
51+
* @param igroup the igroup
5252
* @return true if the initiator is found in the igroup, false otherwise
5353
*/
5454
public boolean validateInitiatorInAccessGroup(String hostInitiator, String svmName, Igroup igroup) {

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ public Volume createStorageVolume(String volumeName, Long size) {
267267

268268
if (ontapVolume == null || ontapVolume.getRecords() == null || ontapVolume.getRecords().isEmpty()) {
269269
s_logger.error("OntapResponse is null for volume: " + volumeName);
270-
throw new CloudRuntimeException("Failed to fetch volume " + volumeName + ": Response is null");
270+
throw new CloudRuntimeException("Failed to fetch volume " + volumeName + ": no records found");
271271
}
272272
Volume volume = ontapVolume.getRecords().get(0);
273273
s_logger.info("Volume retrieved successfully: " + volumeName + ", UUID: " + volume.getUuid());
@@ -278,11 +278,26 @@ public Volume createStorageVolume(String volumeName, Long size) {
278278
}
279279
}
280280

281+
/**
282+
* Updates ONTAP Flex-Volume
283+
* Eligible only for Unified ONTAP storage
284+
* throw exception in case of disaggregated ONTAP storage
285+
*
286+
* @param volume the volume to update
287+
* @return the updated Volume object
288+
*/
281289
public Volume updateStorageVolume(Volume volume) {
282290
//TODO
283291
return null;
284292
}
285293

294+
/**
295+
* Delete ONTAP Flex-Volume
296+
* Eligible only for Unified ONTAP storage
297+
* throw exception in case of disaggregated ONTAP storage
298+
*
299+
* @param volume the volume to delete
300+
*/
286301
public void deleteStorageVolume(Volume volume) {
287302
s_logger.info("Deleting ONTAP volume by name: " + volume.getName() + " and uuid: " + volume.getUuid());
288303
// Calling the VolumeFeignClient to delete the volume
@@ -302,7 +317,14 @@ public void deleteStorageVolume(Volume volume) {
302317
}
303318
s_logger.info("ONTAP volume deletion process completed for volume: " + volume.getName());
304319
}
305-
320+
/**
321+
* Gets ONTAP Flex-Volume
322+
* Eligible only for Unified ONTAP storage
323+
* throw exception in case of disaggregated ONTAP storage
324+
*
325+
* @param volume the volume to retrieve
326+
* @return the retrieved Volume object
327+
*/
306328
public Volume getStorageVolume(Volume volume) {
307329
//TODO
308330
return null;

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

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
3232
import org.apache.cloudstack.storage.command.CreateObjectCommand;
3333
import org.apache.cloudstack.storage.command.DeleteCommand;
34-
import com.cloud.agent.api.to.DataTO;
35-
import org.apache.cloudstack.storage.to.VolumeObjectTO;
3634
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
3735
import org.apache.cloudstack.storage.feign.FeignClientFactory;
3836
import org.apache.cloudstack.storage.feign.client.JobFeignClient;
@@ -89,10 +87,10 @@ public void setOntapStorage(OntapStorage ontapStorage) {
8987
public CloudStackVolume createCloudStackVolume(CloudStackVolume cloudstackVolume) {
9088
s_logger.info("createCloudStackVolume: Create cloudstack volume " + cloudstackVolume);
9189
try {
92-
// Step 1: set cloudstack volume metadata and get the volumeUuid
90+
// Step 1: set cloudstack volume metadata
9391
String volumeUuid = updateCloudStackVolumeMetadata(cloudstackVolume.getDatastoreId(), cloudstackVolume.getVolumeInfo());
94-
// Step 2: Send command to KVM host with explicit volumeUuid to avoid stale cached path
95-
Answer answer = createVolumeOnKVMHost(cloudstackVolume.getVolumeInfo(), volumeUuid);
92+
// Step 2: Send command to KVM host to create qcow2 file using qemu-img
93+
Answer answer = createVolumeOnKVMHost(cloudstackVolume.getVolumeInfo());
9694
if (answer == null || !answer.getResult()) {
9795
String errMsg = answer != null ? answer.getDetails() : "Failed to create qcow2 on KVM host";
9896
s_logger.error("createCloudStackVolume: " + errMsg);
@@ -482,7 +480,7 @@ private String updateCloudStackVolumeMetadata(String dataStoreId, DataObject vol
482480
String volumeUuid = volumeInfo.getUuid();
483481
volume.setPoolType(Storage.StoragePoolType.NetworkFilesystem);
484482
volume.setPoolId(Long.parseLong(dataStoreId));
485-
volume.setPath(volumeUuid); // Filename for qcow2 file - unique per volume
483+
volume.setPath(volumeUuid); // Filename for qcow2 file
486484
volumeDao.update(volume.getId(), volume);
487485
s_logger.info("Updated volume path to {} for volume ID {}", volumeUuid, volumeId);
488486
return volumeUuid;
@@ -492,19 +490,12 @@ private String updateCloudStackVolumeMetadata(String dataStoreId, DataObject vol
492490
}
493491
}
494492

495-
private Answer createVolumeOnKVMHost(DataObject volumeInfo, String correctPath) {
496-
s_logger.info("createVolumeOnKVMHost called with volumeInfo: {}, correctPath: {}", volumeInfo, correctPath);
493+
private Answer createVolumeOnKVMHost(DataObject volumeInfo) {
494+
s_logger.info("createVolumeOnKVMHost called with volumeInfo: {} ", volumeInfo);
497495

498496
try {
499-
// Get the base TO and override the path with correct value to avoid stale cached path
500-
DataTO dataTO = volumeInfo.getTO();
501-
if (dataTO instanceof VolumeObjectTO) {
502-
VolumeObjectTO volumeTO = (VolumeObjectTO) dataTO;
503-
s_logger.info("createVolumeOnKVMHost: Original TO path: {}, overriding with correct path: {}", volumeTO.getPath(), correctPath);
504-
volumeTO.setPath(correctPath); // Override stale path with correct UUID
505-
}
506497
s_logger.info("createVolumeOnKVMHost: Sending CreateObjectCommand to KVM agent for volume: {}", volumeInfo.getUuid());
507-
CreateObjectCommand cmd = new CreateObjectCommand(dataTO);
498+
CreateObjectCommand cmd = new CreateObjectCommand(volumeInfo.getTO());
508499
EndPoint ep = epSelector.select(volumeInfo);
509500
if (ep == null) {
510501
String errMsg = "No remote endpoint to send CreateObjectCommand, check if host is up";

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ public AccessGroup createAccessGroup(AccessGroup accessGroup) {
230230
ProtocolType protocol = ProtocolType.valueOf(dataStoreDetails.get(Constants.PROTOCOL));
231231

232232
// Check if all hosts support the protocol
233-
List<String> hostIdentifiers = new ArrayList<>();
234233
if (!validateProtocolSupport(accessGroup.getHostsToConnect(), protocol)) {
235234
String errMsg = "createAccessGroup: Not all hosts " + " support the protocol: " + protocol.name();
236235
throw new CloudRuntimeException(errMsg);
@@ -370,7 +369,6 @@ private boolean validateProtocolSupport(List<HostVO> hosts, ProtocolType protoco
370369
if (host == null || host.getStorageUrl() == null || host.getStorageUrl().trim().isEmpty() || !host.getStorageUrl().startsWith(protocolPrefix)) {
371370
return false;
372371
}
373-
// hostIdentifiers.add(host.getStorageUrl());
374372
}
375373
s_logger.info("validateProtocolSupportAndFetchHostsIdentifier: All hosts support the protocol: " + protocolType.name());
376374
return true;

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/utils/Utility.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public static String getIgroupName(String svmName, String hostName) {
146146
}
147147

148148
public static String generateExportPolicyName(String svmName, String volumeName){
149-
return Constants.EXPORT + Constants.HYPHEN + svmName + Constants.HYPHEN + volumeName;
149+
return Constants.CS + Constants.HYPHEN + svmName + Constants.HYPHEN + volumeName;
150150
}
151151

152152
public static String getLunName(String volName, String lunName) {

0 commit comments

Comments
 (0)