Skip to content

Commit 2e73ca0

Browse files
[VMware] Support to attach more than 15 data disks in VMware VM
1 parent 3ede1ea commit 2e73ca0

File tree

3 files changed

+92
-56
lines changed

3 files changed

+92
-56
lines changed

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,7 +1945,7 @@ protected StartAnswer execute(StartCommand cmd) {
19451945
int ideUnitNumber = 0;
19461946
int scsiUnitNumber = 0;
19471947
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
1948-
int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException();
1948+
int scsiControllerKey = vmMo.getScsiDeviceControllerKeyNoException();
19491949
int controllerKey;
19501950

19511951
//
@@ -2068,13 +2068,17 @@ protected StartAnswer execute(StartCommand cmd) {
20682068
}
20692069
}
20702070
} else {
2071-
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController);
2071+
if (VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber)) {
2072+
scsiUnitNumber++;
2073+
}
2074+
2075+
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController, scsiUnitNumber);
20722076
if (controllerKey == -1) {
20732077
// 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"
20742078
// Retrieve existing controller and use.
20752079
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
20762080
DiskControllerType existingControllerType = vmScsiControllerInfo.third();
2077-
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString());
2081+
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString(), scsiUnitNumber);
20782082
}
20792083
}
20802084
if (!hasSnapshot) {
@@ -2098,10 +2102,17 @@ protected StartAnswer execute(StartCommand cmd) {
20982102
assert (volumeDsDetails != null);
20992103

21002104
String[] diskChain = syncDiskChain(dcMo, vmMo, vmSpec, vol, matchingExistingDisk, dataStoresDetails);
2101-
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
2105+
2106+
int deviceNumber = -1;
2107+
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) {
2108+
deviceNumber = ideUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER;
2109+
ideUnitNumber++;
2110+
} else {
2111+
deviceNumber = scsiUnitNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER;
21022112
scsiUnitNumber++;
2103-
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(),
2104-
(controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) ? ((ideUnitNumber++) % VmwareHelper.MAX_IDE_CONTROLLER_COUNT) : scsiUnitNumber++, i + 1);
2113+
}
2114+
2115+
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), deviceNumber, i + 1);
21052116

21062117
if (vol.getType() == Volume.Type.ROOT)
21072118
rootDiskTO = vol;
@@ -2113,8 +2124,6 @@ protected StartAnswer execute(StartCommand cmd) {
21132124

21142125
i++;
21152126
} else {
2116-
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
2117-
scsiUnitNumber++;
21182127
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber))
21192128
ideUnitNumber++;
21202129
else

vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,22 +2224,22 @@ public boolean isPvScsiSupported() throws Exception {
22242224

22252225
// Would be useful if there exists multiple sub types of SCSI controllers per VM are supported in CloudStack f
22262226
public int getScsiDiskControllerKey(String diskController) throws Exception {
2227-
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
2228-
getDynamicProperty(_mor, "config.hardware.device");
2227+
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
22292228

2230-
if (devices != null && devices.size() > 0) {
2229+
if (CollectionUtils.isNotEmpty(devices)) {
2230+
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
22312231
for (VirtualDevice device : devices) {
2232-
if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2233-
&& device instanceof VirtualLsiLogicController) {
2232+
if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi)
2233+
&& device instanceof VirtualLsiLogicController && isValidScsiDiskController((VirtualLsiLogicController)device)) {
22342234
return ((VirtualLsiLogicController)device).getKey();
2235-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2236-
&& device instanceof VirtualLsiLogicSASController) {
2235+
} else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi)
2236+
&& device instanceof VirtualLsiLogicSASController && isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
22372237
return ((VirtualLsiLogicSASController)device).getKey();
2238-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2239-
&& device instanceof ParaVirtualSCSIController) {
2238+
} else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi)
2239+
&& device instanceof ParaVirtualSCSIController && isValidScsiDiskController((ParaVirtualSCSIController)device)) {
22402240
return ((ParaVirtualSCSIController)device).getKey();
2241-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2242-
&& device instanceof VirtualBusLogicController) {
2241+
} else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi)
2242+
&& device instanceof VirtualBusLogicController && isValidScsiDiskController((VirtualBusLogicController)device)) {
22432243
return ((VirtualBusLogicController)device).getKey();
22442244
}
22452245
}
@@ -2249,24 +2249,46 @@ public int getScsiDiskControllerKey(String diskController) throws Exception {
22492249
throw new IllegalStateException("Scsi disk controller of type " + diskController + " not found among configured devices.");
22502250
}
22512251

