Skip to content

Commit 34e910c

Browse files
piyush5netapprajiv-jain-netapp
authored andcommitted
bugfix/CSTACKEX-147: Deletion of non last VM on any host still shows … (#46)
1 parent cddacd1 commit 34e910c

1 file changed

Lines changed: 52 additions & 3 deletions

File tree

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

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,23 +350,72 @@ private boolean hasOtherActiveLuns(String host, int port, String iqn, String lun
350350
}
351351
for (java.io.File entry : entries) {
352352
String name = entry.getName();
353-
if (name.startsWith(prefix) && !name.equals(prefix + lun)) {
353+
// Skip partition entries (e.g. lun-0-part1, lun-0-part2) — these are not
354+
// independent LUNs, they are partition symlinks for the same LUN disk.
355+
// Only count actual LUN entries (no "-part" suffix after the lun number).
356+
if (name.startsWith(prefix) && !name.equals(prefix + lun) && !name.contains("-part")) {
354357
logger.debug("Found other active LUN on same target: " + name);
355358
return true;
356359
}
357360
}
358361
return false;
359362
}
360363

364+
/**
365+
* Removes a single stale SCSI device from the kernel using the sysfs interface.
366+
*
367+
* When ONTAP unmaps a LUN from the host's igroup, the by-path symlink and the
368+
* underlying SCSI device (/dev/sdX) remain present in the kernel until explicitly
369+
* removed — the kernel does not auto-remove devices from live iSCSI sessions.
370+
*
371+
* This method resolves the by-path symlink to the real block device name (e.g. sdd),
372+
* then writes "1" to /sys/block/<dev>/device/delete — the standard Linux kernel SCSI
373+
* API for removing a single device without tearing down the entire iSCSI session.
374+
* Once the kernel processes the delete, it also removes the by-path symlink.
375+
*
376+
* This is used instead of iscsiadm --logout when other LUNs on the same IQN are still
377+
* active (ONTAP single-IQN-per-SVM model), since logout would tear down ALL LUNs.
378+
*/
379+
private void removeStaleScsiDevice(String host, int port, String iqn, String lun) {
380+
String byPath = getByPath(host, port, "/" + iqn + "/" + lun);
381+
java.nio.file.Path byPathLink = java.nio.file.Paths.get(byPath);
382+
if (!java.nio.file.Files.exists(byPathLink)) {
383+
logger.debug("by-path entry for LUN " + lun + " already gone, nothing to remove");
384+
return;
385+
}
386+
try {
387+
java.nio.file.Path realDevice = byPathLink.toRealPath();
388+
String devName = realDevice.getFileName().toString();
389+
java.io.File deleteFile = new java.io.File("/sys/block/" + devName + "/device/delete");
390+
if (!deleteFile.exists()) {
391+
logger.warn("sysfs delete entry not found for device " + devName + " — cannot remove stale SCSI device");
392+
return;
393+
}
394+
try (java.io.FileWriter fw = new java.io.FileWriter(deleteFile)) {
395+
fw.write("1");
396+
}
397+
logger.info("Removed stale SCSI device " + devName + " for LUN /" + iqn + "/" + lun + " via sysfs");
398+
} catch (Exception e) {
399+
logger.warn("Failed to remove stale SCSI device for LUN /" + iqn + "/" + lun + ": " + e.getMessage());
400+
}
401+
}
402+
361403
private boolean disconnectPhysicalDisk(String host, int port, String iqn, String lun) {
362404
// Check if other LUNs on the same IQN target are still in use.
363405
// ONTAP (and similar) uses a single IQN per SVM with multiple LUNs.
364406
// Doing iscsiadm --logout tears down the ENTIRE target session,
365407
// which would destroy access to ALL LUNs — not just the one being disconnected.
366408
if (hasOtherActiveLuns(host, port, iqn, lun)) {
367409
logger.info("Skipping iSCSI logout for /" + iqn + "/" + lun +
368-
" — other LUNs on the same target are still active");
369-
return true;
410+
" — other LUNs on the same target are still active. Removing stale SCSI device for this LUN only.");
411+
removeStaleScsiDevice(host, port, iqn, lun);
412+
// After removing this LUN's device, re-check: if no other LUNs remain active,
413+
// If it is the last one then must logout to clean up the iSCSI session entirely.
414+
if (hasOtherActiveLuns(host, port, iqn, lun)) {
415+
logger.info("Other LUNs still active after removing /" + iqn + "/" + lun + " — session kept alive.");
416+
return true;
417+
}
418+
logger.info("No more active LUNs on target after removing /" + iqn + "/" + lun + " — proceeding with iSCSI logout.");
370419
}
371420

372421
// No other LUNs active on this target — safe to logout and delete the node record.

0 commit comments

Comments
 (0)