Skip to content

Commit 56f18fd

Browse files
Srivastava, PiyushSrivastava, Piyush
authored andcommitted
Commit 19
1 parent 20bba51 commit 56f18fd

File tree

1 file changed

+14
-50
lines changed

1 file changed

+14
-50
lines changed

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

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,17 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map<S
136136
// Get junction path from details map (set by VolumeOrchestrator as MOUNT_POINT)
137137
// This contains the ONTAP junction path like "/cs_vol_7e72cff5_9730_46e3_80ff_fb76fd7b1dc8"
138138
String junctionPath = details != null ? details.get(DiskTO.MOUNT_POINT) : null;
139-
// Validate junction path
139+
140+
// Fallback: If MOUNT_POINT not in details, check if volumeUuid parameter itself is a junction path
141+
// (starts with /cs_vol_ or /) - this happens for ROOT volumes where vol.getPath() contains junction path
140142
if (junctionPath == null || junctionPath.isEmpty()) {
141-
logger.error("Missing junction path (MOUNT_POINT) in details for volume: " + volumeUuid);
142-
return false;
143+
if (volumeUuid != null && volumeUuid.startsWith("/")) {
144+
logger.info("volumeUuid parameter appears to be junction path: " + volumeUuid);
145+
junctionPath = volumeUuid;
146+
} else {
147+
logger.error("Missing junction path (MOUNT_POINT) in details and volumeUuid doesn't look like junction path: " + volumeUuid);
148+
return false;
149+
}
143150
}
144151
logger.info("Using junction path: " + junctionPath + " for volume: " + volumeUuid);
145152
// Create a sanitized mount point name (remove leading slash, replace special chars)
@@ -152,27 +159,27 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map<S
152159
logger.info("Volume already mounted: " + mountPoint);
153160
return true;
154161
}
155-
156162
try {
157163
// Create mount point directory
158164
_storageLayer.mkdirs(mountPoint);
159-
160165
// Mount: mount -t nfs <nfsServer>:<junctionPath> <mountPoint>
161166
String nfsServer = pool.getSourceHost();
162167
String mountCmd = "mount -t nfs " + nfsServer + ":" + junctionPath + " " + mountPoint;
163168
Script script = new Script("/bin/bash", 60000, logger);
164169
script.add("-c");
165170
script.add(mountCmd);
166171
String result = script.execute();
167-
168172
if (result != null) {
169173
logger.error("Failed to mount ONTAP NFS volume: " + volumeUuid + ", error: " + result);
170174
return false;
171175
}
172-
173176
logger.info("Successfully mounted ONTAP NFS volume: " + nfsServer + ":" + junctionPath + " at " + mountPoint);
174177
// Store the mapping so other methods can find the correct mount point
178+
// Store both volumeUuid and junctionPath as keys (in case they're different)
175179
volumeToMountPointMap.put(volumeUuid, mountPoint);
180+
if (!volumeUuid.equals(junctionPath)) {
181+
volumeToMountPointMap.put(junctionPath, mountPoint);
182+
}
176183
return true;
177184
} catch (Exception e) {
178185
logger.error("Exception mounting ONTAP NFS volume: " + volumeUuid, e);
@@ -204,9 +211,7 @@ private String getMountPointForVolume(String volumeUuid) {
204211
@Override
205212
public boolean disconnectPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
206213
logger.info("Disconnecting ONTAP NFS volume: " + volumeUuid);
207-
208214
String mountPoint = getMountPointForVolume(volumeUuid);
209-
210215
if (!isMounted(mountPoint)) {
211216
logger.info("Volume not mounted, nothing to disconnect: " + mountPoint);
212217
return true;
@@ -238,18 +243,15 @@ public boolean disconnectPhysicalDisk(Map<String, String> volumeToDisconnect) {
238243
String volumeUuid = volumeToDisconnect.get(DiskTO.UUID);
239244
// Note: POOL_UUID constant doesn't exist in DiskTO, pool info comes from other sources
240245
String poolUuid = volumeToDisconnect.get("poolUuid");
241-
242246
if (volumeUuid == null || poolUuid == null) {
243247
logger.error("Missing volume UUID or pool UUID in disconnect request");
244248
return false;
245249
}
246-
247250
KVMStoragePool pool = getStoragePool(poolUuid);
248251
if (pool == null) {
249252
logger.error("Storage pool not found: " + poolUuid);
250253
return false;
251254
}
252-
253255
return disconnectPhysicalDisk(volumeUuid, pool);
254256
}
255257

@@ -259,21 +261,16 @@ public boolean disconnectPhysicalDiskByPath(String localPath) {
259261
if (localPath == null || !localPath.startsWith(_mountPoint + "/")) {
260262
return false; // Not our path
261263
}
262-
263264
String[] pathParts = localPath.split("/");
264265
if (pathParts.length < 4) {
265266
return false;
266267
}
267-
268268
String volumeUuid = pathParts[2]; // /mnt/<volumeUuid>/...
269269
String mountPoint = _mountPoint + "/" + volumeUuid;
270-
271270
logger.info("Disconnecting ONTAP NFS volume by path: " + localPath + " -> " + volumeUuid);
272-
273271
if (!isMounted(mountPoint)) {
274272
return true;
275273
}
276-
277274
try {
278275
Script script = new Script("/bin/bash", 60000, logger);
279276
script.add("-c");
@@ -297,7 +294,6 @@ public boolean disconnectPhysicalDiskByPath(String localPath) {
297294
@Override
298295
public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
299296
logger.debug("Getting physical disk info for: " + volumeUuid);
300-
301297
// Path to qcow2 file: <mountPoint>/<volumeUuid>
302298
String mountPoint = getMountPointForVolume(volumeUuid);
303299
String diskPath = mountPoint + "/" + volumeUuid;
@@ -312,7 +308,6 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
312308
return disk;
313309
}
314310
KVMPhysicalDisk disk = new KVMPhysicalDisk(diskPath, volumeUuid, pool);
315-
316311
try {
317312
// Get disk info using qemu-img info
318313
QemuImgFile imgFile = new QemuImgFile(diskPath);
@@ -325,19 +320,16 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) {
325320
} else if ("raw".equalsIgnoreCase(format)) {
326321
disk.setFormat(PhysicalDiskFormat.RAW);
327322
}
328-
329323
String sizeStr = info.get("virtual_size");
330324
if (sizeStr != null) {
331325
disk.setVirtualSize(Long.parseLong(sizeStr));
332326
disk.setSize(Long.parseLong(sizeStr));
333327
}
334-
335328
} catch (QemuImgException | LibvirtException e) {
336329
logger.warn("Failed to get qemu-img info for: " + diskPath + ", " + e.getMessage());
337330
// Set default format if qemu-img fails
338331
disk.setFormat(PhysicalDiskFormat.QCOW2);
339332
}
340-
341333
return disk;
342334
}
343335

@@ -374,11 +366,9 @@ public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, KVMStoragePool pool
374366
throw new CloudRuntimeException("ONTAP volume not mounted for: " + volumeUuid +
375367
". Volume must be mounted before creating disk.");
376368
}
377-
378369
// Create qcow2 file using qemu-img
379370
QemuImgFile destFile = new QemuImgFile(diskPath, size, format);
380371
QemuImg qemuImg = new QemuImg(0);
381-
382372
Map<String, String> options = new HashMap<>();
383373
if (format == PhysicalDiskFormat.QCOW2 && provisioningType == Storage.ProvisioningType.THIN) {
384374
options.put("preallocation", "metadata");
@@ -387,19 +377,14 @@ public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, KVMStoragePool pool
387377
} else if (format == PhysicalDiskFormat.QCOW2 && provisioningType == Storage.ProvisioningType.FAT) {
388378
options.put("preallocation", "falloc");
389379
}
390-
391380
qemuImg.create(destFile, options);
392-
393381
logger.info("Successfully created qcow2 file: " + diskPath);
394-
395382
// Return disk object
396383
KVMPhysicalDisk disk = new KVMPhysicalDisk(diskPath, volumeUuid, pool);
397384
disk.setFormat(format);
398385
disk.setSize(size);
399386
disk.setVirtualSize(size);
400-
401387
return disk;
402-
403388
} catch (QemuImgException | LibvirtException e) {
404389
logger.error("Failed to create qcow2 file: " + diskPath, e);
405390
throw new CloudRuntimeException("Failed to create ONTAP NFS disk: " + e.getMessage());
@@ -415,32 +400,25 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Phys
415400
@Override
416401
public boolean deletePhysicalDisk(String volumeUuid, KVMStoragePool pool, Storage.ImageFormat format) {
417402
logger.info("Deleting ONTAP NFS physical disk: " + volumeUuid);
418-
419403
String mountPoint = getMountPointForVolume(volumeUuid);
420404
String diskPath = mountPoint + "/" + volumeUuid;
421-
422405
try {
423406
// Delete qcow2 file
424407
if (_storageLayer.exists(diskPath)) {
425408
_storageLayer.delete(diskPath);
426409
logger.info("Deleted qcow2 file: " + diskPath);
427410
}
428-
429411
// Unmount the volume
430412
if (isMounted(mountPoint)) {
431413
disconnectPhysicalDisk(volumeUuid, pool);
432414
}
433-
434415
// Remove mount point directory
435416
if (_storageLayer.exists(mountPoint)) {
436417
_storageLayer.delete(mountPoint);
437418
}
438-
439419
// Note: The ONTAP volume itself is deleted by OntapPrimaryDatastoreDriver via API
440-
441420
logger.info("Successfully deleted ONTAP NFS disk: " + volumeUuid);
442421
return true;
443-
444422
} catch (Exception e) {
445423
logger.error("Failed to delete ONTAP NFS disk: " + volumeUuid, e);
446424
return false;
@@ -492,34 +470,27 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk srcDisk, String name, KV
492470
public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk srcDisk, String name, KVMStoragePool destPool, int timeout,
493471
byte[] srcPassphrase, byte[] dstPassphrase, Storage.ProvisioningType provisioningType) {
494472
logger.info("Copying disk: " + srcDisk.getName() + " -> " + name);
495-
496473
try {
497474
// Destination path: /mnt/<name>/<name>
498475
String destMountPoint = _mountPoint + "/" + name;
499476
String destPath = destMountPoint + "/" + name;
500-
501477
// Ensure destination volume is mounted
502478
if (!isMounted(destMountPoint)) {
503479
throw new CloudRuntimeException("Destination ONTAP volume not mounted: " + name);
504480
}
505-
506481
// Use qemu-img convert for the copy
507482
QemuImgFile srcFile = new QemuImgFile(srcDisk.getPath());
508483
QemuImgFile destFile = new QemuImgFile(destPath, srcDisk.getVirtualSize(), srcDisk.getFormat());
509-
510484
QemuImg qemuImg = new QemuImg(timeout);
511485
// Note: QemuImg.convert doesn't take passphrase parameters in this version
512486
// For encrypted volumes, use options map instead
513487
qemuImg.convert(srcFile, destFile);
514-
515488
logger.info("Successfully copied disk to: " + destPath);
516-
517489
// Return destination disk
518490
KVMPhysicalDisk destDisk = new KVMPhysicalDisk(destPath, name, destPool);
519491
destDisk.setFormat(srcDisk.getFormat());
520492
destDisk.setSize(srcDisk.getSize());
521493
destDisk.setVirtualSize(srcDisk.getVirtualSize());
522-
523494
return destDisk;
524495

525496
} catch (QemuImgException | LibvirtException e) {
@@ -532,25 +503,18 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk srcDisk, String name, KV
532503
public KVMPhysicalDisk createTemplateFromDirectDownloadFile(String templateFilePath, String destTemplatePath,
533504
KVMStoragePool destPool, Storage.ImageFormat format, int timeout) {
534505
logger.info("Creating template from direct download: " + templateFilePath + " -> " + destTemplatePath);
535-
536506
try {
537507
// Use qemu-img convert to create template
538508
QemuImgFile srcFile = new QemuImgFile(templateFilePath);
539509
QemuImgFile destFile = new QemuImgFile(destTemplatePath);
540-
541510
QemuImg qemuImg = new QemuImg(timeout);
542511
qemuImg.convert(srcFile, destFile);
543-
544512
logger.info("Successfully created template: " + destTemplatePath);
545-
546513
// Get the template name from path
547514
String name = destTemplatePath.substring(destTemplatePath.lastIndexOf("/") + 1);
548-
549515
KVMPhysicalDisk disk = new KVMPhysicalDisk(destTemplatePath, name, destPool);
550516
disk.setFormat(PhysicalDiskFormat.QCOW2);
551-
552517
return disk;
553-
554518
} catch (QemuImgException | LibvirtException e) {
555519
logger.error("Failed to create template from direct download", e);
556520
throw new CloudRuntimeException("Failed to create template: " + e.getMessage());

0 commit comments

Comments
 (0)