blob: 841d914af32bca16442efdff586c9e35fc98e0d2 [file] [log] [blame]
// 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.util;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
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;
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
import com.cloud.utils.LogUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.exception.ExceptionUtil;
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;
import com.vmware.vim25.OptionValue;
import com.vmware.vim25.PerfCounterInfo;
import com.vmware.vim25.PerfMetricId;
import com.vmware.vim25.ResourceAllocationInfo;
import com.vmware.vim25.StorageIOAllocationInfo;
import com.vmware.vim25.VirtualCdrom;
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
import com.vmware.vim25.VirtualCdromRemotePassthroughBackingInfo;
import com.vmware.vim25.VirtualDevice;
import com.vmware.vim25.VirtualDeviceBackingInfo;
import com.vmware.vim25.VirtualDeviceConnectInfo;
import com.vmware.vim25.VirtualDisk;
import com.vmware.vim25.VirtualDiskFlatVer1BackingInfo;
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
import com.vmware.vim25.VirtualDiskMode;
import com.vmware.vim25.VirtualDiskRawDiskMappingVer1BackingInfo;
import com.vmware.vim25.VirtualDiskSparseVer1BackingInfo;
import com.vmware.vim25.VirtualDiskSparseVer2BackingInfo;
import com.vmware.vim25.VirtualE1000;
import com.vmware.vim25.VirtualEthernetCard;
import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
import com.vmware.vim25.VirtualEthernetCardOpaqueNetworkBackingInfo;
import com.vmware.vim25.VirtualMachineConfigSpec;
import com.vmware.vim25.VirtualMachineSnapshotTree;
import com.vmware.vim25.VirtualPCNet32;
import com.vmware.vim25.VirtualUSBController;
import com.vmware.vim25.VirtualVmxnet2;
import com.vmware.vim25.VirtualVmxnet3;
public class VmwareHelper {
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 = 16;
public static final int MAX_SUPPORTED_DEVICES_SCSI_CONTROLLER = MAX_ALLOWED_DEVICES_SCSI_CONTROLLER - 1; // One device node is unavailable for hard disks or SCSI devices
public static final int MAX_USABLE_SCSI_CONTROLLERS = 2;
public static final String MIN_VERSION_UEFI_LEGACY = "5.5";
public static final String MIN_VERSION_VMFS6 = "6.5";
public static boolean isReservedScsiDeviceNumber(int deviceNumber) {
// The SCSI controller is assigned to virtual device node (z:7), so that device node is unavailable for hard disks or SCSI devices.
return (deviceNumber % VmwareHelper.MAX_ALLOWED_DEVICES_SCSI_CONTROLLER) == 7;
}
@Nonnull
private static VirtualDeviceConnectInfo getVirtualDeviceConnectInfo(boolean connected, boolean connectOnStart) {
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setAllowGuestControl(true);
connectInfo.setConnected(connected);
connectInfo.setStartConnected(connectOnStart);
return connectInfo;
}
@Nonnull
private static VirtualEthernetCard createVirtualEthernetCard(VirtualEthernetCardType deviceType) {
VirtualEthernetCard nic;
switch (deviceType) {
case E1000:
nic = new VirtualE1000();
break;
case PCNet32:
nic = new VirtualPCNet32();
break;
case Vmxnet2:
nic = new VirtualVmxnet2();
break;
case Vmxnet3:
nic = new VirtualVmxnet3();
break;
default:
assert (false);
nic = new VirtualE1000();
}
return nic;
}
public static VirtualDevice prepareNicOpaque(VirtualMachineMO vmMo, VirtualEthernetCardType deviceType, String portGroupName,
String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
assert(vmMo.getRunningHost().hasOpaqueNSXNetwork());
VirtualEthernetCard nic = createVirtualEthernetCard(deviceType);
VirtualEthernetCardOpaqueNetworkBackingInfo nicBacking = new VirtualEthernetCardOpaqueNetworkBackingInfo();
nicBacking.setOpaqueNetworkId("br-int");
nicBacking.setOpaqueNetworkType("nsx.network");
nic.setBacking(nicBacking);
nic.setAddressType("Manual");
nic.setConnectable(getVirtualDeviceConnectInfo(connected, connectOnStart));
nic.setMacAddress(macAddress);
nic.setKey(-contextNumber);
return nic;
}
public static void updateNicDevice(VirtualDevice nic, ManagedObjectReference morNetwork, String portGroupName) throws Exception {
VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
nicBacking.setDeviceName(portGroupName);
nicBacking.setNetwork(morNetwork);
nic.setBacking(nicBacking);
}
public static void updateDvNicDevice(VirtualDevice nic, ManagedObjectReference morNetwork, String dvSwitchUuid) throws Exception {
final VirtualEthernetCardDistributedVirtualPortBackingInfo dvPortBacking = new VirtualEthernetCardDistributedVirtualPortBackingInfo();
final DistributedVirtualSwitchPortConnection dvPortConnection = new DistributedVirtualSwitchPortConnection();
dvPortConnection.setSwitchUuid(dvSwitchUuid);
dvPortConnection.setPortgroupKey(morNetwork.getValue());
dvPortBacking.setPort(dvPortConnection);
nic.setBacking(dvPortBacking);
}
public static VirtualDevice prepareNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType, String portGroupName,
String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
VirtualEthernetCard nic = createVirtualEthernetCard(deviceType);
VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
nicBacking.setDeviceName(portGroupName);
nicBacking.setNetwork(morNetwork);
nic.setBacking(nicBacking);
nic.setAddressType("Manual");
nic.setConnectable(getVirtualDeviceConnectInfo(connected, connectOnStart));
nic.setMacAddress(macAddress);
nic.setKey(-contextNumber);
return nic;
}
public static VirtualDevice prepareDvNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType, String dvPortGroupName,
String dvSwitchUuid, String macAddress, int contextNumber, boolean connected, boolean connectOnStart) throws Exception {
VirtualEthernetCard nic = createVirtualEthernetCard(deviceType);
final VirtualEthernetCardDistributedVirtualPortBackingInfo dvPortBacking = new VirtualEthernetCardDistributedVirtualPortBackingInfo();
final DistributedVirtualSwitchPortConnection dvPortConnection = new DistributedVirtualSwitchPortConnection();
dvPortConnection.setSwitchUuid(dvSwitchUuid);
dvPortConnection.setPortgroupKey(morNetwork.getValue());
dvPortBacking.setPort(dvPortConnection);
nic.setBacking(dvPortBacking);
nic.setAddressType("Manual");
nic.setConnectable(getVirtualDeviceConnectInfo(connected, connectOnStart));
nic.setMacAddress(macAddress);
nic.setKey(-contextNumber);
return nic;
}
// vmdkDatastorePath: [datastore name] vmdkFilePath
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, VirtualDisk device, int controllerKey, String vmdkDatastorePathChain[],
ManagedObjectReference morDs, int deviceNumber, int contextNumber, Long maxIops) throws Exception {
s_logger.debug(LogUtils.logGsonWithoutException("Trying to prepare disk device to virtual machine [%s], using the following details: Virtual device [%s], "
+ "ManagedObjectReference [%s], ControllerKey [%s], VMDK path chain [%s], DeviceNumber [%s], ContextNumber [%s] and max IOPS [%s].",
vmMo, device, morDs, controllerKey, vmdkDatastorePathChain, deviceNumber, contextNumber, maxIops));
assert (vmdkDatastorePathChain != null);
assert (vmdkDatastorePathChain.length >= 1);
VirtualDisk disk;
VirtualDiskFlatVer2BackingInfo backingInfo;
if (device != null) {
disk = device;
backingInfo = (VirtualDiskFlatVer2BackingInfo)disk.getBacking();
} else {
disk = new VirtualDisk();
backingInfo = new VirtualDiskFlatVer2BackingInfo();
backingInfo.setDatastore(morDs);
backingInfo.setDiskMode(VirtualDiskMode.PERSISTENT.value());
disk.setBacking(backingInfo);
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
if (controllerKey < 0)
controllerKey = ideControllerKey;
if (deviceNumber < 0) {
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
}
disk.setControllerKey(controllerKey);
disk.setKey(-contextNumber);
disk.setUnitNumber(deviceNumber);
if (maxIops != null && maxIops > 0) {
s_logger.debug(LogUtils.logGsonWithoutException("Defining [%s] as the max IOPS of disk [%s].", maxIops, disk));
StorageIOAllocationInfo storageIOAllocationInfo = new StorageIOAllocationInfo();
storageIOAllocationInfo.setLimit(maxIops);
disk.setStorageIOAllocation(storageIOAllocationInfo);
}
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setConnected(true);
connectInfo.setStartConnected(true);
disk.setConnectable(connectInfo);
}
backingInfo.setFileName(vmdkDatastorePathChain[0]);
if (vmdkDatastorePathChain.length > 1) {
String[] parentDisks = Arrays.copyOfRange(vmdkDatastorePathChain, 1, vmdkDatastorePathChain.length);
setParentBackingInfo(backingInfo, morDs, parentDisks);
}
s_logger.debug(LogUtils.logGsonWithoutException("Prepared disk device, to attach to virtual machine [%s], has the following details: Virtual device [%s], "
+ "ManagedObjectReference [%s], ControllerKey [%s], VMDK path chain [%s], DeviceNumber [%s], ContextNumber [%s] and max IOPS [%s], is: [%s].",
vmMo, device, morDs, controllerKey, vmdkDatastorePathChain, deviceNumber, contextNumber, maxIops, disk));
return disk;
}
// vmdkDatastorePath: [datastore name] vmdkFilePath, create delta disk based on disk from template
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePath, int sizeInMb, ManagedObjectReference morDs,
VirtualDisk templateDisk, int deviceNumber, int contextNumber) throws Exception {
assert (templateDisk != null);
VirtualDeviceBackingInfo parentBacking = templateDisk.getBacking();
assert (parentBacking != null);
// TODO Not sure if we need to check if the disk in template and the new disk needs to share the
// same datastore
VirtualDisk disk = new VirtualDisk();
if (parentBacking instanceof VirtualDiskFlatVer1BackingInfo) {
VirtualDiskFlatVer1BackingInfo backingInfo = new VirtualDiskFlatVer1BackingInfo();
backingInfo.setDiskMode(((VirtualDiskFlatVer1BackingInfo)parentBacking).getDiskMode());
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
backingInfo.setParent((VirtualDiskFlatVer1BackingInfo)parentBacking);
disk.setBacking(backingInfo);
} else if (parentBacking instanceof VirtualDiskFlatVer2BackingInfo) {
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
backingInfo.setDiskMode(((VirtualDiskFlatVer2BackingInfo)parentBacking).getDiskMode());
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
backingInfo.setParent((VirtualDiskFlatVer2BackingInfo)parentBacking);
disk.setBacking(backingInfo);
} else if (parentBacking instanceof VirtualDiskRawDiskMappingVer1BackingInfo) {
VirtualDiskRawDiskMappingVer1BackingInfo backingInfo = new VirtualDiskRawDiskMappingVer1BackingInfo();
backingInfo.setDiskMode(((VirtualDiskRawDiskMappingVer1BackingInfo)parentBacking).getDiskMode());
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
backingInfo.setParent((VirtualDiskRawDiskMappingVer1BackingInfo)parentBacking);
disk.setBacking(backingInfo);
} else if (parentBacking instanceof VirtualDiskSparseVer1BackingInfo) {
VirtualDiskSparseVer1BackingInfo backingInfo = new VirtualDiskSparseVer1BackingInfo();
backingInfo.setDiskMode(((VirtualDiskSparseVer1BackingInfo)parentBacking).getDiskMode());
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
backingInfo.setParent((VirtualDiskSparseVer1BackingInfo)parentBacking);
disk.setBacking(backingInfo);
} else if (parentBacking instanceof VirtualDiskSparseVer2BackingInfo) {
VirtualDiskSparseVer2BackingInfo backingInfo = new VirtualDiskSparseVer2BackingInfo();
backingInfo.setDiskMode(((VirtualDiskSparseVer2BackingInfo)parentBacking).getDiskMode());
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
backingInfo.setParent((VirtualDiskSparseVer2BackingInfo)parentBacking);
disk.setBacking(backingInfo);
} else {
throw new Exception("Unsupported disk backing: " + parentBacking.getClass().getCanonicalName());
}
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
if (controllerKey < 0)
controllerKey = ideControllerKey;
disk.setControllerKey(controllerKey);
if (deviceNumber < 0) {
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
}
disk.setKey(-contextNumber);
disk.setUnitNumber(deviceNumber);
disk.setCapacityInKB(sizeInMb * 1024);
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setConnected(true);
connectInfo.setStartConnected(true);
disk.setConnectable(connectInfo);
return disk;
}
private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo, ManagedObjectReference morDs, String[] parentDatastorePathList) {
VirtualDiskFlatVer2BackingInfo parentBacking = new VirtualDiskFlatVer2BackingInfo();
parentBacking.setDatastore(morDs);
parentBacking.setDiskMode(VirtualDiskMode.PERSISTENT.value());
if (parentDatastorePathList.length > 1) {
String[] nextDatastorePathList = new String[parentDatastorePathList.length - 1];
for (int i = 0; i < parentDatastorePathList.length - 1; i++)
nextDatastorePathList[i] = parentDatastorePathList[i + 1];
setParentBackingInfo(parentBacking, morDs, nextDatastorePathList);
}
parentBacking.setFileName(parentDatastorePathList[0]);
backingInfo.setParent(parentBacking);
}
@SuppressWarnings("unchecked")
private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo, Pair<String, ManagedObjectReference>[] parentDatastorePathList) {
VirtualDiskFlatVer2BackingInfo parentBacking = new VirtualDiskFlatVer2BackingInfo();
parentBacking.setDatastore(parentDatastorePathList[0].second());
parentBacking.setDiskMode(VirtualDiskMode.PERSISTENT.value());
if (parentDatastorePathList.length > 1) {
Pair<String, ManagedObjectReference>[] nextDatastorePathList = new Pair[parentDatastorePathList.length - 1];
for (int i = 0; i < parentDatastorePathList.length - 1; i++)
nextDatastorePathList[i] = parentDatastorePathList[i + 1];
setParentBackingInfo(parentBacking, nextDatastorePathList);
}
parentBacking.setFileName(parentDatastorePathList[0].first());
backingInfo.setParent(parentBacking);
}
public static Pair<VirtualDevice, Boolean> prepareIsoDevice(VirtualMachineMO vmMo, String isoDatastorePath, ManagedObjectReference morDs, boolean connect,
boolean connectAtBoot, int deviceNumber, int contextNumber) throws Exception {
boolean newCdRom = false;
VirtualCdrom cdRom = (VirtualCdrom)vmMo.getIsoDevice();
if (cdRom == null) {
newCdRom = true;
cdRom = new VirtualCdrom();
assert (vmMo.getIDEDeviceControllerKey() >= 0);
cdRom.setControllerKey(vmMo.getIDEDeviceControllerKey());
if (deviceNumber < 0)
deviceNumber = vmMo.getNextIDEDeviceNumber();
cdRom.setUnitNumber(deviceNumber);
cdRom.setKey(-contextNumber);
}
VirtualDeviceConnectInfo cInfo = new VirtualDeviceConnectInfo();
cInfo.setConnected(connect);
cInfo.setStartConnected(connectAtBoot);
cdRom.setConnectable(cInfo);
if (isoDatastorePath != null) {
VirtualCdromIsoBackingInfo backingInfo = new VirtualCdromIsoBackingInfo();
backingInfo.setFileName(isoDatastorePath);
backingInfo.setDatastore(morDs);
cdRom.setBacking(backingInfo);
} else {
VirtualCdromRemotePassthroughBackingInfo backingInfo = new VirtualCdromRemotePassthroughBackingInfo();
backingInfo.setDeviceName("");
cdRom.setBacking(backingInfo);
}
return new Pair<VirtualDevice, Boolean>(cdRom, newCdRom);
}
public static VirtualDisk getRootDisk(VirtualDisk[] disks) {
if (disks.length == 1)
return disks[0];
// TODO : for now, always return the first disk as root disk
return disks[0];
}
public static ManagedObjectReference findSnapshotInTree(List<VirtualMachineSnapshotTree> snapTree, String findName) {
assert (findName != null);
ManagedObjectReference snapMor = null;
if (snapTree == null)
return snapMor;
for (int i = 0; i < snapTree.size() && snapMor == null; i++) {
VirtualMachineSnapshotTree node = snapTree.get(i);
if (node.getName().equals(findName)) {
snapMor = node.getSnapshot();
} else {
List<VirtualMachineSnapshotTree> childTree = node.getChildSnapshotList();
snapMor = findSnapshotInTree(childTree, findName);
}
}
return snapMor;
}
public static byte[] composeDiskInfo(List<Ternary<String, String, String>> diskInfo, int disksInChain, boolean includeBase) throws IOException {
BufferedWriter out = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
out = new BufferedWriter(new OutputStreamWriter(bos,"UTF-8"));
out.write("disksInChain=" + disksInChain);
out.newLine();
out.write("disksInBackup=" + diskInfo.size());
out.newLine();
out.write("baseDiskIncluded=" + includeBase);
out.newLine();
int seq = disksInChain - 1;
for (Ternary<String, String, String> item : diskInfo) {
out.write(String.format("disk%d.fileName=%s", seq, item.first()));
out.newLine();
out.write(String.format("disk%d.baseFileName=%s", seq, item.second()));
out.newLine();
if (item.third() != null) {
out.write(String.format("disk%d.parentFileName=%s", seq, item.third()));
out.newLine();
}
seq--;
}
out.newLine();
} finally {
if (out != null)
out.close();
}
return bos.toByteArray();
}
public static OptionValue[] composeVncOptions(OptionValue[] optionsToMerge, boolean enableVnc, String vncPassword, int vncPort, String keyboardLayout) {
int numOptions = 3;
boolean needKeyboardSetup = false;
if (keyboardLayout != null && !keyboardLayout.isEmpty()) {
numOptions++;
needKeyboardSetup = true;
}
if (optionsToMerge != null)
numOptions += optionsToMerge.length;
OptionValue[] options = new OptionValue[numOptions];
int i = 0;
if (optionsToMerge != null) {
for (int j = 0; j < optionsToMerge.length; j++)
options[i++] = optionsToMerge[j];
}
options[i] = new OptionValue();
options[i].setKey("RemoteDisplay.vnc.enabled");
options[i++].setValue(enableVnc ? "true" : "false");
options[i] = new OptionValue();
options[i].setKey("RemoteDisplay.vnc.password");
options[i++].setValue(vncPassword);
options[i] = new OptionValue();
options[i].setKey("RemoteDisplay.vnc.port");
options[i++].setValue("" + vncPort);
if (needKeyboardSetup) {
options[i] = new OptionValue();
options[i].setKey("RemoteDisplay.vnc.keymap");
options[i++].setValue(keyboardLayout);
}
return options;
}
public static void setVmScaleUpConfig(VirtualMachineConfigSpec vmConfig, int cpuCount, int cpuSpeedMHz, int cpuReservedMhz, int memoryMB, int memoryReserveMB,
boolean limitCpuUse) {
// VM config for scaling up
vmConfig.setMemoryMB((long)memoryMB);
vmConfig.setNumCPUs(cpuCount);
ResourceAllocationInfo cpuInfo = new ResourceAllocationInfo();
if (limitCpuUse) {
cpuInfo.setLimit((long)(cpuSpeedMHz * cpuCount));
} else {
cpuInfo.setLimit(-1L);
}
cpuInfo.setReservation((long)cpuReservedMhz);
vmConfig.setCpuAllocation(cpuInfo);
ResourceAllocationInfo memInfo = new ResourceAllocationInfo();
memInfo.setLimit((long)memoryMB);
memInfo.setReservation((long)memoryReserveMB);
vmConfig.setMemoryAllocation(memInfo);
}
public static void setBasicVmConfig(VirtualMachineConfigSpec vmConfig, int cpuCount, int cpuSpeedMHz, int cpuReservedMhz, int memoryMB, int memoryReserveMB,
String guestOsIdentifier, boolean limitCpuUse, boolean deployAsIs) {
// VM config basics
vmConfig.setMemoryMB((long)memoryMB);
vmConfig.setNumCPUs(cpuCount);
ResourceAllocationInfo cpuInfo = new ResourceAllocationInfo();
if (limitCpuUse) {
cpuInfo.setLimit(((long)cpuSpeedMHz * cpuCount));
} else {
cpuInfo.setLimit(-1L);
}
cpuInfo.setReservation((long)cpuReservedMhz);
vmConfig.setCpuAllocation(cpuInfo);
ResourceAllocationInfo memInfo = new ResourceAllocationInfo();
memInfo.setLimit((long)memoryMB);
memInfo.setReservation((long)memoryReserveMB);
vmConfig.setMemoryAllocation(memInfo);
if (!deployAsIs) {
// Deploy as-is uses the cloned VM guest OS
vmConfig.setGuestId(guestOsIdentifier);
}
}
public static VirtualDevice prepareUSBControllerDevice() {
s_logger.debug("Preparing USB controller(EHCI+UHCI) device");
VirtualUSBController usbController = new VirtualUSBController(); //EHCI+UHCI
usbController.setEhciEnabled(true);
usbController.setAutoConnectDevices(true);
return usbController;
}
public static PerfMetricId createPerfMetricId(PerfCounterInfo counterInfo, String instance) {
PerfMetricId metricId = new PerfMetricId();
metricId.setCounterId(counterInfo.getKey());
metricId.setInstance(instance);
return metricId;
}
public static String getDiskDeviceFileName(VirtualDisk diskDevice) {
VirtualDeviceBackingInfo backingInfo = diskDevice.getBacking();
if (backingInfo instanceof VirtualDiskFlatVer2BackingInfo) {
final String vmdkName = ((VirtualDiskFlatVer2BackingInfo)backingInfo).getFileName().replace(".vmdk", "");
if (vmdkName.contains("/")) {
return vmdkName.split("/", 2)[1];
}
return vmdkName;
}
return null;
}
public static ManagedObjectReference getDiskDeviceDatastore(VirtualDisk diskDevice) throws Exception {
VirtualDeviceBackingInfo backingInfo = diskDevice.getBacking();
assert (backingInfo instanceof VirtualDiskFlatVer2BackingInfo);
return ((VirtualDiskFlatVer2BackingInfo)backingInfo).getDatastore();
}
public static Object getPropValue(ObjectContent oc, String name) {
List<DynamicProperty> props = oc.getPropSet();
for (DynamicProperty prop : props) {
if (prop.getName().equalsIgnoreCase(name))
return prop.getVal();
}
return null;
}
public static String getFileExtension(String fileName, String defaultExtension) {
int pos = fileName.lastIndexOf('.');
if (pos < 0)
return defaultExtension;
return fileName.substring(pos);
}
public static boolean isSameHost(String ipAddress, String destName) {
// TODO : may need to do DNS lookup to compare IP address exactly
return ipAddress.equals(destName);
}
public static String getExceptionMessage(Throwable e) {
return getExceptionMessage(e, false);
}
public static String getExceptionMessage(Throwable e, boolean printStack) {
//TODO: in vim 5.1, exceptions do not have a base exception class, MethodFault becomes a FaultInfo that we can only get
// from individual exception through getFaultInfo, so we have to use reflection here to get MethodFault information.
try {
Class<? extends Throwable> cls = e.getClass();
Method mth = cls.getDeclaredMethod("getFaultInfo", (Class<?>)null);
if (mth != null) {
Object fault = mth.invoke(e, (Object[])null);
if (fault instanceof MethodFault) {
final StringWriter writer = new StringWriter();
writer.append("Exception: " + fault.getClass().getName() + "\n");
writer.append("message: " + ((MethodFault)fault).getFaultMessage() + "\n");
if (printStack) {
writer.append("stack: ");
e.printStackTrace(new PrintWriter(writer));
}
return writer.toString();
}
}
} catch (Exception ex) {
s_logger.info("[ignored]"
+ "failed to get message for exception: " + e.getLocalizedMessage());
}
return ExceptionUtil.toString(e, printStack);
}
public static VirtualMachineMO pickOneVmOnRunningHost(List<VirtualMachineMO> vmList, boolean bFirstFit) throws Exception {
List<VirtualMachineMO> candidates = new ArrayList<VirtualMachineMO>();
for (VirtualMachineMO vmMo : vmList) {
HostMO hostMo = vmMo.getRunningHost();
if (hostMo.isHyperHostConnected())
candidates.add(vmMo);
}
if (candidates.size() == 0)
return null;
if (bFirstFit)
return candidates.get(0);
Random random = new Random();
return candidates.get(random.nextInt(candidates.size()));
}
public static boolean isDvPortGroup(ManagedObjectReference networkMor) {
return "DistributedVirtualPortgroup".equalsIgnoreCase(networkMor.getType());
}
public static boolean isFeatureLicensed(VmwareHypervisorHost hyperHost, String featureKey) throws Exception {
boolean hotplugSupportedByLicense = false;
String licenseName;
LicenseAssignmentManagerMO licenseAssignmentMgrMo;
licenseAssignmentMgrMo = hyperHost.getLicenseAssignmentManager();
// Check if license supports the feature
hotplugSupportedByLicense = licenseAssignmentMgrMo.isFeatureSupported(featureKey, hyperHost.getMor());
// Fetch license name
licenseName = licenseAssignmentMgrMo.getHostLicenseName(hyperHost.getMor());
if (!hotplugSupportedByLicense) {
throw new Exception("hotplug feature is not supported by license : [" + licenseName + "] assigned to host : " + hyperHost.getHyperHostName());
}
return hotplugSupportedByLicense;
}
public static String getVCenterSafeUuid(DatastoreMO dsMo) throws Exception{
// Object name that is greater than 32 is not safe in vCenter
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
if (dsMo.getDatastoreType().equalsIgnoreCase("VVOL")) {
return CustomFieldConstants.CLOUD_UUID + "-" + uuid;
}
return uuid;
}
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,}")) {
List<String> trimmedTokens = new ArrayList<String>();
for (int i = 0; i < tokens.length - 1; i++)
trimmedTokens.add(tokens[i]);
return StringUtils.join(trimmedTokens, "-");
}
return name;
}
public static boolean isControllerOsRecommended(String dataDiskController) {
return DiskControllerType.getType(dataDiskController) == DiskControllerType.osdefault;
}
public static XMLGregorianCalendar getXMLGregorianCalendar(final Date date, final int offsetSeconds) throws DatatypeConfigurationException {
if (offsetSeconds > 0) {
date.setTime(date.getTime() - offsetSeconds * 1000);
}
final GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.setTime(date);
return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar);
}
public static HostMO getHostMOFromHostName(final VmwareContext context, final String hostName) {
HostMO host = null;
if (StringUtils.isNotBlank(hostName) && hostName.contains("@")) {
String hostMorInfo = hostName.split("@")[0];
if (hostMorInfo.contains(":")) {
ManagedObjectReference morHost = new ManagedObjectReference();
morHost.setType(hostMorInfo.split(":")[0]);
morHost.setValue(hostMorInfo.split(":")[1]);
host = new HostMO(context, morHost);
}
}
return host;
}
}