Skip to content

Commit 3f90227

Browse files
Srivastava, PiyushSrivastava, Piyush
authored andcommitted
Commit 16
1 parent 5e7106c commit 3f90227

File tree

5 files changed

+155
-49
lines changed

5 files changed

+155
-49
lines changed

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

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public class OntapNfsStorageAdaptor implements StorageAdaptor {
6565
private StorageLayer _storageLayer;
6666

6767
private static final Map<String, KVMStoragePool> MapStorageUuidToStoragePool = new HashMap<String, KVMStoragePool>();
68+
// Map to store volumeUuid → actual mount point path (with sanitized junction path)
69+
private static final Map<String, String> volumeToMountPointMap = new HashMap<String, String>();
6870

6971
public OntapNfsStorageAdaptor(StorageLayer storagelayer) {
7072
_storageLayer = storagelayer;
@@ -169,6 +171,10 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map<S
169171
}
170172

171173
logger.info("Successfully mounted ONTAP NFS volume: " + nfsServer + ":" + junctionPath + " at " + mountPoint);
174+
175+
// Store the mapping so other methods can find the correct mount point
176+
volumeToMountPointMap.put(volumeUuid, mountPoint);
177+
172178
return true;
173179

174180
} catch (Exception e) {
@@ -177,6 +183,21 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map<S
177183
}
178184
}
179185

