// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
//
// Automatically generated by addcopyright.py at 04/03/2012
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.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.apache.log4j.Logger;
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
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.ManagedObjectReference;
import com.vmware.vim25.MethodFault;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.OptionValue;
import com.vmware.vim25.ResourceAllocationInfo;
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.VirtualMachineConfigSpec;
import com.vmware.vim25.VirtualMachineSnapshotTree;
import com.vmware.vim25.VirtualPCNet32;
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 VirtualDevice prepareNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType,
String portGroupName, String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
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();
}
VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
nicBacking.setDeviceName(portGroupName);
nicBacking.setNetwork(morNetwork);
nic.setBacking(nicBacking);
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setAllowGuestControl(true);
connectInfo.setConnected(conntected);
connectInfo.setStartConnected(connectOnStart);
nic.setAddressType("Manual");
nic.setConnectable(connectInfo);
nic.setMacAddress(macAddress);
nic.setUnitNumber(deviceNumber);
nic.setKey(-contextNumber);
return nic;
}
public static VirtualDevice prepareDvNicDevice(VirtualMachineMO vmMo, ManagedObjectReference morNetwork, VirtualEthernetCardType deviceType,
String dvPortGroupName, String dvSwitchUuid, String macAddress, int deviceNumber, int contextNumber, boolean conntected, boolean connectOnStart) throws Exception {
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();
}
final VirtualEthernetCardDistributedVirtualPortBackingInfo dvPortBacking = new VirtualEthernetCardDistributedVirtualPortBackingInfo();
final DistributedVirtualSwitchPortConnection dvPortConnection = new DistributedVirtualSwitchPortConnection();
final VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
dvPortConnection.setSwitchUuid(dvSwitchUuid);
dvPortConnection.setPortgroupKey(morNetwork.get_value());
dvPortBacking.setPort(dvPortConnection);
nic.setBacking(dvPortBacking);
nic.setKey(30);
connectInfo.setAllowGuestControl(true);
connectInfo.setConnected(conntected);
connectInfo.setStartConnected(connectOnStart);
nic.setAddressType("Manual");
nic.setConnectable(connectInfo);
nic.setMacAddress(macAddress);
nic.setUnitNumber(deviceNumber);
nic.setKey(-contextNumber);
return nic;
}
// vmdkDatastorePath: [datastore name] vmdkFilePath
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePath,
int sizeInMb, ManagedObjectReference morDs, int deviceNumber, int contextNumber) throws Exception {
VirtualDisk disk = new VirtualDisk();
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
backingInfo.setDiskMode(VirtualDiskMode.persistent.toString());
backingInfo.setThinProvisioned(true);
backingInfo.setEagerlyScrub(false);
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePath);
disk.setBacking(backingInfo);
if(controllerKey < 0)
controllerKey = vmMo.getIDEDeviceControllerKey();
if(deviceNumber < 0)
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
disk.setControllerKey(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;
}
// 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());
}
if(controllerKey < 0)
controllerKey = vmMo.getIDEDeviceControllerKey();
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;
}
// vmdkDatastorePath: [datastore name] vmdkFilePath
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePathChain[],
ManagedObjectReference morDs, int deviceNumber, int contextNumber) throws Exception {
assert(vmdkDatastorePathChain != null);
assert(vmdkDatastorePathChain.length >= 1);
VirtualDisk disk = new VirtualDisk();
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
backingInfo.setDatastore(morDs);
backingInfo.setFileName(vmdkDatastorePathChain[0]);
backingInfo.setDiskMode(VirtualDiskMode.persistent.toString());
if(vmdkDatastorePathChain.length > 1) {
String[] parentDisks = new String[vmdkDatastorePathChain.length - 1];
for(int i = 0; i < vmdkDatastorePathChain.length - 1; i++)
parentDisks[i] = vmdkDatastorePathChain[i + 1];
setParentBackingInfo(backingInfo, morDs, parentDisks);
}
disk.setBacking(backingInfo);
if(controllerKey < 0)
controllerKey = vmMo.getIDEDeviceControllerKey();
if(deviceNumber < 0)
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
disk.setControllerKey(controllerKey);
disk.setKey(-contextNumber);
disk.setUnitNumber(deviceNumber);
VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo();
connectInfo.setConnected(true);
connectInfo.setStartConnected(true);
disk.setConnectable(connectInfo);
return disk;
}
public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey,
Pair<String, ManagedObjectReference>[] vmdkDatastorePathChain,
int deviceNumber, int contextNumber) throws Exception {
assert(vmdkDatastorePathChain != null);
assert(vmdkDatastorePathChain.length >= 1);
VirtualDisk disk = new VirtualDisk();
VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo();
backingInfo.setDatastore(vmdkDatastorePathChain[0].second());
backingInfo.setFileName(vmdkDatastorePathChain[0].first());
backingInfo.setDiskMode(VirtualDiskMode.persistent.toString());
if(vmdkDatastorePathChain.length > 1) {
Pair<String, ManagedObjectReference>[] parentDisks = new Pair[vmdkDatastorePathChain.length - 1];
for(int i = 0; i < vmdkDatastorePathChain.length - 1; i++)
parentDisks[i] = vmdkDatastorePathChain[i + 1];
setParentBackingInfo(backingInfo, parentDisks);
}
disk.setBacking(backingInfo);
if(controllerKey < 0)
controllerKey = vmMo.getIDEDeviceControllerKey();
if(deviceNumber < 0)
deviceNumber = vmMo.getNextDeviceNumber(controllerKey);
disk.setControllerKey(controllerKey);
disk.setKey(-contextNumber);
disk.setUnitNumber(deviceNumber);
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.toString());
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);
}
private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo,
Pair<String, ManagedObjectReference>[] parentDatastorePathList) {
VirtualDiskFlatVer2BackingInfo parentBacking = new VirtualDiskFlatVer2BackingInfo();
parentBacking.setDatastore(parentDatastorePathList[0].second());
parentBacking.setDiskMode(VirtualDiskMode.persistent.toString());
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(VirtualMachineSnapshotTree[] snapTree, String findName) {
assert(findName != null);
ManagedObjectReference snapMor = null;
if (snapTree == null)
return snapMor;
for (int i = 0; i < snapTree.length && snapMor == null; i++) {
VirtualMachineSnapshotTree node = snapTree[i];
if (node.getName().equals(findName)) {
snapMor = node.getSnapshot();
} else {
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));
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 setBasicVmConfig(VirtualMachineConfigSpec vmConfig, int cpuCount, int cpuSpeedMHz, int cpuReservedMhz,
int memoryMB, int memoryReserveMB, String guestOsIdentifier, boolean limitCpuUse) {
// 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);
vmConfig.setGuestId(guestOsIdentifier);
}
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) {
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 void deleteVolumeVmdkFiles(DatastoreMO dsMo, String volumeName, DatacenterMO dcMo) throws Exception {
String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeName);
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
volumeDatastorePath = String.format("[%s] %s-flat.vmdk", dsMo.getName(), volumeName);
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
volumeDatastorePath = String.format("[%s] %s-delta.vmdk", dsMo.getName(), volumeName);
dsMo.deleteFile(volumeDatastorePath, dcMo.getMor(), true);
}
public static String getExceptionMessage(Throwable e) {
return getExceptionMessage(e, false);
}
public static String getExceptionMessage(Throwable e, boolean printStack) {
if(e instanceof MethodFault) {
final StringWriter writer = new StringWriter();
writer.append("Exception: " + e.getClass().getName() + "\n");
writer.append("message: " + ((MethodFault)e).getFaultString() + "\n");
if(printStack) {
writer.append("stack: ");
e.printStackTrace(new PrintWriter(writer));
}
return writer.toString();
}
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()));
}
}