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..109c54189e21 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,12 @@ 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; + + /** 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); @@ -90,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(); @@ -122,28 +132,12 @@ public boolean connectPhysicalDisk(String volumeUuid, KVMStoragePool pool, Map 0) { + while ((deviceSize = getPhysicalDisk(volumeUuid, pool).getSize()) == 0 && numberOfTries > 0) { numberOfTries--; try { Thread.sleep(timeBetweenTries); - } catch (Exception ex) { - // don't do anything + } catch (InterruptedException ex) { + logger.warn("Interrupted while waiting for iSCSI device {} to become available", volumeUuid, ex); + return false; } } + + return deviceSize > 0; } private void waitForDiskToBecomeUnavailable(String host, int port, String iqn, String lun) { @@ -290,8 +343,17 @@ public KVMPhysicalDisk getPhysicalDisk(String volumeUuid, KVMStoragePool pool) { private long getDeviceSize(String deviceByPath) { try { - if (!Files.exists(Paths.get(deviceByPath))) { - logger.debug("Device by-path does not exist yet: " + deviceByPath); + Path devicePath = Paths.get(deviceByPath); + if (!Files.exists(devicePath)) { + logger.debug("Device by-path does not exist yet: {}", deviceByPath); + return 0L; + } + if (Files.isRegularFile(devicePath)) { + logger.warn("Found a corrupt regular file at iSCSI by-path {} (expected block device symlink); it must be removed manually", deviceByPath); + return 0L; + } + if (!Files.isSymbolicLink(devicePath)) { + logger.warn("Path {} exists but is not an iSCSI block device symlink", deviceByPath); return 0L; } } catch (Exception ex) {