From f528fdfdb6e0b04c275711a3625f49c765731d13 Mon Sep 17 00:00:00 2001 From: "Gupta, Surya" Date: Thu, 6 Aug 2026 22:34:06 +0530 Subject: [PATCH 1/2] [CSTACKEX-233] Subsequent VM Creation is failing for ISCSI Storage Pool on Oracle Linux --- .../kvm/storage/IscsiAdmStorageAdaptor.java | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java index 495ae45a2896..d8ed59a4e66a 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java @@ -47,6 +47,9 @@ public class IscsiAdmStorageAdaptor implements StorageAdaptor { private static final Map MapStorageUuidToStoragePool = new HashMap<>(); + /** iscsiadm's ISCSI_ERR_NO_OBJS_FOUND: returned by "-m session" when no session is established. */ + private static final int ISCSI_ERR_NO_OBJS_FOUND = 21; + @Override public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map details, boolean isPrimaryStorage) { IscsiAdmStoragePool storagePool = new IscsiAdmStoragePool(uuid, host, port, storagePoolType, this); @@ -126,6 +129,8 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map null). + final boolean sessionPreExisted = sessionAlreadyActive || (result != null); + + if (sessionPreExisted) { + logger.info("sessionPreExisted : performing rescan explicitely"); rescanIscsiSessions(iqn, host, port); } @@ -156,6 +164,11 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map Date: Fri, 7 Aug 2026 16:13:02 +0530 Subject: [PATCH 2/2] [CSTACKEX-233] Added session exists error code check --- .../kvm/storage/IscsiAdmStorageAdaptor.java | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java index d8ed59a4e66a..a20fce08833d 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java @@ -50,6 +50,9 @@ public class IscsiAdmStorageAdaptor implements StorageAdaptor { /** iscsiadm's ISCSI_ERR_NO_OBJS_FOUND: returned by "-m session" when no session is established. */ private static final int ISCSI_ERR_NO_OBJS_FOUND = 21; + /** iscsiadm's ISCSI_ERR_SESS_EXISTS: returned by "--login" when the session is already logged in (e.g. Ubuntu). */ + private static final int ISCSI_SESSION_EXISTS_CODE = 15; + @Override public KVMStoragePool createStoragePool(String uuid, String host, int port, String path, String userInfo, StoragePoolType storagePoolType, Map details, boolean isPrimaryStorage) { IscsiAdmStoragePool storagePool = new IscsiAdmStoragePool(uuid, host, port, storagePoolType, this); @@ -93,12 +96,16 @@ public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, KVMStoragePool pool @Override public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map details, boolean isVMMigrate) { + final String host = pool.getSourceHost(); + final int port = pool.getSourcePort(); + final String iqn = getIqn(volumeUuid); + // ex. sudo iscsiadm -m node -T iqn.2012-03.com.test:volume1 -p 192.168.233.10:3260 -o new Script iScsiAdmCmd = new Script(true, "iscsiadm", 0, logger); iScsiAdmCmd.add("-m", "node"); - iScsiAdmCmd.add("-T", getIqn(volumeUuid)); - iScsiAdmCmd.add("-p", pool.getSourceHost() + ":" + pool.getSourcePort()); + iScsiAdmCmd.add("-T", iqn); + iScsiAdmCmd.add("-p", host + ":" + port); iScsiAdmCmd.add("-o", "new"); String result = iScsiAdmCmd.execute(); @@ -125,13 +132,11 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map null). - final boolean sessionPreExisted = sessionAlreadyActive || (result != null); - + // Newly mapped LUNs on an existing session are invisible until rescan. + // Prefer the pre-login session check (required on Oracle, where re-login exits 0). + // Also treat ISCSI_ERR_SESS_EXISTS as a hint (Ubuntu). if (sessionPreExisted) { - logger.info("sessionPreExisted : performing rescan explicitely"); + logger.debug("iSCSI session for target {} at {}:{} pre-existed, performing rescan", iqn, host, port); rescanIscsiSessions(iqn, host, port); } @@ -192,16 +198,19 @@ boolean handleNodeCreateResult(String result, String volumeUuid) { /** * Checks the result of an iscsiadm login command. - * Returns true if the login succeeded or session already exists, false on failure. + * Returns true if the session already existed (pre-check and/or ISCSI_ERR_SESS_EXISTS) + * or login succeeded with no error output, false on failure. + * + * sessionPreExisted must be checked first: on Ubuntu, re-login exits 15 with a non-null + * error message that would otherwise be treated as failure. */ - boolean handleLoginResult(String result, String volumeUuid) { - if (result == null) { - logger.debug("Successfully logged in to iSCSI target {}", volumeUuid); + boolean handleLoginResult(String result, boolean sessionPreExisted, String volumeUuid) { + if (sessionPreExisted) { + logger.debug("iSCSI session already active for target {}", volumeUuid); return true; } - String msg = result.toLowerCase(); - if (msg.contains("already present") || msg.contains("already logged in") || msg.contains("session exists")) { - logger.debug("iSCSI session already exists for target {}, proceeding", volumeUuid); + if (result == null) { + logger.debug("Successfully logged in to iSCSI target {}", volumeUuid); return true; } logger.debug("Failed to log in to iSCSI target {}: {}", volumeUuid, result);