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
This commit is contained in:
sureshanaparti 2020-07-15 15:51:55 +05:30 committed by GitHub
parent dfc76e0278
commit f0a67cca7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 56 deletions

View File

@ -1949,7 +1949,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
int ideUnitNumber = 0; int ideUnitNumber = 0;
int scsiUnitNumber = 0; int scsiUnitNumber = 0;
int ideControllerKey = vmMo.getIDEDeviceControllerKey(); int ideControllerKey = vmMo.getIDEDeviceControllerKey();
int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException(); int scsiControllerKey = vmMo.getScsiDeviceControllerKeyNoException();
int controllerKey; int controllerKey;
// //
@ -2072,13 +2072,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} }
} }
} else { } else {
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController); if (VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) {
scsiUnitNumber++;
}
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController, scsiUnitNumber);
if (controllerKey == -1) { 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" // 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. // Retrieve existing controller and use.
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo(); Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
DiskControllerType existingControllerType = vmScsiControllerInfo.third(); DiskControllerType existingControllerType = vmScsiControllerInfo.third();
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString()); controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString(), scsiUnitNumber);
} }
} }
if (!hasSnapshot) { if (!hasSnapshot) {
@ -2102,10 +2106,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
assert (volumeDsDetails != null); assert (volumeDsDetails != null);
String[] diskChain = syncDiskChain(dcMo, vmMo, vmSpec, vol, matchingExistingDisk, dataStoresDetails); 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++; 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) if (vol.getType() == Volume.Type.ROOT)
rootDiskTO = vol; rootDiskTO = vol;
@ -2117,8 +2128,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
i++; i++;
} else { } else {
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
scsiUnitNumber++;
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber))
ideUnitNumber++; ideUnitNumber++;
else else

View File

@ -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 // 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 { public int getScsiDiskControllerKey(String diskController) throws Exception {
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient(). List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
getDynamicProperty(_mor, "config.hardware.device");
if (devices != null && devices.size() > 0) { if (CollectionUtils.isNotEmpty(devices)) {
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
for (VirtualDevice device : devices) { for (VirtualDevice device : devices) {
if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi)
&& device instanceof VirtualLsiLogicController) { && device instanceof VirtualLsiLogicController && isValidScsiDiskController((VirtualLsiLogicController)device)) {
return ((VirtualLsiLogicController)device).getKey(); return ((VirtualLsiLogicController)device).getKey();
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi) } else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi)
&& device instanceof VirtualLsiLogicSASController) { && device instanceof VirtualLsiLogicSASController && isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
return ((VirtualLsiLogicSASController)device).getKey(); return ((VirtualLsiLogicSASController)device).getKey();
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi) } else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi)
&& device instanceof ParaVirtualSCSIController) { && device instanceof ParaVirtualSCSIController && isValidScsiDiskController((ParaVirtualSCSIController)device)) {
return ((ParaVirtualSCSIController)device).getKey(); return ((ParaVirtualSCSIController)device).getKey();
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) } else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi)
&& device instanceof VirtualBusLogicController) { && device instanceof VirtualBusLogicController && isValidScsiDiskController((VirtualBusLogicController)device)) {
return ((VirtualBusLogicController)device).getKey(); 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."); throw new IllegalStateException("Scsi disk controller of type " + diskController + " not found among configured devices.");
} }
public int getScsiDiskControllerKeyNoException(String diskController) throws Exception { public int getScsiDiskControllerKeyNoException(String diskController, int scsiUnitNumber) throws Exception {
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient(). List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
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) { for (VirtualDevice device : devices) {
if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicController) {
&& device instanceof VirtualLsiLogicController) { if (scsiControllerDeviceCount == requiredScsiController) {
return ((VirtualLsiLogicController)device).getKey(); if (isValidScsiDiskController((VirtualLsiLogicController)device)) {
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi) return ((VirtualLsiLogicController)device).getKey();
&& device instanceof VirtualLsiLogicSASController) { }
return ((VirtualLsiLogicSASController)device).getKey(); break;
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi) }
&& device instanceof ParaVirtualSCSIController) { scsiControllerDeviceCount++;
return ((ParaVirtualSCSIController)device).getKey(); } else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicSASController) {
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi) if (scsiControllerDeviceCount == requiredScsiController) {
&& device instanceof VirtualBusLogicController) { if (isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
return ((VirtualBusLogicController)device).getKey(); 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) { if (devices != null && devices.size() > 0) {
for (VirtualDevice device : devices) { for (VirtualDevice device : devices) {
if (device instanceof VirtualSCSIController) { if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) {
return device.getKey(); return device.getKey();
} }
} }
@ -2295,27 +2317,12 @@ public class VirtualMachineMO extends BaseMO {
throw new Exception("SCSI Controller Not Found"); throw new Exception("SCSI Controller Not Found");
} }
public int getGenericScsiDeviceControllerKeyNoException() throws Exception { public int getScsiDeviceControllerKeyNoException() throws Exception {
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device"); List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
if (devices != null && devices.size() > 0) { if (devices != null && devices.size() > 0) {
for (VirtualDevice device : devices) { for (VirtualDevice device : devices) {
if (device instanceof VirtualSCSIController) { if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) {
return device.getKey();
}
}
}
return -1;
}
public int getScsiDeviceControllerKeyNoException() throws Exception {
List<VirtualDevice> devices = (List<VirtualDevice>)_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 device.getKey();
} }
} }
@ -2412,6 +2419,23 @@ public class VirtualMachineMO extends BaseMO {
} }
} }
private boolean isValidScsiDiskController(VirtualSCSIController scsiDiskController) {
if (scsiDiskController == null) {
return false;
}
List<Integer> 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) // return pair of VirtualDisk and disk device bus name(ide0:0, etc)
public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath) throws Exception { public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath) throws Exception {
final String zeroLengthString = ""; final String zeroLengthString = "";
@ -2985,7 +3009,7 @@ public class VirtualMachineMO extends BaseMO {
List<Integer> existingUnitNumbers = new ArrayList<Integer>(); List<Integer> existingUnitNumbers = new ArrayList<Integer>();
int deviceNumber = 0; int deviceNumber = 0;
int scsiControllerKey = getGenericScsiDeviceControllerKeyNoException(); int scsiControllerKey = getScsiDeviceControllerKeyNoException();
if (devices != null && devices.size() > 0) { if (devices != null && devices.size() > 0) {
for (VirtualDevice device : devices) { for (VirtualDevice device : devices) {
if (device.getControllerKey() != null && device.getControllerKey().intValue() == controllerKey) { if (device.getControllerKey() != null && device.getControllerKey().intValue() == controllerKey) {

View File

@ -91,11 +91,14 @@ public class VmwareHelper {
public static final int MAX_SCSI_CONTROLLER_COUNT = 4; public static final int MAX_SCSI_CONTROLLER_COUNT = 4;
public static final int MAX_IDE_CONTROLLER_COUNT = 2; 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_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 final String MIN_VERSION_UEFI_LEGACY = "5.5";
public static boolean isReservedScsiDeviceNumber(int deviceNumber) { 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 @Nonnull