2252-
public int getScsiDiskControllerKeyNoException(String diskController) throws Exception {
2253-
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
2254-
getDynamicProperty(_mor, "config.hardware.device");
2252+
public int getScsiDiskControllerKeyNoException(String diskController, int scsiUnitNumber) throws Exception {
2253+
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
22552254

2256-
if (devices != null && devices.size() > 0) {
2255+
if (CollectionUtils.isNotEmpty(devices) && scsiUnitNumber >= 0) {
2256+
int requiredScsiController = scsiUnitNumber / VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER;
2257+
int scsiControllerDeviceCount = 0;
2258+
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
22572259
for (VirtualDevice device : devices) {
2258-
if ((DiskControllerType.getType(diskController) == DiskControllerType.lsilogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2259-
&& device instanceof VirtualLsiLogicController) {
2260-
return ((VirtualLsiLogicController)device).getKey();
2261-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.lsisas1068 || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2262-
&& device instanceof VirtualLsiLogicSASController) {
2263-
return ((VirtualLsiLogicSASController)device).getKey();
2264-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.pvscsi || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2265-
&& device instanceof ParaVirtualSCSIController) {
2266-
return ((ParaVirtualSCSIController)device).getKey();
2267-
} else if ((DiskControllerType.getType(diskController) == DiskControllerType.buslogic || DiskControllerType.getType(diskController) == DiskControllerType.scsi)
2268-
&& device instanceof VirtualBusLogicController) {
2269-
return ((VirtualBusLogicController)device).getKey();
2260+
if ((diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicController) {
2261+
if (scsiControllerDeviceCount == requiredScsiController) {
2262+
if (isValidScsiDiskController((VirtualLsiLogicController)device)) {
2263+
return ((VirtualLsiLogicController)device).getKey();
2264+
}
2265+
break;
2266+
}
2267+
scsiControllerDeviceCount++;
2268+
} else if ((diskControllerType == DiskControllerType.lsisas1068 || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualLsiLogicSASController) {
2269+
if (scsiControllerDeviceCount == requiredScsiController) {
2270+
if (isValidScsiDiskController((VirtualLsiLogicSASController)device)) {
2271+
return ((VirtualLsiLogicSASController)device).getKey();
2272+
}
2273+
break;
2274+
}
2275+
scsiControllerDeviceCount++;
2276+
} else if ((diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.scsi) && device instanceof ParaVirtualSCSIController) {
2277+
if (scsiControllerDeviceCount == requiredScsiController) {
2278+
if (isValidScsiDiskController((ParaVirtualSCSIController)device)) {
2279+
return ((ParaVirtualSCSIController)device).getKey();
2280+
}
2281+
break;
2282+
}
2283+
scsiControllerDeviceCount++;
2284+
} else if ((diskControllerType == DiskControllerType.buslogic || diskControllerType == DiskControllerType.scsi) && device instanceof VirtualBusLogicController) {
2285+
if (scsiControllerDeviceCount == requiredScsiController) {
2286+
if (isValidScsiDiskController((VirtualBusLogicController)device)) {
2287+
return ((VirtualBusLogicController)device).getKey();
2288+
}
2289+
break;
2290+
}
2291+
scsiControllerDeviceCount++;
22702292
}
22712293
}
22722294
}
@@ -2285,7 +2307,7 @@ public int getScsiDeviceControllerKey() throws Exception {
22852307

22862308
if (devices != null && devices.size() > 0) {
22872309
for (VirtualDevice device : devices) {
2288-
if (device instanceof VirtualSCSIController) {
2310+
if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) {
22892311
return device.getKey();
22902312
}
22912313
}
@@ -2295,27 +2317,12 @@ public int getScsiDeviceControllerKey() throws Exception {
22952317
throw new Exception("SCSI Controller Not Found");
22962318
}
22972319

2298-
public int getGenericScsiDeviceControllerKeyNoException() throws Exception {
2320+
public int getScsiDeviceControllerKeyNoException() throws Exception {
22992321
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
23002322

23012323
if (devices != null && devices.size() > 0) {
23022324
for (VirtualDevice device : devices) {
2303-
if (device instanceof VirtualSCSIController) {
2304-
return device.getKey();
2305-
}
2306-
}
2307-
}
2308-
2309-
return -1;
2310-
}
2311-
2312-
public int getScsiDeviceControllerKeyNoException() throws Exception {
2313-
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
2314-
getDynamicProperty(_mor, "config.hardware.device");
2315-
2316-
if(devices != null && devices.size() > 0) {
2317-
for(VirtualDevice device : devices) {
2318-
if(device instanceof VirtualSCSIController) {
2325+
if (device instanceof VirtualSCSIController && isValidScsiDiskController((VirtualSCSIController)device)) {
23192326
return device.getKey();
23202327
}
23212328
}
@@ -2412,6 +2419,23 @@ public void ensureScsiDeviceControllers(int count, int availableBusNum) throws E
24122419
}
24132420
}
24142421

2422+
private boolean isValidScsiDiskController(VirtualSCSIController scsiDiskController) {
2423+
if (scsiDiskController == null) {
2424+
return false;
2425+
}
2426+
2427+
List<Integer> scsiDiskDevicesOnController = scsiDiskController.getDevice();
2428+
if (scsiDiskDevicesOnController == null || scsiDiskDevicesOnController.size() >= (VmwareHelper.MAX_SUPPORTED_DEVICES_SCSI_CONTROLLER)) {
2429+
return false;
2430+
}
2431+
2432+
if (scsiDiskController.getBusNumber() >= VmwareHelper.MAX_SCSI_CONTROLLER_COUNT) {
2433+
return false;
2434+
}
2435+
2436+
return true;
2437+
}
2438+
24152439
// return pair of VirtualDisk and disk device bus name(ide0:0, etc)
24162440
public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath) throws Exception {
24172441
final String zeroLengthString = "";
@@ -2985,7 +3009,7 @@ public int getNextDeviceNumber(int controllerKey) throws Exception {
29853009

29863010
List<Integer> existingUnitNumbers = new ArrayList<Integer>();
29873011
int deviceNumber = 0;
2988-
int scsiControllerKey = getGenericScsiDeviceControllerKeyNoException();
3012+
int scsiControllerKey = getScsiDeviceControllerKeyNoException();
29893013
if (devices != null && devices.size() > 0) {
29903014
for (VirtualDevice device : devices) {
29913015
if (device.getControllerKey() != null && device.getControllerKey().intValue() == controllerKey) {

vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,14 @@ public class VmwareHelper {
9191
public static final int MAX_SCSI_CONTROLLER_COUNT = 4;
9292
public static final int MAX_IDE_CONTROLLER_COUNT = 2;
9393
public static final int MAX_ALLOWED_DEVICES_IDE_CONTROLLER = 2;
94-
public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 15;
94+
public static final int MAX_ALLOWED_DEVICES_SCSI_CONTROLLER = 16;
95+
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
96+
public static final int MAX_USABLE_SCSI_CONTROLLERS = 2;
9597
public static final String MIN_VERSION_UEFI_LEGACY = "5.5";
9698

9799
public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
98-
return deviceNumber == 7;
100+
// The SCSI controller is assigned to virtual device node (z:7), so that device node is unavailable for hard disks or SCSI devices.
101+
return (deviceNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER) == 7;
99102
}
100103

101104
@Nonnull

0 commit comments

Comments
 (0)