From f0a67cca7a38ca6a6cd38f1d2c54d15137d206e2 Mon Sep 17 00:00:00 2001 From: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com> Date: Wed, 15 Jul 2020 15:51:55 +0530 Subject: [PATCH] vmware: Support to attach more than 15 data disks in VMware VM (#4172) Support to attach more than 15 data disks in VMware VM Fixes #4102 --- .../vmware/resource/VmwareResource.java | 25 ++-- .../vmware/mo/VirtualMachineMO.java | 116 +++++++++++------- .../hypervisor/vmware/util/VmwareHelper.java | 7 +- 3 files changed, 92 insertions(+), 56 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index aebda554a93..9051981291f 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -1949,7 +1949,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa int ideUnitNumber = 0; int scsiUnitNumber = 0; int ideControllerKey = vmMo.getIDEDeviceControllerKey(); - int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException(); + int scsiControllerKey = vmMo.getScsiDeviceControllerKeyNoException(); int controllerKey; // @@ -2072,13 +2072,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } } else { - controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController); + if (VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) { + scsiUnitNumber++; + } + + controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController, scsiUnitNumber); if (controllerKey == -1) { // This may happen for ROOT legacy VMs which doesn't have recommended disk controller when global configuration parameter 'vmware.root.disk.controller' is set to "osdefault" // Retrieve existing controller and use. Ternary vmScsiControllerInfo = vmMo.getScsiControllerInfo(); DiskControllerType existingControllerType = vmScsiControllerInfo.third(); - controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString()); + controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString(), scsiUnitNumber); } } if (!hasSnapshot) { @@ -2102,10 +2106,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa assert (volumeDsDetails != null); String[] diskChain = syncDiskChain(dcMo, vmMo, vmSpec, vol, matchingExistingDisk, dataStoresDetails); - if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) + + int deviceNumber = -1; + if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) { + deviceNumber = ideUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER; + ideUnitNumber++; + } else { + deviceNumber = scsiUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER; scsiUnitNumber++; - VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), - (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) ? ((ideUnitNumber++) % VmwareHelper.MAX_IDE_CONTROLLER_COUNT) : scsiUnitNumber++, i + 1); + } + + VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), deviceNumber, i + 1); if (vol.getType() == Volume.Type.ROOT) rootDiskTO = vol; @@ -2117,8 +2128,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa i++; } else { - if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) - scsiUnitNumber++; if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) ideUnitNumber++; else diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index d5df4b93471..394505627a7 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -2224,22 +2224,22 @@ public class VirtualMachineMO extends BaseMO { // Would be useful if there exists multiple sub types of SCSI controllers per VM are supported in CloudStack f public int getScsiDiskControllerKey(String diskController) throws Exception { - List devices = (List)_context.getVimClient(). - getDynamicProperty(_mor, "config.hardware.device"); + List devices = (List)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device"); - if (devices != null && devices.size() > 0) { + if (CollectionUtils.isNotEmpty(devices)) { + DiskControllerType diskControllerType = DiskControllerType.getType(diskController); for (VirtualDevice device : devices) { - if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualLsiLogicController) { + if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi) + && device instanceof VirtualLsiLogicController && isValidScsiDiskController((VirtualLsiLogicController)device)) { return ((VirtualLsiLogicController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualLsiLogicSASController) { + } else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi) + && device instanceof VirtualLsiLogicSASController && isValidScsiDiskController((VirtualLsiLogicSASController)device)) { return ((VirtualLsiLogicSASController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof ParaVirtualSCSIController) { + } else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi) + && device instanceof ParaVirtualSCSIController && isValidScsiDiskController((ParaVirtualSCSIController)device)) { return ((ParaVirtualSCSIController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualBusLogicController) { + } else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi) + && device instanceof VirtualBusLogicController && isValidScsiDiskController((VirtualBusLogicController)device)) { return ((VirtualBusLogicController)device).getKey(); } } @@ -2249,24 +2249,46 @@ public class VirtualMachineMO extends BaseMO { throw new IllegalStateException("Scsi disk controller of type " + diskController + " not found among configured devices."); } - public int getScsiDiskControllerKeyNoException(String diskController) throws Exception { - List devices = (List)_context.getVimClient(). - getDynamicProperty(_mor, "config.hardware.device"); + public int getScsiDiskControllerKeyNoException(String diskController, int scsiUnitNumber) throws Exception { + List devices = (List)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device"); - if (devices != null && devices.size() > 0) { + if (CollectionUtils.isNotEmpty(devices) && scsiUnitNumber >= 0) { + int requiredScsiController = scsiUnitNumber / VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER; + int scsiControllerDeviceCount = 0; + DiskControllerType diskControllerType = DiskControllerType.getType(diskController); for (VirtualDevice device : devices) { - if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualLsiLogicController) { - return ((VirtualLsiLogicController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualLsiLogicSASController) { - return ((VirtualLsiLogicSASController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof ParaVirtualSCSIController) { - return ((ParaVirtualSCSIController)device).getKey(); - } else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) - && device instanceof VirtualBusLogicController) { - return ((VirtualBusLogicController)device).getKey(); + if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicController) { + if (scsiControllerDeviceCount == requiredScsiController) { + if (isValidScsiDiskController((VirtualLsiLogicController)device)) { + return ((VirtualLsiLogicController)device).getKey(); + } + break; + } + scsiControllerDeviceCount++; + } else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicSASController) { + if (scsiControllerDeviceCount == requiredScsiController) { + if (isValidScsiDiskController((VirtualLsiLogicSASController)device)) { + return ((VirtualLsiLogicSASController)device).getKey(); + } + break; + } + scsiControllerDeviceCount++; + } else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi) && device instanceof ParaVirtualSCSIController) { + if (scsiControllerDeviceCount == requiredScsiController) { + if (isValidScsiDiskController((ParaVirtualSCSIController)device)) { + return ((ParaVirtualSCSIController)device).getKey(); + } + break; + } + scsiControllerDeviceCount++; + } else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualBusLogicController) { + if (scsiControllerDeviceCount == requiredScsiController) { + if (isValidScsiDiskController((VirtualBusLogicController)device)) { + return ((VirtualBusLogicController)device).getKey(); + } + break; + } + scsiControllerDeviceCount++; } } } @@ -2285,7 +2307,7 @@ public class VirtualMachineMO extends BaseMO { if (devices != null && devices.size() > 0) { for (VirtualDevice device : devices) { - if (device instanceof VirtualSCSIController) { + if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) { return device.getKey(); } } @@ -2295,27 +2317,12 @@ public class VirtualMachineMO extends BaseMO { throw new Exception("SCSI Controller Not Found"); } - public int getGenericScsiDeviceControllerKeyNoException() throws Exception { + public int getScsiDeviceControllerKeyNoException() throws Exception { List devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device"); if (devices != null && devices.size() > 0) { for (VirtualDevice device : devices) { - if (device instanceof VirtualSCSIController) { - return device.getKey(); - } - } - } - - return -1; - } - - public int getScsiDeviceControllerKeyNoException() throws Exception { - List devices = (List)_context.getVimClient(). - getDynamicProperty(_mor, "config.hardware.device"); - - if(devices != null && devices.size() > 0) { - for(VirtualDevice device : devices) { - if(device instanceof VirtualSCSIController) { + if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) { return device.getKey(); } } @@ -2412,6 +2419,23 @@ public class VirtualMachineMO extends BaseMO { } } + private boolean isValidScsiDiskController(VirtualSCSIController scsiDiskController) { + if (scsiDiskController == null) { + return false; + } + + List scsiDiskDevicesOnController = scsiDiskController.getDevice(); + if (scsiDiskDevicesOnController == null || scsiDiskDevicesOnController.size() >= (VmwareHelper.MAX_SUPPORTED_DEVICES_SCSI_CONTROLLER)) { + return false; + } + + if (scsiDiskController.getBusNumber() >= VmwareHelper.MAX_SCSI_CONTROLLER_COUNT) { + return false; + } + + return true; + } + // return pair of VirtualDisk and disk device bus name(ide0:0, etc) public Pair getDiskDevice(String vmdkDatastorePath) throws Exception { final String zeroLengthString = ""; @@ -2985,7 +3009,7 @@ public class VirtualMachineMO extends BaseMO { List existingUnitNumbers = new ArrayList(); int deviceNumber = 0; - int scsiControllerKey = getGenericScsiDeviceControllerKeyNoException(); + int scsiControllerKey = getScsiDeviceControllerKeyNoException(); if (devices != null && devices.size() > 0) { for (VirtualDevice device : devices) { if (device.getControllerKey() != null && device.getControllerKey().intValue() == controllerKey) { diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 3d209fb9175..181b2ef183f 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -91,11 +91,14 @@ public class VmwareHelper { public static final int MAX_SCSI_CONTROLLER_COUNT = 4; public static final int MAX_IDE_CONTROLLER_COUNT = 2; public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2; - public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 15; + public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 16; + public static final int MAX_SUPPORTED_DEVICES_SCSI_CONTROLLER = MAX_ALLOWED_DEVICES_SCSI_CONTROLLER - 1; // One device node is unavailable for hard disks or SCSI devices + public static final int MAX_USABLE_SCSI_CONTROLLERS = 2; public static final String MIN_VERSION_UEFI_LEGACY = "5.5"; public static boolean isReservedScsiDeviceNumber(int deviceNumber) { - return deviceNumber == 7; + // The SCSI controller is assigned to virtual device node (z:7), so that device node is unavailable for hard disks or SCSI devices. + return (deviceNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER) == 7; } @Nonnull