mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Merge release branch 4.6 to master
* 4.6: [UI] bug fix: Delete added ACL lists is not available for Domain Admin and normal users CLOUDSTACK-4787: Allow users to select disk controller for VM/template CLOUDSTACK-4787 Allow selection of scsi controller type in vSphere
This commit is contained in:
commit
cdfcea3da2
@ -22,4 +22,5 @@ public interface VmDetailConstants {
|
||||
public static final String ROOK_DISK_CONTROLLER = "rootDiskController";
|
||||
public static final String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag";
|
||||
public static final String HYPERVISOR_TOOLS_VERSION = "hypervisortoolsversion";
|
||||
public static final String DATA_DISK_CONTROLLER = "dataDiskController";
|
||||
}
|
||||
|
||||
@ -19,18 +19,34 @@
|
||||
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
|
||||
public final class AttachCommand extends StorageSubSystemCommand {
|
||||
private DiskTO disk;
|
||||
private String vmName;
|
||||
private boolean inSeq;
|
||||
private boolean inSeq = false;
|
||||
private Map<String, String> controllerInfo;
|
||||
|
||||
public AttachCommand(final DiskTO disk, final String vmName) {
|
||||
super();
|
||||
this.disk = disk;
|
||||
this.vmName = vmName;
|
||||
}
|
||||
public AttachCommand(DiskTO disk, String vmName, Map<String, String> controllerInfo) {
|
||||
super();
|
||||
this.disk = disk;
|
||||
this.vmName = vmName;
|
||||
this.controllerInfo = controllerInfo;
|
||||
}
|
||||
|
||||
public Map<String, String> getControllerInfo() {
|
||||
return controllerInfo;
|
||||
}
|
||||
public void setControllerInfo(Map<String, String> controllerInfo) {
|
||||
this.controllerInfo = controllerInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
|
||||
@ -67,6 +67,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import com.cloud.hypervisor.HypervisorGuruBase;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
import com.cloud.network.Network.Provider;
|
||||
import com.cloud.network.Network.Service;
|
||||
@ -205,6 +206,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
|
||||
details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController());
|
||||
}
|
||||
}
|
||||
String diskController = details.get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
if (userVm) {
|
||||
if (diskController == null) {
|
||||
details.put(VmDetailConstants.DATA_DISK_CONTROLLER, DiskControllerType.lsilogic.toString());
|
||||
}
|
||||
}
|
||||
|
||||
List<NicProfile> nicProfiles = vm.getNics();
|
||||
|
||||
|
||||
@ -78,5 +78,6 @@ public interface VmwareManager {
|
||||
|
||||
boolean isLegacyZone(long dcId);
|
||||
|
||||
public String getDataDiskController();
|
||||
boolean hasNexusVSM(Long clusterId);
|
||||
}
|
||||
|
||||
@ -186,6 +186,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
|
||||
private String _rootDiskController = DiskControllerType.ide.toString();
|
||||
|
||||
private String _dataDiskController = DiskControllerType.osdefault.toString();
|
||||
|
||||
private final Map<String, String> _storageMounts = new HashMap<String, String>();
|
||||
|
||||
private final Random _rand = new Random(System.currentTimeMillis());
|
||||
@ -484,6 +486,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
params.put("service.console.name", _serviceConsoleName);
|
||||
params.put("management.portgroup.name", _managemetPortGroupName);
|
||||
params.put("vmware.root.disk.controller", _rootDiskController);
|
||||
params.put("vmware.data.disk.controller", _dataDiskController);
|
||||
params.put("vmware.recycle.hung.wokervm", _recycleHungWorker);
|
||||
params.put("ports.per.dvportgroup", _portsPerDvPortGroup);
|
||||
}
|
||||
@ -936,6 +939,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
|
||||
return _rootDiskController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataDiskController() {
|
||||
return _dataDiskController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVcenterSessionTimeout() {
|
||||
return _vCenterSessionTimeout;
|
||||
|
||||
@ -80,6 +80,7 @@ import com.vmware.vim25.VirtualDeviceBackingInfo;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualDisk;
|
||||
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
|
||||
import com.vmware.vim25.VirtualEthernetCard;
|
||||
import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
|
||||
import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
|
||||
@ -596,7 +597,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
s_logger.trace("resize volume done (failed)");
|
||||
throw new Exception("No such disk device: " + path);
|
||||
}
|
||||
// IDE virtual disk cannot be re-sized if VM is running
|
||||
if (vdisk.second() != null && vdisk.second().contains("ide")) {
|
||||
throw new Exception("Re-sizing a virtual disk over IDE controller is not supported in VMware hypervisor. " +
|
||||
"Please re-try when virtual disk is attached to a VM using SCSI controller.");
|
||||
}
|
||||
|
||||
VirtualDisk disk = vdisk.first();
|
||||
String vmdkAbsFile = getAbsoluteVmdkFile(disk);
|
||||
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
|
||||
vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
|
||||
}
|
||||
|
||||
disk.setCapacityInKB(newSize);
|
||||
|
||||
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
|
||||
@ -1327,6 +1339,63 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return new ScaleVmAnswer(cmd, true, null);
|
||||
}
|
||||
|
||||
protected void ensureDiskControllers(VirtualMachineMO vmMo, Pair<String, String> controllerInfo) throws Exception {
|
||||
if (vmMo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String msg;
|
||||
String rootDiskController = controllerInfo.first();
|
||||
String dataDiskController = controllerInfo.second();
|
||||
String scsiDiskController;
|
||||
String recommendedDiskController = null;
|
||||
|
||||
if (VmwareHelper.isControllerOsRecommended(dataDiskController) || VmwareHelper.isControllerOsRecommended(rootDiskController)) {
|
||||
recommendedDiskController = vmMo.getRecommendedDiskController(null);
|
||||
}
|
||||
scsiDiskController = HypervisorHostHelper.getScsiController(new Pair<String, String>(rootDiskController, dataDiskController), recommendedDiskController);
|
||||
if (scsiDiskController == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
vmMo.getScsiDeviceControllerKeyNoException();
|
||||
// This VM needs SCSI controllers.
|
||||
// Get count of existing scsi controllers. Helps not to attempt to create more than the maximum allowed 4
|
||||
// Get maximum among the bus numbers in use by scsi controllers. Safe to pick maximum, because we always go sequential allocating bus numbers.
|
||||
Ternary<Integer, Integer, DiskControllerType> scsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
int requiredNumScsiControllers = VmwareHelper.MAX_SCSI_CONTROLLER_COUNT - scsiControllerInfo.first();
|
||||
int availableBusNum = scsiControllerInfo.second() + 1; // method returned current max. bus number
|
||||
|
||||
if (requiredNumScsiControllers == 0) {
|
||||
return;
|
||||
}
|
||||
if (scsiControllerInfo.first() > 0) {
|
||||
// For VMs which already have a SCSI controller, do NOT attempt to add any more SCSI controllers & return the sub type.
|
||||
// For Legacy VMs would have only 1 LsiLogic Parallel SCSI controller, and doesn't require more.
|
||||
// For VMs created post device ordering support, 4 SCSI subtype controllers are ensured during deployment itself. No need to add more.
|
||||
// For fresh VM deployment only, all required controllers should be ensured.
|
||||
return;
|
||||
}
|
||||
ensureScsiDiskControllers(vmMo, scsiDiskController, requiredNumScsiControllers, availableBusNum);
|
||||
}
|
||||
|
||||
private void ensureScsiDiskControllers(VirtualMachineMO vmMo, String scsiDiskController, int requiredNumScsiControllers, int availableBusNum) throws Exception {
|
||||
// Pick the sub type of scsi
|
||||
if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.pvscsi) {
|
||||
if (!vmMo.isPvScsiSupported()) {
|
||||
String msg = "This VM doesn't support Vmware Paravirtual SCSI controller for virtual disks, because the virtual hardware version is less than 7.";
|
||||
throw new Exception(msg);
|
||||
}
|
||||
vmMo.ensurePvScsiDeviceController(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.lsisas1068) {
|
||||
vmMo.ensureLsiLogicSasDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.buslogic) {
|
||||
vmMo.ensureBusLogicDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
} else if (DiskControllerType.getType(scsiDiskController) == DiskControllerType.lsilogic) {
|
||||
vmMo.ensureScsiDeviceControllers(requiredNumScsiControllers, availableBusNum);
|
||||
}
|
||||
}
|
||||
|
||||
protected StartAnswer execute(StartCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource StartCommand: " + _gson.toJson(cmd));
|
||||
@ -1342,7 +1411,29 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
Pair<String, String> names = composeVmNames(vmSpec);
|
||||
String vmInternalCSName = names.first();
|
||||
String vmNameOnVcenter = names.second();
|
||||
String dataDiskController = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
String rootDiskController = vmSpec.getDetails().get(VmDetailConstants.ROOK_DISK_CONTROLLER);
|
||||
|
||||
// If root disk controller is scsi, then data disk controller would also be scsi instead of using 'osdefault'
|
||||
// This helps avoid mix of different scsi subtype controllers in instance.
|
||||
if (DiskControllerType.lsilogic == DiskControllerType.getType(rootDiskController)) {
|
||||
dataDiskController = DiskControllerType.scsi.toString();
|
||||
}
|
||||
|
||||
// Validate the controller types
|
||||
dataDiskController = DiskControllerType.getType(dataDiskController).toString();
|
||||
rootDiskController = DiskControllerType.getType(rootDiskController).toString();
|
||||
|
||||
if (DiskControllerType.getType(rootDiskController) == DiskControllerType.none) {
|
||||
throw new CloudRuntimeException("Invalid root disk controller detected : " + rootDiskController);
|
||||
}
|
||||
if (DiskControllerType.getType(dataDiskController) == DiskControllerType.none) {
|
||||
throw new CloudRuntimeException("Invalid data disk controller detected : " + dataDiskController);
|
||||
}
|
||||
|
||||
Pair<String, String> controllerInfo = new Pair<String, String>(rootDiskController, dataDiskController);
|
||||
|
||||
Boolean systemVm = vmSpec.getType().isUsedBySystem();
|
||||
// Thus, vmInternalCSName always holds i-x-y, the cloudstack generated internal VM name.
|
||||
VmwareContext context = getServiceContext();
|
||||
DatacenterMO dcMo = null;
|
||||
@ -1381,6 +1472,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
|
||||
VirtualMachineDiskInfoBuilder diskInfoBuilder = null;
|
||||
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
|
||||
DiskControllerType systemVmScsiControllerType = DiskControllerType.lsilogic;
|
||||
int firstScsiControllerBusNum = 0;
|
||||
int numScsiControllerForSystemVm = 1;
|
||||
boolean hasSnapshot = false;
|
||||
if (vmMo != null) {
|
||||
s_logger.info("VM " + vmInternalCSName + " already exists, tear down devices for reconfiguration");
|
||||
@ -1394,7 +1488,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
vmMo.tearDownDevices(new Class<?>[] {VirtualDisk.class, VirtualEthernetCard.class});
|
||||
else
|
||||
vmMo.tearDownDevices(new Class<?>[] {VirtualEthernetCard.class});
|
||||
vmMo.ensureScsiDeviceController();
|
||||
if (systemVm) {
|
||||
ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum);
|
||||
} else {
|
||||
ensureDiskControllers(vmMo, controllerInfo);
|
||||
}
|
||||
} else {
|
||||
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
|
||||
assert (morDc != null);
|
||||
@ -1416,7 +1514,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
vmMo.tearDownDevices(new Class<?>[] {VirtualDisk.class, VirtualEthernetCard.class});
|
||||
else
|
||||
vmMo.tearDownDevices(new Class<?>[] {VirtualEthernetCard.class});
|
||||
vmMo.ensureScsiDeviceController();
|
||||
|
||||
if (systemVm) {
|
||||
// System volumes doesn't require more than 1 SCSI controller as there is no requirement for data volumes.
|
||||
ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum);
|
||||
} else {
|
||||
ensureDiskControllers(vmMo, controllerInfo);
|
||||
}
|
||||
} else {
|
||||
// If a VM with the same name is found in a different cluster in the DC, unregister the old VM and configure a new VM (cold-migration).
|
||||
VirtualMachineMO existingVmInDc = dcMo.findVm(vmInternalCSName);
|
||||
@ -1460,7 +1564,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
tearDownVm(vmMo);
|
||||
}else if (!hyperHost.createBlankVm(vmNameOnVcenter, vmInternalCSName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(),
|
||||
getReservedCpuMHZ(vmSpec), vmSpec.getLimitCpuUse(), (int)(vmSpec.getMaxRam() / (1024 * 1024)), getReservedMemoryMb(vmSpec),
|
||||
translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs(), vmSpec.getPlatformEmulator()).value(), rootDiskDataStoreDetails.first(), false)) {
|
||||
translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs(), vmSpec.getPlatformEmulator()).value(), rootDiskDataStoreDetails.first(), false, controllerInfo, systemVm)) {
|
||||
throw new Exception("Failed to create VM. vmName: " + vmInternalCSName);
|
||||
}
|
||||
}
|
||||
@ -1522,7 +1626,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
int scsiUnitNumber = 0;
|
||||
int nicUnitNumber = 0;
|
||||
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
|
||||
int scsiControllerKey = vmMo.getScsiDeviceControllerKey();
|
||||
int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException();
|
||||
int controllerKey;
|
||||
|
||||
//
|
||||
@ -1621,7 +1725,31 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
|
||||
VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context);
|
||||
controllerKey = getDiskController(matchingExistingDisk, vol, vmSpec, ideControllerKey, scsiControllerKey);
|
||||
String diskController = getDiskController(vmMo, matchingExistingDisk, vol, new Pair<String, String>(rootDiskController, dataDiskController));
|
||||
|
||||
if (DiskControllerType.getType(diskController) == DiskControllerType.osdefault) {
|
||||
diskController = vmMo.getRecommendedDiskController(null);
|
||||
}
|
||||
if (DiskControllerType.getType(diskController) == DiskControllerType.ide) {
|
||||
controllerKey = vmMo.getIDEControllerKey(ideUnitNumber);
|
||||
if (vol.getType() == Volume.Type.DATADISK) {
|
||||
// Could be result of flip due to user configured setting or "osdefault" for data disks
|
||||
// Ensure maximum of 2 data volumes over IDE controller, 3 includeing root volume
|
||||
if (vmMo.getNumberOfVirtualDisks() > 3) {
|
||||
throw new CloudRuntimeException("Found more than 3 virtual disks attached to this VM [" + vmMo.getVmName() + "]. Unable to implement the disks over "
|
||||
+ diskController + " controller, as maximum number of devices supported over IDE controller is 4 includeing CDROM device.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController);
|
||||
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<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
DiskControllerType existingControllerType = vmScsiControllerInfo.third();
|
||||
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString());
|
||||
}
|
||||
}
|
||||
if (!hasSnapshot) {
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
|
||||
@ -1650,7 +1778,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey,
|
||||
diskChain,
|
||||
volumeDsDetails.first(),
|
||||
(controllerKey == ideControllerKey) ? ideUnitNumber++ : scsiUnitNumber++, i + 1);
|
||||
(controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) ? ((ideUnitNumber++) % VmwareHelper.MAX_IDE_CONTROLLER_COUNT) : scsiUnitNumber++, i + 1);
|
||||
|
||||
deviceConfigSpecArray[i].setDevice(device);
|
||||
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
@ -1662,7 +1790,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
} else {
|
||||
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
|
||||
scsiUnitNumber++;
|
||||
if (controllerKey == ideControllerKey)
|
||||
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber))
|
||||
ideUnitNumber++;
|
||||
else
|
||||
scsiUnitNumber++;
|
||||
@ -2218,6 +2346,36 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return controllerKey;
|
||||
}
|
||||
|
||||
private String getDiskController(VirtualMachineMO vmMo, VirtualMachineDiskInfo matchingExistingDisk, DiskTO vol, Pair<String, String> controllerInfo) throws Exception {
|
||||
int controllerKey;
|
||||
DiskControllerType controllerType = DiskControllerType.none;
|
||||
if (matchingExistingDisk != null) {
|
||||
String currentBusName = matchingExistingDisk.getDiskDeviceBusName();
|
||||
if (currentBusName != null) {
|
||||
s_logger.info("Chose disk controller based on existing information: " + currentBusName);
|
||||
if (currentBusName.startsWith("ide")) {
|
||||
controllerType = DiskControllerType.ide;
|
||||
} else if (currentBusName.startsWith("scsi")) {
|
||||
controllerType = DiskControllerType.scsi;
|
||||
}
|
||||
}
|
||||
if (controllerType == DiskControllerType.scsi || controllerType == DiskControllerType.none) {
|
||||
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
|
||||
controllerType = vmScsiControllerInfo.third();
|
||||
}
|
||||
return controllerType.toString();
|
||||
}
|
||||
|
||||
if (vol.getType() == Volume.Type.ROOT) {
|
||||
s_logger.info("Chose disk controller for vol " + vol.getType() + " -> " + controllerInfo.first()
|
||||
+ ", based on root disk controller settings at global configuration setting.");
|
||||
return controllerInfo.first();
|
||||
} else {
|
||||
s_logger.info("Chose disk controller for vol " + vol.getType() + " -> " + controllerInfo.second()
|
||||
+ ", based on default data disk controller setting i.e. Operating system recommended."); // Need to bring in global configuration setting & template level setting.
|
||||
return controllerInfo.second();
|
||||
}
|
||||
}
|
||||
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey,
|
||||
int scsiControllerKey, Map<String, String> iqnToPath, VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception {
|
||||
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
|
||||
@ -3158,8 +3316,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
relocateSpec.setDatastore(morTgtDatastore);
|
||||
}
|
||||
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
||||
diskLocator.setDatastore(morTgtDatastore);
|
||||
int diskId = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk");
|
||||
diskLocator.setDatastore(morDsAtSource);
|
||||
Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volume.getPath() + ".vmdk");
|
||||
String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
|
||||
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
|
||||
vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
|
||||
}
|
||||
int diskId = diskInfo.first().getKey();
|
||||
diskLocator.setDiskId(diskId);
|
||||
|
||||
diskLocators.add(diskLocator);
|
||||
@ -3326,7 +3489,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
|
||||
DatastoreMO targetDsMo = new DatastoreMO(srcHyperHost.getContext(), morDs);
|
||||
String fullVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(targetDsMo, vmName, volumePath + ".vmdk");
|
||||
int diskId = getVirtualDiskInfo(vmMo, volumePath + ".vmdk");
|
||||
Pair<VirtualDisk, String> diskInfo = getVirtualDiskInfo(vmMo, volumePath + ".vmdk");
|
||||
String vmdkAbsFile = getAbsoluteVmdkFile(diskInfo.first());
|
||||
if (vmdkAbsFile != null && !vmdkAbsFile.isEmpty()) {
|
||||
vmMo.updateAdapterTypeIfRequired(vmdkAbsFile);
|
||||
}
|
||||
int diskId = diskInfo.first().getKey();
|
||||
|
||||
diskLocator = new VirtualMachineRelocateSpecDiskLocator();
|
||||
diskLocator.setDatastore(morDs);
|
||||
diskLocator.setDiskId(diskId);
|
||||
@ -3385,12 +3554,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
}
|
||||
|
||||
private int getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception {
|
||||
private Pair<VirtualDisk, String> getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception {
|
||||
Pair<VirtualDisk, String> deviceInfo = vmMo.getDiskDevice(srcDiskName);
|
||||
if (deviceInfo == null) {
|
||||
throw new Exception("No such disk device: " + srcDiskName);
|
||||
}
|
||||
return deviceInfo.first().getKey();
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
private VmwareHypervisorHost getTargetHyperHost(DatacenterMO dcMo, String destIp) throws Exception {
|
||||
@ -4993,8 +5162,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
value = (String)params.get("vmware.root.disk.controller");
|
||||
if (value != null && value.equalsIgnoreCase("scsi"))
|
||||
_rootDiskController = DiskControllerType.scsi;
|
||||
else
|
||||
else if (value != null && value.equalsIgnoreCase("ide"))
|
||||
_rootDiskController = DiskControllerType.ide;
|
||||
else
|
||||
_rootDiskController = DiskControllerType.osdefault;
|
||||
|
||||
Integer intObj = (Integer)params.get("ports.per.dvportgroup");
|
||||
if (intObj != null)
|
||||
@ -5218,4 +5389,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return new Answer(cmd, false, msg);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAbsoluteVmdkFile(VirtualDisk disk) {
|
||||
String vmdkAbsFile = null;
|
||||
VirtualDeviceBackingInfo backingInfo = disk.getBacking();
|
||||
if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) {
|
||||
VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)backingInfo;
|
||||
vmdkAbsFile = diskBackingInfo.getFileName();
|
||||
}
|
||||
return vmdkAbsFile;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,12 +75,14 @@ import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreFile;
|
||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
|
||||
import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.HostStorageSystemMO;
|
||||
@ -104,6 +106,7 @@ import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.VirtualMachine.PowerState;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
|
||||
public class VmwareStorageProcessor implements StorageProcessor {
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
|
||||
@ -1292,10 +1295,10 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
String storageHost = details.get(DiskTO.STORAGE_HOST);
|
||||
int storagePort = Integer.parseInt(details.get(DiskTO.STORAGE_PORT));
|
||||
|
||||
return this.attachVolume(cmd, cmd.getDisk(), true, isManaged, cmd.getVmName(), iScsiName, storageHost, storagePort);
|
||||
return this.attachVolume(cmd, cmd.getDisk(), true, isManaged, cmd.getVmName(), iScsiName, storageHost, storagePort, cmd.getControllerInfo());
|
||||
}
|
||||
|
||||
private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName, String iScsiName, String storageHost, int storagePort) {
|
||||
private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName, String iScsiName, String storageHost, int storagePort, Map<String, String> controllerInfo) {
|
||||
VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
|
||||
DataStoreTO primaryStore = volumeTO.getDataStore();
|
||||
try {
|
||||
@ -1360,7 +1363,24 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
AttachAnswer answer = new AttachAnswer(disk);
|
||||
|
||||
if (isAttach) {
|
||||
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
|
||||
String dataDiskController = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER);
|
||||
String rootDiskController = controllerInfo.get(VmDetailConstants.ROOK_DISK_CONTROLLER);
|
||||
DiskControllerType rootDiskControllerType = DiskControllerType.getType(rootDiskController);
|
||||
|
||||
if (dataDiskController == null) {
|
||||
dataDiskController = getLegacyVmDataDiskController();
|
||||
} else if ((rootDiskControllerType == DiskControllerType.lsilogic) ||
|
||||
(rootDiskControllerType == DiskControllerType.lsisas1068) ||
|
||||
(rootDiskControllerType == DiskControllerType.pvscsi) ||
|
||||
(rootDiskControllerType == DiskControllerType.buslogic)) {
|
||||
//TODO: Support mix of SCSI controller types for single VM. If root disk is already over
|
||||
//a SCSI controller then use the same for data volume as well. This limitation will go once mix
|
||||
//of SCSI controller types for single VM.
|
||||
dataDiskController = rootDiskController;
|
||||
} else if (DiskControllerType.getType(dataDiskController) == DiskControllerType.osdefault) {
|
||||
dataDiskController = vmMo.getRecommendedDiskController(null);
|
||||
}
|
||||
vmMo.attachDisk(new String[] {datastoreVolumePath}, morDs, dataDiskController);
|
||||
} else {
|
||||
vmMo.removeAllSnapshots();
|
||||
vmMo.detachDisk(datastoreVolumePath, false);
|
||||
@ -1504,7 +1524,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
|
||||
@Override
|
||||
public Answer dettachVolume(DettachCommand cmd) {
|
||||
return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort());
|
||||
return this.attachVolume(cmd, cmd.getDisk(), false, cmd.isManaged(), cmd.getVmName(), cmd.get_iScsiName(), cmd.getStorageHost(), cmd.getStoragePort(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2277,4 +2297,28 @@ public class VmwareStorageProcessor implements StorageProcessor {
|
||||
templateUuid = templateUuid.replaceAll("-", "");
|
||||
return templateUuid;
|
||||
}
|
||||
|
||||
private String getControllerFromConfigurationSetting() throws Exception {
|
||||
String diskController = null;
|
||||
VmwareContext context = null;
|
||||
try {
|
||||
context = hostService.getServiceContext(null);
|
||||
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
|
||||
diskController = mgr.getDataDiskController();
|
||||
} catch (Throwable e) {
|
||||
if (e instanceof RemoteException) {
|
||||
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
|
||||
hostService.invalidateServiceContext(context);
|
||||
}
|
||||
|
||||
String details = "Failed to connect to vCenter due to " + VmwareHelper.getExceptionMessage(e);
|
||||
s_logger.error(details, e);
|
||||
}
|
||||
|
||||
return diskController;
|
||||
}
|
||||
|
||||
private String getLegacyVmDataDiskController() throws Exception {
|
||||
return DiskControllerType.lsilogic.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1202,7 +1202,7 @@ public enum Config {
|
||||
String.class,
|
||||
"vmware.root.disk.controller",
|
||||
"ide",
|
||||
"Specify the default disk controller for root volumes, valid values are scsi, ide",
|
||||
"Specify the default disk controller for root volumes, valid values are scsi, ide, osdefault. Please check documentation for more details on each of these values.",
|
||||
null),
|
||||
VmwareSystemVmNicDeviceType(
|
||||
"Advanced",
|
||||
|
||||
@ -150,6 +150,7 @@ import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.VmWork;
|
||||
import com.cloud.vm.VmWorkAttachVolume;
|
||||
import com.cloud.vm.VmWorkConstants;
|
||||
@ -2453,6 +2454,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
||||
details.put(DiskTO.CHAP_TARGET_USERNAME, chapInfo.getTargetUsername());
|
||||
details.put(DiskTO.CHAP_TARGET_SECRET, chapInfo.getTargetSecret());
|
||||
}
|
||||
_userVmDao.loadDetails(vm);
|
||||
Map<String, String> controllerInfo = new HashMap<String, String>();
|
||||
controllerInfo.put(VmDetailConstants.ROOK_DISK_CONTROLLER, vm.getDetail(VmDetailConstants.ROOK_DISK_CONTROLLER));
|
||||
controllerInfo.put(VmDetailConstants.DATA_DISK_CONTROLLER, vm.getDetail(VmDetailConstants.DATA_DISK_CONTROLLER));
|
||||
cmd.setControllerInfo(controllerInfo);
|
||||
|
||||
try {
|
||||
answer = (AttachAnswer)_agentMgr.send(hostId, cmd);
|
||||
|
||||
@ -3510,8 +3510,22 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
if (guestOS.getDisplayName().toLowerCase().contains("apple mac os")) {
|
||||
vm.setDetail("smc.present", "TRUE");
|
||||
vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, "scsi");
|
||||
vm.setDetail(VmDetailConstants.DATA_DISK_CONTROLLER, "scsi");
|
||||
vm.setDetail("firmware", "efi");
|
||||
s_logger.info("guestOS is OSX : overwrite root disk controller to scsi, use smc and efi");
|
||||
} else {
|
||||
String controllerSetting = _configDao.getValue("vmware.root.disk.controller");
|
||||
// Don't override if VM already has root/data disk controller detail
|
||||
if (vm.getDetail(VmDetailConstants.ROOK_DISK_CONTROLLER) == null) {
|
||||
vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, controllerSetting);
|
||||
}
|
||||
if (vm.getDetail(VmDetailConstants.DATA_DISK_CONTROLLER) == null) {
|
||||
if (controllerSetting.equalsIgnoreCase("scsi")) {
|
||||
vm.setDetail(VmDetailConstants.DATA_DISK_CONTROLLER, "scsi");
|
||||
} else {
|
||||
vm.setDetail(VmDetailConstants.DATA_DISK_CONTROLLER, "osdefault");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -281,6 +281,26 @@
|
||||
id: "ide",
|
||||
description: "ide"
|
||||
});
|
||||
items.push({
|
||||
id: "osdefault",
|
||||
description: "osdefault"
|
||||
});
|
||||
items.push({
|
||||
id: "pvscsi",
|
||||
description: "pvscsi"
|
||||
});
|
||||
items.push({
|
||||
id: "lsilogic",
|
||||
description: "lsilogic"
|
||||
});
|
||||
items.push({
|
||||
id: "lsisas1068",
|
||||
description: "lsilogicsas"
|
||||
});
|
||||
items.push({
|
||||
id: "buslogic",
|
||||
description: "buslogic"
|
||||
});
|
||||
args.response.success({
|
||||
data: items
|
||||
});
|
||||
|
||||
@ -638,7 +638,7 @@
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jobID,
|
||||
getUpdateIdtem: function() {
|
||||
getUpdatedItem: function() {
|
||||
$(window).trigger('cloudStack.fullRefresh');
|
||||
}
|
||||
},
|
||||
@ -1225,12 +1225,19 @@
|
||||
url: createURL('createNetworkACLList&vpcid=' + args.context.vpc[0].id),
|
||||
data: data,
|
||||
success: function(json) {
|
||||
var items = json.createnetworkacllistresponse;
|
||||
args.response.success({
|
||||
data: items
|
||||
_custom: {
|
||||
jobId: json.createnetworkacllistresponse.jobid,
|
||||
getUpdatedItem: function(json) {
|
||||
return json.queryasyncjobresultresponse.jobresult.networkacllist;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
notification: {
|
||||
poll: pollAsyncJobResult
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1255,7 +1262,10 @@
|
||||
var jid = json.deletenetworkacllistresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid
|
||||
jobId: jid,
|
||||
getUpdatedItem: function() {
|
||||
$(window).trigger('cloudStack.fullRefresh');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -1292,9 +1302,8 @@
|
||||
data: items,
|
||||
actionFilter: function(args) {
|
||||
var allowedActions = [];
|
||||
if (isAdmin() && items.vpcid) {
|
||||
if (items.vpcid != null) {
|
||||
allowedActions.push("remove");
|
||||
|
||||
}
|
||||
return allowedActions;
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ import com.vmware.vim25.ComputeResourceSummary;
|
||||
import com.vmware.vim25.CustomFieldStringValue;
|
||||
import com.vmware.vim25.DatastoreInfo;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.GuestOsDescriptor;
|
||||
import com.vmware.vim25.HostHardwareSummary;
|
||||
import com.vmware.vim25.HostIpRouteEntry;
|
||||
import com.vmware.vim25.HostRuntimeInfo;
|
||||
@ -46,9 +47,11 @@ import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigOption;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.hypervisor.vmware.util.VmwareHelper;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@ -271,7 +274,7 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.getValue() + ", vmName: " + vmName + ", cpuCount: " + cpuCount + ", cpuSpeedMhz: " +
|
||||
@ -280,7 +283,7 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
boolean result =
|
||||
HypervisorHostHelper.createBlankVm(this, vmName, vmInternalCSName, cpuCount, cpuSpeedMHz, cpuReservedMHz, limitCpuUse, memoryMB, memoryReserveMB,
|
||||
guestOsIdentifier, morDs, snapshotDirToParent);
|
||||
guestOsIdentifier, morDs, snapshotDirToParent, controllerInfo, systemVm);
|
||||
|
||||
if (s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm() done");
|
||||
@ -582,4 +585,32 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
|
||||
// LicenseAssignmentManager deals with only host/vcenter licenses only. Has nothing todo with cluster
|
||||
throw new CloudRuntimeException("Unable to get LicenseAssignmentManager at cluster level");
|
||||
}
|
||||
private ManagedObjectReference getEnvironmentBrowser() throws Exception {
|
||||
if (_environmentBrowser == null) {
|
||||
_environmentBrowser = _context.getVimClient().getMoRefProp(_mor, "environmentBrowser");
|
||||
}
|
||||
return _environmentBrowser;
|
||||
}
|
||||
@Override
|
||||
public String getRecommendedDiskController(String guestOsId) throws Exception {
|
||||
VirtualMachineConfigOption vmConfigOption = _context.getService().queryConfigOption(getEnvironmentBrowser(), null, null);
|
||||
GuestOsDescriptor guestOsDescriptor = null;
|
||||
String diskController = null;
|
||||
List<GuestOsDescriptor> guestDescriptors = vmConfigOption.getGuestOSDescriptor();
|
||||
for (GuestOsDescriptor descriptor : guestDescriptors) {
|
||||
if (guestOsId != null && guestOsId.equalsIgnoreCase(descriptor.getId())) {
|
||||
guestOsDescriptor = descriptor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (guestOsDescriptor != null) {
|
||||
diskController = VmwareHelper.getRecommendedDiskControllerFromDescriptor(guestOsDescriptor);
|
||||
s_logger.debug("Retrieved recommended disk controller for guest OS : " + guestOsId + " in cluster " + getHyperHostName() + " : " + diskController);
|
||||
return diskController;
|
||||
} else {
|
||||
String msg = "Unable to retrieve recommended disk controller for guest OS : " + guestOsId + " in cluster " + getHyperHostName();
|
||||
s_logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,5 +17,34 @@
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum DiskControllerType {
|
||||
ide, scsi
|
||||
ide,
|
||||
scsi,
|
||||
osdefault,
|
||||
lsilogic,
|
||||
lsisas1068,
|
||||
buslogic,
|
||||
pvscsi,
|
||||
none;
|
||||
public static DiskControllerType getType(String diskController) {
|
||||
if (diskController == null || diskController.equalsIgnoreCase("osdefault")) {
|
||||
return DiskControllerType.osdefault;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualLsiLogicSASController") || diskController.equalsIgnoreCase("VirtualLsiLogicSASController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.LSILOGIC_SAS)) {
|
||||
return DiskControllerType.lsisas1068;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualLsiLogicController") || diskController.equalsIgnoreCase("VirtualLsiLogicController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.LSILOGIC_PARALLEL) || diskController.equalsIgnoreCase("scsi")) {
|
||||
return DiskControllerType.lsilogic;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualIDEController") || diskController.equalsIgnoreCase("VirtualIDEController")
|
||||
|| diskController.equalsIgnoreCase("ide")) {
|
||||
return DiskControllerType.ide;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.ParaVirtualSCSIController") || diskController.equalsIgnoreCase("ParaVirtualSCSIController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.VMWARE_PARAVIRTUAL)) {
|
||||
return DiskControllerType.pvscsi;
|
||||
} else if (diskController.equalsIgnoreCase("vim.vm.device.VirtualBusLogicController") || diskController.equalsIgnoreCase("VirtualBusLogicController")
|
||||
|| diskController.equalsIgnoreCase(ScsiDiskControllerType.BUSLOGIC)) {
|
||||
return DiskControllerType.buslogic;
|
||||
} else {
|
||||
return DiskControllerType.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -751,16 +751,17 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
|
||||
@Override
|
||||
public boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.getValue() + ", vmName: " + vmName + ", cpuCount: " + cpuCount + ", cpuSpeedMhz: " +
|
||||
cpuSpeedMHz + ", cpuReservedMHz: " + cpuReservedMHz + ", limitCpu: " + limitCpuUse + ", memoryMB: " + memoryMB + ", guestOS: " + guestOsIdentifier +
|
||||
", datastore: " + morDs.getValue() + ", snapshotDirToParent: " + snapshotDirToParent);
|
||||
", datastore: " + morDs.getValue() + ", snapshotDirToParent: " + snapshotDirToParent +
|
||||
", controllerInfo:[" + controllerInfo.first() + "," + controllerInfo.second() + "], systemvm: " + systemVm);
|
||||
|
||||
boolean result =
|
||||
HypervisorHostHelper.createBlankVm(this, vmName, vmInternalCSName, cpuCount, cpuSpeedMHz, cpuReservedMHz, limitCpuUse, memoryMB, memoryReserveMB,
|
||||
guestOsIdentifier, morDs, snapshotDirToParent);
|
||||
guestOsIdentifier, morDs, snapshotDirToParent, controllerInfo, systemVm);
|
||||
|
||||
if (s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - createBlankVm() done");
|
||||
@ -1069,6 +1070,16 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRecommendedDiskController(String guestOsId) throws Exception {
|
||||
ManagedObjectReference morParent = getParentMor();
|
||||
if (morParent.getType().equals("ClusterComputeResource")) {
|
||||
ClusterMO clusterMo = new ClusterMO(_context, morParent);
|
||||
return clusterMo.getRecommendedDiskController(guestOsId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getHostManagementIp(String managementPortGroup) throws Exception {
|
||||
HostNetworkInfo netInfo = getHostNetworkInfo();
|
||||
|
||||
|
||||
@ -69,18 +69,24 @@ import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.OvfCreateImportSpecParams;
|
||||
import com.vmware.vim25.OvfCreateImportSpecResult;
|
||||
import com.vmware.vim25.OvfFileItem;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.VMwareDVSConfigSpec;
|
||||
import com.vmware.vim25.VMwareDVSPortSetting;
|
||||
import com.vmware.vim25.VMwareDVSPortgroupPolicy;
|
||||
import com.vmware.vim25.VMwareDVSPvlanConfigSpec;
|
||||
import com.vmware.vim25.VMwareDVSPvlanMapEntry;
|
||||
import com.vmware.vim25.VirtualBusLogicController;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualLsiLogicSASController;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
||||
import com.vmware.vim25.VirtualMachineVideoCard;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
|
||||
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
|
||||
@ -1242,11 +1248,13 @@ public class HypervisorHostHelper {
|
||||
}
|
||||
|
||||
public static boolean createBlankVm(VmwareHypervisorHost host, String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz,
|
||||
boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception {
|
||||
boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent,
|
||||
Pair<String, String> controllerInfo, Boolean systemVm) throws Exception {
|
||||
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Create blank VM. cpuCount: " + cpuCount + ", cpuSpeed(MHz): " + cpuSpeedMHz + ", mem(Mb): " + memoryMB);
|
||||
|
||||
VirtualDeviceConfigSpec controllerSpec = null;
|
||||
// VM config basics
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
vmConfig.setName(vmName);
|
||||
@ -1255,14 +1263,33 @@ public class HypervisorHostHelper {
|
||||
|
||||
VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, memoryReserveMB, guestOsIdentifier, limitCpuUse);
|
||||
|
||||
// Scsi controller
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(0);
|
||||
scsiController.setKey(1);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
String recommendedController = host.getRecommendedDiskController(guestOsIdentifier);
|
||||
String newRootDiskController = controllerInfo.first();
|
||||
String newDataDiskController = controllerInfo.second();
|
||||
if (DiskControllerType.getType(controllerInfo.first()) == DiskControllerType.osdefault) {
|
||||
newRootDiskController = recommendedController;
|
||||
}
|
||||
if (DiskControllerType.getType(controllerInfo.second()) == DiskControllerType.osdefault) {
|
||||
newDataDiskController = recommendedController;
|
||||
}
|
||||
|
||||
Pair<String, String> updatedControllerInfo = new Pair<String, String>(newRootDiskController, newDataDiskController);
|
||||
String scsiDiskController = HypervisorHostHelper.getScsiController(updatedControllerInfo, recommendedController);
|
||||
// If there is requirement for a SCSI controller, ensure to create those.
|
||||
if (scsiDiskController != null) {
|
||||
int busNum = 0;
|
||||
int maxControllerCount = VmwareHelper.MAX_SCSI_CONTROLLER_COUNT;
|
||||
if (systemVm) {
|
||||
maxControllerCount = 1;
|
||||
}
|
||||
while (busNum < maxControllerCount) {
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec = getControllerSpec(DiskControllerType.getType(scsiDiskController).toString(), busNum);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
|
||||
DatastoreMO dsMo = new DatastoreMO(host.getContext(), morDs);
|
||||
@ -1277,7 +1304,6 @@ public class HypervisorHostHelper {
|
||||
videoDeviceSpec.setDevice(videoCard);
|
||||
videoDeviceSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
vmConfig.getDeviceChange().add(videoDeviceSpec);
|
||||
if (host.createVm(vmConfig)) {
|
||||
// Here, when attempting to find the VM, we need to use the name
|
||||
@ -1307,6 +1333,34 @@ public class HypervisorHostHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static VirtualDeviceConfigSpec getControllerSpec(String diskController, int busNum) {
|
||||
VirtualDeviceConfigSpec controllerSpec = new VirtualDeviceConfigSpec();
|
||||
VirtualController controller = null;
|
||||
|
||||
if (diskController.equalsIgnoreCase(DiskControllerType.ide.toString())) {
|
||||
controller = new VirtualIDEController();
|
||||
} else if (DiskControllerType.pvscsi == DiskControllerType.getType(diskController)) {
|
||||
controller = new ParaVirtualSCSIController();
|
||||
} else if (DiskControllerType.lsisas1068 == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualLsiLogicSASController();
|
||||
} else if (DiskControllerType.buslogic == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualBusLogicController();
|
||||
} else if (DiskControllerType.lsilogic == DiskControllerType.getType(diskController)) {
|
||||
controller = new VirtualLsiLogicController();
|
||||
}
|
||||
|
||||
if (!diskController.equalsIgnoreCase(DiskControllerType.ide.toString())) {
|
||||
((VirtualSCSIController)controller).setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
}
|
||||
|
||||
controller.setBusNumber(busNum);
|
||||
controller.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
|
||||
controllerSpec.setDevice(controller);
|
||||
controllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
return controllerSpec;
|
||||
}
|
||||
public static VirtualMachineMO createWorkerVM(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
|
||||
|
||||
// Allow worker VM to float within cluster so that we will have better chance to
|
||||
@ -1516,4 +1570,42 @@ public class HypervisorHostHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getScsiController(Pair<String, String> controllerInfo, String recommendedController) {
|
||||
String rootDiskController = controllerInfo.first();
|
||||
String dataDiskController = controllerInfo.second();
|
||||
|
||||
// If "osdefault" is specified as controller type, then translate to actual recommended controller.
|
||||
if (VmwareHelper.isControllerOsRecommended(rootDiskController)) {
|
||||
rootDiskController = recommendedController;
|
||||
}
|
||||
if (VmwareHelper.isControllerOsRecommended(dataDiskController)) {
|
||||
dataDiskController = recommendedController;
|
||||
}
|
||||
|
||||
String scsiDiskController = null; //If any of the controller provided is SCSI then return it's sub-type.
|
||||
if (isIdeController(rootDiskController) && isIdeController(dataDiskController)) {
|
||||
//Default controllers would exist
|
||||
return null;
|
||||
} else if (isIdeController(rootDiskController) || isIdeController(dataDiskController)) {
|
||||
// Only one of the controller types is IDE. Pick the other controller type to create controller.
|
||||
if (isIdeController(rootDiskController)) {
|
||||
scsiDiskController = dataDiskController;
|
||||
} else {
|
||||
scsiDiskController = rootDiskController;
|
||||
}
|
||||
} else if (DiskControllerType.getType(rootDiskController) != DiskControllerType.getType(dataDiskController)) {
|
||||
// Both ROOT and DATA controllers are SCSI controllers but different sub-types, then prefer ROOT controller
|
||||
scsiDiskController = rootDiskController;
|
||||
} else {
|
||||
// Both are SCSI controllers.
|
||||
scsiDiskController = rootDiskController;
|
||||
}
|
||||
return scsiDiskController;
|
||||
}
|
||||
|
||||
public static boolean isIdeController(String controller) {
|
||||
return DiskControllerType.getType(controller) == DiskControllerType.ide;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public interface ScsiDiskControllerType {
|
||||
public final static String LSILOGIC_PARALLEL = "lsilogic";
|
||||
public final static String LSILOGIC_SAS = "lsisas1068";
|
||||
public final static String BUSLOGIC = "buslogic";
|
||||
public final static String VMWARE_PARAVIRTUAL = "pvscsi";
|
||||
}
|
||||
@ -55,12 +55,15 @@ import com.vmware.vim25.OptionValue;
|
||||
import com.vmware.vim25.OvfCreateDescriptorParams;
|
||||
import com.vmware.vim25.OvfCreateDescriptorResult;
|
||||
import com.vmware.vim25.OvfFile;
|
||||
import com.vmware.vim25.ParaVirtualSCSIController;
|
||||
import com.vmware.vim25.PropertyFilterSpec;
|
||||
import com.vmware.vim25.PropertySpec;
|
||||
import com.vmware.vim25.TraversalSpec;
|
||||
import com.vmware.vim25.VirtualBusLogicController;
|
||||
import com.vmware.vim25.VirtualCdrom;
|
||||
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
|
||||
import com.vmware.vim25.VirtualCdromRemotePassthroughBackingInfo;
|
||||
import com.vmware.vim25.VirtualController;
|
||||
import com.vmware.vim25.VirtualDevice;
|
||||
import com.vmware.vim25.VirtualDeviceBackingInfo;
|
||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
||||
@ -80,6 +83,7 @@ import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
|
||||
import com.vmware.vim25.VirtualHardwareOption;
|
||||
import com.vmware.vim25.VirtualIDEController;
|
||||
import com.vmware.vim25.VirtualLsiLogicController;
|
||||
import com.vmware.vim25.VirtualLsiLogicSASController;
|
||||
import com.vmware.vim25.VirtualMachineCloneSpec;
|
||||
import com.vmware.vim25.VirtualMachineConfigInfo;
|
||||
import com.vmware.vim25.VirtualMachineConfigOption;
|
||||
@ -97,7 +101,6 @@ import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
|
||||
import com.vmware.vim25.VirtualMachineRuntimeInfo;
|
||||
import com.vmware.vim25.VirtualMachineSnapshotInfo;
|
||||
import com.vmware.vim25.VirtualMachineSnapshotTree;
|
||||
import com.vmware.vim25.VirtualPCIController;
|
||||
import com.vmware.vim25.VirtualSCSIController;
|
||||
import com.vmware.vim25.VirtualSCSISharing;
|
||||
|
||||
@ -1091,6 +1094,130 @@ public class VirtualMachineMO extends BaseMO {
|
||||
s_logger.trace("vCenter API trace - createDisk() done(successfully)");
|
||||
}
|
||||
|
||||
public void updateVmdkAdapter(String vmdkFileName, String newAdapterType) throws Exception {
|
||||
Pair<VmdkFileDescriptor, byte[]> vmdkInfo = getVmdkFileInfo(vmdkFileName);
|
||||
VmdkFileDescriptor vmdkFileDescriptor = vmdkInfo.first();
|
||||
boolean isVmfsSparseFile = vmdkFileDescriptor.isVmfsSparseFile();
|
||||
if (!isVmfsSparseFile) {
|
||||
String currentAdapterType = vmdkFileDescriptor.getAdapterType();
|
||||
if (!currentAdapterType.equalsIgnoreCase(newAdapterType)) {
|
||||
s_logger.info("Updating adapter type to " + newAdapterType + " for VMDK file " + vmdkFileName);
|
||||
Pair<DatacenterMO, String> dcInfo = getOwnerDatacenter();
|
||||
byte[] newVmdkContent = vmdkFileDescriptor.changeVmdkAdapterType(vmdkInfo.second(), newAdapterType);
|
||||
String vmdkUploadUrl = getContext().composeDatastoreBrowseUrl(dcInfo.first().getName(), vmdkFileName);
|
||||
getContext().uploadResourceContent(vmdkUploadUrl, newVmdkContent);
|
||||
s_logger.info("Updated VMDK file " + vmdkFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAdapterTypeIfRequired(String vmdkFileName) throws Exception {
|
||||
// Validate existing adapter type of VMDK file. Update it with a supported adapter type if validation fails.
|
||||
Pair<VmdkFileDescriptor, byte[]> vmdkInfo = getVmdkFileInfo(vmdkFileName);
|
||||
VmdkFileDescriptor vmdkFileDescriptor = vmdkInfo.first();
|
||||
|
||||
boolean isVmfsSparseFile = vmdkFileDescriptor.isVmfsSparseFile();
|
||||
if (!isVmfsSparseFile) {
|
||||
String currentAdapterTypeStr = vmdkFileDescriptor.getAdapterType();
|
||||
if (s_logger.isTraceEnabled()) {
|
||||
s_logger.trace("Detected adapter type " + currentAdapterTypeStr + " for VMDK file " + vmdkFileName);
|
||||
}
|
||||
VmdkAdapterType currentAdapterType = VmdkAdapterType.getType(currentAdapterTypeStr);
|
||||
if (currentAdapterType == VmdkAdapterType.none) {
|
||||
// Value of currentAdapterType can be VmdkAdapterType.none only if adapter type of vmdk is set to either
|
||||
// lsisas1068 (SAS controller) or pvscsi (Vmware Paravirtual) only. Valid adapter type for those controllers is lsilogic.
|
||||
// Hence use adapter type lsilogic. Other adapter types ide, lsilogic, buslogic are valid and does not need to be modified.
|
||||
VmdkAdapterType newAdapterType = VmdkAdapterType.lsilogic;
|
||||
s_logger.debug("Updating adapter type to " + newAdapterType + " from " + currentAdapterTypeStr + " for VMDK file " + vmdkFileName);
|
||||
Pair<DatacenterMO, String> dcInfo = getOwnerDatacenter();
|
||||
byte[] newVmdkContent = vmdkFileDescriptor.changeVmdkAdapterType(vmdkInfo.second(), newAdapterType.toString());
|
||||
String vmdkUploadUrl = getContext().composeDatastoreBrowseUrl(dcInfo.first().getName(), vmdkFileName);
|
||||
|
||||
getContext().uploadResourceContent(vmdkUploadUrl, newVmdkContent);
|
||||
s_logger.debug("Updated VMDK file " + vmdkFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs, String diskController) throws Exception {
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - attachDisk(). target MOR: " + _mor.getValue() + ", vmdkDatastorePath: "
|
||||
+ new Gson().toJson(vmdkDatastorePathChain) + ", datastore: " + morDs.getValue());
|
||||
int controllerKey = 0;
|
||||
int unitNumber = 0;
|
||||
|
||||
if (DiskControllerType.getType(diskController) == DiskControllerType.ide) {
|
||||
// IDE virtual disk cannot be added if VM is running
|
||||
if (getPowerState() == VirtualMachinePowerState.POWERED_ON) {
|
||||
throw new Exception("Adding a virtual disk over IDE controller is not supported while VM is running in VMware hypervisor. Please re-try when VM is not running.");
|
||||
}
|
||||
// Get next available unit number and controller key
|
||||
int ideDeviceCount = getNumberOfIDEDevices();
|
||||
if (ideDeviceCount >= VmwareHelper.MAX_IDE_CONTROLLER_COUNT * VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER) {
|
||||
throw new Exception("Maximum limit of devices supported on IDE controllers [" + VmwareHelper.MAX_IDE_CONTROLLER_COUNT
|
||||
* VmwareHelper.MAX_ALLOWED_DEVICES_IDE_CONTROLLER + "] is reached.");
|
||||
}
|
||||
controllerKey = getIDEControllerKey(ideDeviceCount);
|
||||
unitNumber = getFreeUnitNumberOnIDEController(controllerKey);
|
||||
} else {
|
||||
controllerKey = getScsiDiskControllerKey(diskController);
|
||||
unitNumber = -1;
|
||||
}
|
||||
synchronized (_mor.getValue().intern()) {
|
||||
VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, null, controllerKey, vmdkDatastorePathChain, morDs, unitNumber, 1);
|
||||
controllerKey = newDisk.getControllerKey();
|
||||
unitNumber = newDisk.getUnitNumber();
|
||||
VirtualDiskFlatVer2BackingInfo backingInfo = (VirtualDiskFlatVer2BackingInfo)newDisk.getBacking();
|
||||
String vmdkFileName = backingInfo.getFileName();
|
||||
DiskControllerType diskControllerType = DiskControllerType.getType(diskController);
|
||||
VmdkAdapterType vmdkAdapterType = VmdkAdapterType.getAdapterType(diskControllerType);
|
||||
if (vmdkAdapterType == VmdkAdapterType.none) {
|
||||
String message = "Failed to attach disk due to invalid vmdk adapter type for vmdk file [" +
|
||||
vmdkFileName + "] with controller : " + diskControllerType;
|
||||
s_logger.debug(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
updateVmdkAdapter(vmdkFileName, vmdkAdapterType.toString());
|
||||
VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec();
|
||||
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
|
||||
|
||||
deviceConfigSpec.setDevice(newDisk);
|
||||
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
reConfigSpec.getDeviceChange().add(deviceConfigSpec);
|
||||
|
||||
ManagedObjectReference morTask = _context.getService().reconfigVMTask(_mor, reConfigSpec);
|
||||
boolean result = _context.getVimClient().waitForTask(morTask);
|
||||
|
||||
if (!result) {
|
||||
if (s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - attachDisk() done(failed)");
|
||||
throw new Exception("Failed to attach disk due to " + TaskMO.getTaskFailureInfo(_context, morTask));
|
||||
}
|
||||
|
||||
_context.waitForTaskProgressDone(morTask);
|
||||
}
|
||||
|
||||
if(s_logger.isTraceEnabled())
|
||||
s_logger.trace("vCenter API trace - attachDisk() done(successfully)");
|
||||
}
|
||||
|
||||
private int getControllerBusNumber(int controllerKey) 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 VirtualController && device.getKey() == controllerKey) {
|
||||
return ((VirtualController)device).getBusNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Exception("SCSI Controller with key " + controllerKey + " is Not Found");
|
||||
|
||||
}
|
||||
|
||||
public void attachDisk(String[] vmdkDatastorePathChain, ManagedObjectReference morDs) throws Exception {
|
||||
|
||||
if (s_logger.isTraceEnabled())
|
||||
@ -1760,20 +1887,17 @@ public class VirtualMachineMO extends BaseMO {
|
||||
}
|
||||
}
|
||||
|
||||
public String getGuestId() throws Exception {
|
||||
return (String)_context.getVimClient().getDynamicProperty(_mor, "config.guestId");
|
||||
}
|
||||
|
||||
public GuestOsDescriptor getGuestOsDescriptor(String guestOsId) throws Exception {
|
||||
GuestOsDescriptor guestOsDescriptor = null;
|
||||
if (guestOsId == null) {
|
||||
guestOsId = getGuestId();
|
||||
String guestId = guestOsId;
|
||||
if (guestId == null) {
|
||||
guestId = getGuestId();
|
||||
}
|
||||
ManagedObjectReference vmEnvironmentBrowser = _context.getVimClient().getMoRefProp(_mor, "environmentBrowser");
|
||||
VirtualMachineConfigOption vmConfigOption = _context.getService().queryConfigOption(vmEnvironmentBrowser, null, null);
|
||||
List<GuestOsDescriptor> guestDescriptors = vmConfigOption.getGuestOSDescriptor();
|
||||
for (GuestOsDescriptor descriptor : guestDescriptors) {
|
||||
if (guestOsId != null && guestOsId.equalsIgnoreCase(descriptor.getId())) {
|
||||
if (guestId != null && guestId.equalsIgnoreCase(descriptor.getId())) {
|
||||
guestOsDescriptor = descriptor;
|
||||
break;
|
||||
}
|
||||
@ -1912,6 +2036,134 @@ public class VirtualMachineMO extends BaseMO {
|
||||
}
|
||||
}
|
||||
|
||||
public int getPvScsiDeviceControllerKeyNoException() 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 ParaVirtualSCSIController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getPvScsiDeviceControllerKey() 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 ParaVirtualSCSIController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (false);
|
||||
throw new Exception("VMware Paravirtual SCSI Controller Not Found");
|
||||
}
|
||||
|
||||
public void ensurePvScsiDeviceController(int requiredNumScsiControllers, int availableBusNum) throws Exception {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < requiredNumScsiControllers) {
|
||||
ParaVirtualSCSIController scsiController = new ParaVirtualSCSIController();
|
||||
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controllers to the VM " + getName());
|
||||
} else {
|
||||
s_logger.info("Successfully added " + requiredNumScsiControllers + " SCSI controllers.");
|
||||
}
|
||||
}
|
||||
|
||||
public String getRecommendedDiskController(String guestOsId) throws Exception {
|
||||
String recommendedController;
|
||||
GuestOsDescriptor guestOsDescriptor = getGuestOsDescriptor(guestOsId);
|
||||
recommendedController = VmwareHelper.getRecommendedDiskControllerFromDescriptor(guestOsDescriptor);
|
||||
return recommendedController;
|
||||
}
|
||||
|
||||
public boolean isPvScsiSupported() throws Exception {
|
||||
int virtualHardwareVersion;
|
||||
|
||||
virtualHardwareVersion = getVirtualHardwareVersion();
|
||||
|
||||
// Check if virtual machine is using hardware version 7 or later.
|
||||
if (virtualHardwareVersion < 7) {
|
||||
s_logger.error("The virtual hardware version of the VM is " + virtualHardwareVersion
|
||||
+ ", which doesn't support PV SCSI controller type for virtual harddisks. Please upgrade this VM's virtual hardware version to 7 or later.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (false);
|
||||
throw new Exception(diskController + " Controller Not Found");
|
||||
}
|
||||
|
||||
public int getScsiDiskControllerKeyNoException(String diskController) 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 ((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();
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getNextScsiDiskDeviceNumber() throws Exception {
|
||||
int scsiControllerKey = getScsiDeviceControllerKey();
|
||||
int deviceNumber = getNextDeviceNumber(scsiControllerKey);
|
||||
@ -1924,7 +2176,7 @@ public class VirtualMachineMO extends BaseMO {
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualLsiLogicController) {
|
||||
if (device instanceof VirtualSCSIController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
@ -1949,11 +2201,12 @@ public class VirtualMachineMO extends BaseMO {
|
||||
}
|
||||
|
||||
public int getScsiDeviceControllerKeyNoException() throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
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 VirtualLsiLogicController) {
|
||||
if(devices != null && devices.size() > 0) {
|
||||
for(VirtualDevice device : devices) {
|
||||
if(device instanceof VirtualLsiLogicController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
@ -1983,6 +2236,32 @@ public class VirtualMachineMO extends BaseMO {
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureScsiDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getScsiDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controllers to the VM " + getName());
|
||||
} else {
|
||||
s_logger.info("Successfully added " + count + " SCSI controllers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return pair of VirtualDisk and disk device bus name(ide0:0, etc)
|
||||
public Pair<VirtualDisk, String> getDiskDevice(String vmdkDatastorePath) throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
@ -2361,6 +2640,67 @@ public class VirtualMachineMO extends BaseMO {
|
||||
throw new Exception("IDE Controller Not Found");
|
||||
}
|
||||
|
||||
public int getIDEControllerKey(int ideUnitNumber) throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int requiredIdeController = ideUnitNumber / VmwareHelper.MAX_IDE_CONTROLLER_COUNT;
|
||||
|
||||
int ideControllerCount = 0;
|
||||
if(devices != null && devices.size() > 0) {
|
||||
for(VirtualDevice device : devices) {
|
||||
if(device instanceof VirtualIDEController) {
|
||||
if (ideControllerCount == requiredIdeController) {
|
||||
return ((VirtualIDEController)device).getKey();
|
||||
}
|
||||
ideControllerCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
throw new Exception("IDE Controller Not Found");
|
||||
}
|
||||
|
||||
public int getNumberOfIDEDevices() throws Exception {
|
||||
int ideDeviceCount = 0;
|
||||
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 VirtualIDEController) {
|
||||
ideDeviceCount += ((VirtualIDEController)device).getDevice().size();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ideDeviceCount;
|
||||
}
|
||||
|
||||
public int getFreeUnitNumberOnIDEController(int controllerKey) throws Exception {
|
||||
int freeUnitNumber = 0;
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int deviceCount = 0;
|
||||
int ideDeviceUnitNumber = -1;
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualDisk && (controllerKey == device.getControllerKey())) {
|
||||
deviceCount++;
|
||||
ideDeviceUnitNumber = device.getUnitNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deviceCount == 1) {
|
||||
if (ideDeviceUnitNumber == 0) {
|
||||
freeUnitNumber = 1;
|
||||
} // else freeUnitNumber is already initialized to 0
|
||||
} else if (deviceCount == 2) {
|
||||
throw new Exception("IDE controller with key [" + controllerKey + "] already has 2 device attached. Cannot attach more than the limit of 2.");
|
||||
}
|
||||
return freeUnitNumber;
|
||||
}
|
||||
public int getNextIDEDeviceNumber() throws Exception {
|
||||
int controllerKey = getIDEDeviceControllerKey();
|
||||
return getNextDeviceNumber(controllerKey);
|
||||
@ -2378,26 +2718,6 @@ public class VirtualMachineMO extends BaseMO {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getPCIDeviceControllerKey() throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualPCIController) {
|
||||
return ((VirtualPCIController)device).getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (false);
|
||||
throw new Exception("PCI Controller Not Found");
|
||||
}
|
||||
|
||||
public int getNextPCIDeviceNumber() throws Exception {
|
||||
int controllerKey = getPCIDeviceControllerKey();
|
||||
return getNextDeviceNumber(controllerKey);
|
||||
}
|
||||
|
||||
public int getNextDeviceNumber(int controllerKey) throws Exception {
|
||||
List<VirtualDevice> devices = _context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
@ -2653,6 +2973,9 @@ public class VirtualMachineMO extends BaseMO {
|
||||
public long getHotAddMemoryLimitInMb() throws Exception {
|
||||
return (Long)_context.getVimClient().getDynamicProperty(_mor, "config.hotPlugMemoryLimit");
|
||||
}
|
||||
public String getGuestId() throws Exception {
|
||||
return (String)_context.getVimClient().getDynamicProperty(_mor, "config.guestId");
|
||||
}
|
||||
|
||||
public int getCoresPerSocket() throws Exception {
|
||||
// number of cores per socket is 1 in case of ESXi. It's not defined explicitly and the property is support since vSphere API 5.0.
|
||||
@ -2729,6 +3052,135 @@ public class VirtualMachineMO extends BaseMO {
|
||||
}
|
||||
return guestOsSupportsMemoryHotAdd && virtualHardwareSupportsMemoryHotAdd;
|
||||
}
|
||||
public void ensureLsiLogicSasDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getLsiLogicSasDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualLsiLogicSASController scsiController = new VirtualLsiLogicSASController();
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi controller of type LsiLogic SAS.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getLsiLogicSasDeviceControllerKeyNoException() 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 VirtualLsiLogicSASController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void ensureBusLogicDeviceControllers(int count, int availableBusNum) throws Exception {
|
||||
int scsiControllerKey = getBusLogicDeviceControllerKeyNoException();
|
||||
if (scsiControllerKey < 0) {
|
||||
VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
|
||||
|
||||
int busNum = availableBusNum;
|
||||
while (busNum < count) {
|
||||
VirtualBusLogicController scsiController = new VirtualBusLogicController();
|
||||
|
||||
scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
|
||||
scsiController.setBusNumber(busNum);
|
||||
scsiController.setKey(busNum - VmwareHelper.MAX_SCSI_CONTROLLER_COUNT);
|
||||
VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
|
||||
scsiControllerSpec.setDevice(scsiController);
|
||||
scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
|
||||
vmConfig.getDeviceChange().add(scsiControllerSpec);
|
||||
busNum++;
|
||||
}
|
||||
|
||||
if (configureVm(vmConfig)) {
|
||||
throw new Exception("Unable to add Scsi BusLogic controllers to the VM " + getName());
|
||||
} else {
|
||||
s_logger.info("Successfully added " + count + " SCSI BusLogic controllers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getBusLogicDeviceControllerKeyNoException() 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 VirtualBusLogicController) {
|
||||
return device.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Ternary<Integer, Integer, DiskControllerType> getScsiControllerInfo() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
|
||||
getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
int scsiControllerCount = 0;
|
||||
int busNum = -1;
|
||||
DiskControllerType controllerType = DiskControllerType.lsilogic;
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualSCSIController) {
|
||||
scsiControllerCount++;
|
||||
int deviceBus = ((VirtualSCSIController)device).getBusNumber();
|
||||
if (busNum < deviceBus) {
|
||||
busNum = deviceBus;
|
||||
}
|
||||
if (device instanceof VirtualLsiLogicController) {
|
||||
controllerType = DiskControllerType.lsilogic;
|
||||
} else if (device instanceof VirtualLsiLogicSASController) {
|
||||
controllerType = DiskControllerType.lsisas1068;
|
||||
} else if (device instanceof VirtualBusLogicController) {
|
||||
controllerType = DiskControllerType.buslogic;
|
||||
} else if (device instanceof ParaVirtualSCSIController) {
|
||||
controllerType = DiskControllerType.pvscsi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Ternary<Integer, Integer, DiskControllerType>(scsiControllerCount, busNum, controllerType);
|
||||
}
|
||||
|
||||
public int getNumberOfVirtualDisks() throws Exception {
|
||||
List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor, "config.hardware.device");
|
||||
|
||||
s_logger.info("Counting disk devices attached to VM " + getVmName());
|
||||
int count = 0;
|
||||
|
||||
if (devices != null && devices.size() > 0) {
|
||||
for (VirtualDevice device : devices) {
|
||||
if (device instanceof VirtualDisk) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean consolidateVmDisks() throws Exception {
|
||||
ManagedObjectReference morTask = _context.getService().consolidateVMDisksTask(_mor);
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.vmware.mo;
|
||||
|
||||
public enum VmdkAdapterType {
|
||||
ide,
|
||||
lsilogic,
|
||||
buslogic,
|
||||
none;
|
||||
|
||||
public static VmdkAdapterType getAdapterType(DiskControllerType diskControllerType) {
|
||||
if (diskControllerType == DiskControllerType.ide) {
|
||||
return VmdkAdapterType.ide;
|
||||
} else if (diskControllerType == DiskControllerType.buslogic) {
|
||||
return VmdkAdapterType.buslogic;
|
||||
} else if (diskControllerType == DiskControllerType.lsilogic || diskControllerType == DiskControllerType.pvscsi || diskControllerType == DiskControllerType.lsisas1068) {
|
||||
return VmdkAdapterType.lsilogic;
|
||||
} else {
|
||||
return VmdkAdapterType.none;
|
||||
}
|
||||
}
|
||||
|
||||
public static VmdkAdapterType getType(String vmdkAdapterType) {
|
||||
if (vmdkAdapterType.equalsIgnoreCase("ide")) {
|
||||
return VmdkAdapterType.ide;
|
||||
} else if (vmdkAdapterType.equalsIgnoreCase("lsilogic")) {
|
||||
return VmdkAdapterType.lsilogic;
|
||||
} else if (vmdkAdapterType.equalsIgnoreCase("buslogic")) {
|
||||
return VmdkAdapterType.buslogic;
|
||||
} else {
|
||||
return VmdkAdapterType.none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,6 +29,9 @@ import org.apache.log4j.Logger;
|
||||
|
||||
public class VmdkFileDescriptor {
|
||||
private static final Logger s_logger = Logger.getLogger(VmdkFileDescriptor.class);
|
||||
private static final String VMDK_PROPERTY_CREATE_TYPE = "createType";
|
||||
private static final String VMDK_CREATE_TYPE_VMFSSPARSE = "vmfsSparse";
|
||||
private static final String VMDK_PROPERTY_ADAPTER_TYPE = "ddb.adapterType";
|
||||
|
||||
private Properties _properties = new Properties();
|
||||
private String _baseFileName;
|
||||
@ -84,6 +87,73 @@ public class VmdkFileDescriptor {
|
||||
return _properties.getProperty("parentFileNameHint");
|
||||
}
|
||||
|
||||
public boolean isVmfsSparseFile() {
|
||||
String vmdkCreateType = _properties.getProperty(VMDK_PROPERTY_CREATE_TYPE);
|
||||
if (vmdkCreateType.equalsIgnoreCase(VMDK_CREATE_TYPE_VMFSSPARSE)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getAdapterType() {
|
||||
return _properties.getProperty(VMDK_PROPERTY_ADAPTER_TYPE);
|
||||
}
|
||||
|
||||
|
||||
public static byte[] changeVmdkAdapterType(byte[] vmdkContent, String newAdapterType) throws IOException {
|
||||
assert (vmdkContent != null);
|
||||
|
||||
BufferedReader in = null;
|
||||
BufferedWriter out = null;
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(vmdkContent)));
|
||||
out = new BufferedWriter(new OutputStreamWriter(bos));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
// ignore empty and comment lines
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
out.newLine();
|
||||
continue;
|
||||
}
|
||||
if (line.charAt(0) == '#') {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] tokens = line.split("=");
|
||||
if (tokens.length == 2) {
|
||||
String name = tokens[0].trim();
|
||||
String value = tokens[1].trim();
|
||||
if (value.charAt(0) == '\"')
|
||||
value = value.substring(1, value.length() - 1);
|
||||
|
||||
if (newAdapterType != null && name.equals(VMDK_PROPERTY_ADAPTER_TYPE)) {
|
||||
out.write(name + "=\"" + newAdapterType + "\"");
|
||||
out.newLine();
|
||||
} else {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
}
|
||||
} else {
|
||||
out.write(line);
|
||||
out.newLine();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (in != null)
|
||||
in.close();
|
||||
if (out != null)
|
||||
out.close();
|
||||
}
|
||||
|
||||
return bos.toByteArray();
|
||||
|
||||
}
|
||||
|
||||
public static byte[] changeVmdkContentBaseInfo(byte[] vmdkContent, String baseFileName, String parentFileName) throws IOException {
|
||||
|
||||
assert (vmdkContent != null);
|
||||
|
||||
@ -23,6 +23,7 @@ import com.vmware.vim25.ObjectContent;
|
||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
||||
|
||||
import com.cloud.hypervisor.vmware.util.VmwareContext;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
/**
|
||||
* Interface to consolidate ESX(i) hosts and HA/FT clusters into a common interface used by CloudStack Hypervisor resources
|
||||
@ -53,7 +54,8 @@ public interface VmwareHypervisorHost {
|
||||
boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception;
|
||||
|
||||
boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB,
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception;
|
||||
int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent,
|
||||
Pair<String, String> controllerInfo, Boolean systemVm) throws Exception;
|
||||
|
||||
void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption) throws Exception;
|
||||
|
||||
@ -81,4 +83,5 @@ public interface VmwareHypervisorHost {
|
||||
ComputeResourceSummary getHyperHostHardwareSummary() throws Exception;
|
||||
|
||||
LicenseAssignmentManagerMO getLicenseAssignmentManager() throws Exception;
|
||||
String getRecommendedDiskController(String guestOsId) throws Exception;
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
|
||||
import com.vmware.vim25.DynamicProperty;
|
||||
import com.vmware.vim25.GuestOsDescriptor;
|
||||
import com.vmware.vim25.ManagedObjectReference;
|
||||
import com.vmware.vim25.MethodFault;
|
||||
import com.vmware.vim25.ObjectContent;
|
||||
@ -62,6 +63,8 @@ import com.vmware.vim25.VirtualMachineSnapshotTree;
|
||||
import com.vmware.vim25.VirtualPCNet32;
|
||||
import com.vmware.vim25.VirtualVmxnet2;
|
||||
import com.vmware.vim25.VirtualVmxnet3;
|
||||
|
||||
import com.cloud.hypervisor.vmware.mo.DiskControllerType;
|
||||
import com.cloud.hypervisor.vmware.mo.HostMO;
|
||||
import com.cloud.hypervisor.vmware.mo.LicenseAssignmentManagerMO;
|
||||
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
|
||||
@ -75,6 +78,11 @@ public class VmwareHelper {
|
||||
@SuppressWarnings("unused")
|
||||
private static final Logger s_logger = Logger.getLogger(VmwareHelper.class);
|
||||
|
||||
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 boolean isReservedScsiDeviceNumber(int deviceNumber) {
|
||||
return deviceNumber == 7;
|
||||
}
|
||||
@ -751,6 +759,19 @@ public class VmwareHelper {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||
}
|
||||
|
||||
public static String getRecommendedDiskControllerFromDescriptor(GuestOsDescriptor guestOsDescriptor) throws Exception {
|
||||
String recommendedController;
|
||||
|
||||
recommendedController = guestOsDescriptor.getRecommendedDiskController();
|
||||
|
||||
// By-pass auto detected PVSCSI controller to use LsiLogic Parallel instead
|
||||
if (DiskControllerType.getType(recommendedController) == DiskControllerType.pvscsi) {
|
||||
recommendedController = DiskControllerType.lsilogic.toString();
|
||||
}
|
||||
|
||||
return recommendedController;
|
||||
}
|
||||
|
||||
public static String trimSnapshotDeltaPostfix(String name) {
|
||||
String[] tokens = name.split("-");
|
||||
if (tokens.length > 1 && tokens[tokens.length - 1].matches("[0-9]{6,}")) {
|
||||
@ -762,4 +783,8 @@ public class VmwareHelper {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static boolean isControllerOsRecommended(String dataDiskController) {
|
||||
return DiskControllerType.getType(dataDiskController) == DiskControllerType.osdefault;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user