186+
/**
187+
* Get the mount point for a volume UUID.
188+
* Returns the stored mount point from connectPhysicalDisk, or falls back to volumeUuid.
189+
*/
190+
private String getMountPointForVolume(String volumeUuid) {
191+
// First check if we have a stored mount point (from connectPhysicalDisk)
192+
String mountPoint = volumeToMountPointMap.get(volumeUuid);
193+
if (mountPoint != null) {
194+
return mountPoint;
195+
}
196+
197+
// Fallback: assume mount at /mnt/<volumeUuid> (old behavior)
198+
return _mountPoint + "/" + volumeUuid;
199+
}
200+
180201
/**
181202
* Disconnect (unmount) a physical disk.
182203
*
@@ -188,7 +209,7 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map<S
188209
public boolean disconnectPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
189210
logger.info("Disconnecting ONTAP NFS volume: " + volumeUuid);
190211

191-
String mountPoint = _mountPoint + "/" + volumeUuid;
212+
String mountPoint = getMountPointForVolume(volumeUuid);
192213

193214
if (!isMounted(mountPoint)) {
194215
logger.info("Volume not mounted, nothing to disconnect: " + mountPoint);
@@ -209,6 +230,10 @@ public boolean disconnectPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
209230
}
210231

211232
logger.info("Successfully unmounted ONTAP NFS volume: " + mountPoint);
233+
234+
// Remove from mapping
235+
volumeToMountPointMap.remove(volumeUuid);
236+
212237
return true;
213238

214239
} catch (Exception e) {
@@ -283,8 +308,8 @@ public boolean disconnectPhysicalDiskByPath(String localPath) {
283308
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
284309
logger.debug("Getting physical disk info for: " + volumeUuid);
285310

286-
// Path to qcow2 file: /mnt/<volumeUuid>/<volumeUuid>
287-
String mountPoint = _mountPoint + "/" + volumeUuid;
311+
// Path to qcow2 file: <mountPoint>/<volumeUuid>
312+
String mountPoint = getMountPointForVolume(volumeUuid);
288313
String diskPath = mountPoint + "/" + volumeUuid;
289314

290315
// Check if file exists - if not, this might be a new disk that needs to be created
@@ -346,10 +371,10 @@ public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, KVMStoragePool pool
346371

347372
// For ONTAP NFS, the ONTAP volume should already exist (created by management server)
348373
// We need to:
349-
// 1. Mount the per-volume NFS export
374+
// 1. Mount the per-volume NFS export (via connectPhysicalDisk)
350375
// 2. Create the qcow2 file on it
351376

352-
String mountPoint = _mountPoint + "/" + volumeUuid;
377+
String mountPoint = getMountPointForVolume(volumeUuid);
353378
String diskPath = mountPoint + "/" + volumeUuid;
354379

355380
try {
@@ -401,7 +426,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Phys
401426
public boolean deletePhysicalDisk(String volumeUuid, KVMStoragePool pool, Storage.ImageFormat format) {
402427
logger.info("Deleting ONTAP NFS physical disk: " + volumeUuid);
403428

404-
String mountPoint = _mountPoint + "/" + volumeUuid;
429+
String mountPoint = getMountPointForVolume(volumeUuid);
405430
String diskPath = mountPoint + "/" + volumeUuid;
406431

407432
try {

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.apache.cloudstack.storage.feign.model.OntapStorage;
5050
import org.apache.cloudstack.storage.provider.StorageProviderFactory;
5151
import org.apache.cloudstack.storage.service.StorageStrategy;
52+
import org.apache.cloudstack.storage.service.model.AccessGroup;
5253
import org.apache.cloudstack.storage.service.model.CloudStackVolume;
5354
import org.apache.cloudstack.storage.service.model.ProtocolType;
5455
import org.apache.cloudstack.storage.utils.Constants;
@@ -210,6 +211,43 @@ private String createCloudStackVolumeForTypeVolume(DataStore dataStore, DataObje
210211
// throw new CloudRuntimeException(errMsg);
211212
// }
212213

214+
// create export olicy and attach it to new volume created
215+
VolumeInfo volumeInfo = (VolumeInfo) dataObject;
216+
Map<String, String> volumeDetails = new HashMap<>();
217+
volumeDetails.put(Constants.VOLUME_UUID, volumeInfo.getUuid());
218+
volumeDetails.put(Constants.VOLUME_NAME, volumeInfo.getName());
219+
220+
StorageStrategy storageStrategy = getStrategyByStoragePoolDetails(details);
221+
AccessGroup accessGroup = new AccessGroup();
222+
accessGroup.setStoragePooldetails(details);
223+
accessGroup.setVolumedetails(volumeDetails);
224+
storageStrategy.createAccessGroup(accessGroup);
225+
226+
// create export policy
227+
// VolumeInfo volumeInfo = (VolumeInfo) dataObject;
228+
// String svmName = details.get(Constants.SVM_NAME);
229+
// String volumeName = volumeInfo.getName();
230+
// String volumeUUID = volumeInfo.getUuid();
231+
//
232+
// // Create the export policy
233+
// ExportPolicy policyRequest = createExportPolicyRequest(svmName,volumeName);
234+
// try {
235+
// createExportPolicy(svmName, policyRequest);
236+
// s_logger.info("ExportPolicy created: {}, now attaching this policy to storage pool volume", policyRequest.getName());
237+
//
238+
// // attach export policy to volume of storage pool
239+
// assignExportPolicyToVolume(volumeUUID,policyRequest.getName());
240+
// s_logger.info("Successfully assigned exportPolicy {} to volume {}", policyRequest.getName(), volumeName);
241+
// accessGroup.setPolicy(policyRequest);
242+
// return accessGroup;
243+
// }catch(Exception e){
244+
// s_logger.error("Exception occurred while creating access group: " + e);
245+
// throw new CloudRuntimeException("Failed to create access group: " + e);
246+
// }
247+
//
248+
249+
250+
213251
return volumeUuid;
214252
} else if (ProtocolType.ISCSI.name().equalsIgnoreCase(protocol)) {
215253
return createManagedBlockVolume(dataStore, dataObject, storagePool, details);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public boolean attachCluster(DataStore dataStore, ClusterScope scope) {
283283
accessGroupRequest.setHostsToConnect(hostsToConnect);
284284
accessGroupRequest.setScope(scope);
285285
primaryStore.setDetails(details);// setting details as it does not come from cloudstack
286-
accessGroupRequest.setPrimaryDataStoreInfo(primaryStore);
286+
//accessGroupRequest.setPrimaryDataStoreInfo(primaryStore);
287287
accessGroupRequest.setPolicy(exportPolicy);
288288
strategy.createAccessGroup(accessGroupRequest);
289289

@@ -321,7 +321,7 @@ public boolean attachZone(DataStore dataStore, ZoneScope scope, Hypervisor.Hyper
321321
accessGroupRequest.setHostsToConnect(hostsToConnect);
322322
accessGroupRequest.setScope(scope);
323323
primaryStore.setDetails(details); // setting details as it does not come from cloudstack
324-
accessGroupRequest.setPrimaryDataStoreInfo(primaryStore);
324+
//accessGroupRequest.setPrimaryDataStoreInfo(primaryStore);
325325
accessGroupRequest.setPolicy(exportPolicy);
326326
strategy.createAccessGroup(accessGroupRequest);
327327

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

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.apache.cloudstack.storage.service;
2121

22-
import com.cloud.host.HostVO;
2322
import com.cloud.utils.exception.CloudRuntimeException;
2423
import feign.FeignException;
2524
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
@@ -116,27 +115,60 @@ CloudStackVolume getCloudStackVolume(CloudStackVolume cloudstackVolume) {
116115
@Override
117116
public AccessGroup createAccessGroup(AccessGroup accessGroup) {
118117

119-
// Map<String, String> details = accessGroup.getPrimaryDataStoreInfo().getDetails();
120-
// String svmName = details.get(Constants.SVM_NAME);
121-
// String volumeUUID = details.get(Constants.VOLUME_UUID);
122-
// String volumeName = details.get(Constants.VOLUME_NAME);
123-
//
124-
// // Create the export policy
125-
// ExportPolicy policyRequest = createExportPolicyRequest(accessGroup,svmName,volumeName);
126-
// try {
127-
// createExportPolicy(svmName, policyRequest);
128-
// s_logger.info("ExportPolicy created: {}, now attaching this policy to storage pool volume", policyRequest.getName());
129-
//
130-
// // attach export policy to volume of storage pool
131-
// assignExportPolicyToVolume(volumeUUID,policyRequest.getName());
132-
// s_logger.info("Successfully assigned exportPolicy {} to volume {}", policyRequest.getName(), volumeName);
133-
// accessGroup.setPolicy(policyRequest);
134-
// return accessGroup;
135-
// }catch(Exception e){
136-
// s_logger.error("Exception occurred while creating access group: " + e);
137-
// throw new CloudRuntimeException("Failed to create access group: " + e);
138-
// }
139-
return null;
118+
Map<String, String> storagePooldetails = accessGroup.getStoragePooldetails();
119+
String svmName = storagePooldetails.get(Constants.SVM_NAME);
120+
Map<String, String> volumedetails = accessGroup.getVolumedetails();
121+
String volumeUUID = volumedetails.get(Constants.VOLUME_UUID);
122+
String volumeName = volumedetails.get(Constants.VOLUME_NAME);
123+
124+
// Create the export policy
125+
ExportPolicy policyRequest = createExportPolicyRequest(accessGroup,svmName,volumeName);
126+
try {
127+
createExportPolicy(svmName, policyRequest);
128+
s_logger.info("ExportPolicy created: {}, now attaching this policy to storage pool volume", policyRequest.getName());
129+
String sanitizedName = volumeUUID.replace('-', '_');
130+
String ontapVolumeName = "cs_vol_" + sanitizedName;
131+
// get the volume from ontap using name
132+
try {
133+
// Get the AuthHeader
134+
String authHeader = Utility.generateAuthHeader(storage.getUsername(), storage.getPassword());
135+
Map<String, Object> queryParams = Map.of(Constants.NAME, ontapVolumeName);
136+
s_logger.debug("Fetching volume details for: " + volumeName);
137+
138+
OntapResponse<Volume> ontapVolume = volumeFeignClient.getVolume(authHeader, queryParams);
139+
s_logger.debug("Feign call completed. Processing response...");
140+
141+
if (ontapVolume == null) {
142+
s_logger.error("OntapResponse is null for volume: " + volumeName);
143+
throw new CloudRuntimeException("Failed to fetch volume " + volumeName + ": Response is null");
144+
}
145+
s_logger.debug("OntapResponse is not null. Checking records field...");
146+
147+
if (ontapVolume.getRecords() == null) {
148+
s_logger.error("OntapResponse.records is null for volume: " + volumeName);
149+
throw new CloudRuntimeException("Failed to fetch volume " + volumeName + ": Records list is null");
150+
}
151+
s_logger.debug("Records field is not null. Size: " + ontapVolume.getRecords().size());
152+
153+
if (ontapVolume.getRecords().isEmpty()) {
154+
s_logger.error("OntapResponse.records is empty for volume: " + volumeName);
155+
throw new CloudRuntimeException("Failed to fetch volume " + volumeName + ": No records found");
156+
}
157+
Volume onpvolume = ontapVolume.getRecords().get(0);
158+
s_logger.info("Volume retrieved successfully: " + volumeName + ", UUID: " + onpvolume.getUuid());
159+
// attach export policy to volume of storage pool
160+
assignExportPolicyToVolume(onpvolume.getUuid(),policyRequest.getName());
161+
s_logger.info("Successfully assigned exportPolicy {} to volume {}", policyRequest.getName(), volumeName);
162+
accessGroup.setPolicy(policyRequest);
163+
return accessGroup;
164+
} catch (Exception e) {
165+
s_logger.error("Exception while retrieving volume details for: " + volumeName, e);
166+
throw new CloudRuntimeException("Failed to fetch volume: " + volumeName + ". Error: " + e.getMessage(), e);
167+
}
168+
}catch(Exception e){
169+
s_logger.error("Exception occurred while creating access group: " + e);
170+
throw new CloudRuntimeException("Failed to create access group: " + e);
171+
}
140172
}
141173

142174
@Override
@@ -374,17 +406,21 @@ private ExportPolicy createExportPolicyRequest(AccessGroup accessGroup,String sv
374406
ExportRule exportRule = new ExportRule();
375407

376408
List<ExportRule.ExportClient> exportClients = new ArrayList<>();
377-
List<HostVO> hosts = accessGroup.getHostsToConnect();
378-
for (HostVO host : hosts) {
379-
String hostStorageIp = host.getStorageIpAddress();
380-
String ip = (hostStorageIp != null && !hostStorageIp.isEmpty())
381-
? hostStorageIp
382-
: host.getPrivateIpAddress();
383-
String ipToUse = ip + "/31";
384-
ExportRule.ExportClient exportClient = new ExportRule.ExportClient();
385-
exportClient.setMatch(ipToUse);
386-
exportClients.add(exportClient);
387-
}
409+
// List<HostVO> hosts = accessGroup.getHostsToConnect();
410+
// for (HostVO host : hosts) {
411+
// String hostStorageIp = host.getStorageIpAddress();
412+
// String ip = (hostStorageIp != null && !hostStorageIp.isEmpty())
413+
// ? hostStorageIp
414+
// : host.getPrivateIpAddress();
415+
// String ipToUse = ip + "/31";
416+
// ExportRule.ExportClient exportClient = new ExportRule.ExportClient();
417+
// exportClient.setMatch(ipToUse);
418+
// exportClients.add(exportClient);
419+
// }
420+
421+
ExportRule.ExportClient exportClient = new ExportRule.ExportClient();
422+
String ipToUse = "0.0.0.0/0";
423+
exportClient.setMatch(ipToUse);
388424
exportRule.setClients(exportClients);
389425
exportRule.setProtocols(List.of(ExportRule.ProtocolsEnum.any));
390426
exportRule.setRoRule(List.of("sys")); // Use sys (Unix UID/GID) authentication for NFS

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@
2020
package org.apache.cloudstack.storage.service.model;
2121

2222
import com.cloud.host.HostVO;
23-
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
2423
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
2524
import org.apache.cloudstack.storage.feign.model.ExportPolicy;
2625
import org.apache.cloudstack.storage.feign.model.Igroup;
2726

2827
import java.util.List;
28+
import java.util.Map;
2929

3030
public class AccessGroup {
3131

3232
private Igroup igroup;
3333
private ExportPolicy exportPolicy;
3434

3535
private List<HostVO> hostsToConnect;
36-
private PrimaryDataStoreInfo primaryDataStoreInfo;
36+
private Map<String, String> storagePooldetails;
37+
private Map<String, String> volumedetails;
3738
private Scope scope;
3839

3940

@@ -58,17 +59,23 @@ public List<HostVO> getHostsToConnect() {
5859
public void setHostsToConnect(List<HostVO> hostsToConnect) {
5960
this.hostsToConnect = hostsToConnect;
6061
}
61-
public PrimaryDataStoreInfo getPrimaryDataStoreInfo() {
62-
return primaryDataStoreInfo;
63-
}
64-
public void setPrimaryDataStoreInfo(PrimaryDataStoreInfo primaryDataStoreInfo) {
65-
this.primaryDataStoreInfo = primaryDataStoreInfo;
66-
}
6762
public Scope getScope() {
6863
return scope;
6964
}
7065
public void setScope(Scope scope) {
7166
this.scope = scope;
7267
}
68+
public Map<String, String> getStoragePooldetails() {
69+
return storagePooldetails;
70+
}
71+
public void setStoragePooldetails(Map<String, String> storagePooldetails) {
72+
this.storagePooldetails = storagePooldetails;
73+
}
74+
public Map<String, String> getVolumedetails() {
75+
return volumedetails;
76+
}
77+
public void setVolumedetails(Map<String, String> volumedetails) {
78+
this.volumedetails = volumedetails;
79+
}
7380

7481
}

0 commit comments

Comments
 (0)