/**
* Copyright (c) 2016 Inria
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* - Christophe Gourdin <christophe.gourdin@inria.fr>
*
*/
package org.occiware.clouddesigner.occi.infrastructure.connector.vmware.utils;
import java.rmi.RemoteException;
import org.occiware.clouddesigner.occi.infrastructure.connector.vmware.addons.exceptions.MountVMWareToolsDiskException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.RuntimeFault;
import com.vmware.vim25.TaskInfo;
import com.vmware.vim25.TaskInfoState;
import com.vmware.vim25.VirtualDevice;
import com.vmware.vim25.VirtualDeviceConfigSpec;
import com.vmware.vim25.VirtualDeviceConfigSpecFileOperation;
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
import com.vmware.vim25.VirtualDisk;
import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo;
import com.vmware.vim25.VirtualHardware;
import com.vmware.vim25.VirtualLsiLogicController;
import com.vmware.vim25.VirtualMachineConfigSpec;
import com.vmware.vim25.VirtualMachinePowerState;
import com.vmware.vim25.VirtualMachineQuickStats;
import com.vmware.vim25.VirtualMachineToolsStatus;
import com.vmware.vim25.VirtualSCSISharing;
import com.vmware.vim25.mo.Datacenter;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ResourcePool;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.Task;
import com.vmware.vim25.mo.VirtualMachine;
/**
* Helper for Virtual Machine operations.
*
* @author Christophe Gourdin - Inria
*
*/
public class VMHelper {
private static Logger LOGGER = LoggerFactory.getLogger(VMHelper.class);
/**
* The virtual machine is currently powered off.
*/
public static final String POWER_OFF = "poweredOff";
/**
* The virtual machine is currently powered on.
*/
public static final String POWER_ON = "poweredOn";
public static final int POWER_ON_INT = 1;
public static final int POWER_OFF_INT = 0;
/**
* The virtual machine is currently suspended.
*/
public static final String SUSPENDED = "suspended";
public static final int SUSPENDED_INT = 2;
public static final String VIRTUAL_MACHINE = "VirtualMachine";
/**
* Search for a VirtualMachine on tree folder for a name.
*
* @param folder
* @param name
* @return a VirtualMachine object, null if not found.
*/
public static VirtualMachine findVMForName(final Folder folder, final String name) {
VirtualMachine vm = null;
try {
vm = (VirtualMachine) new InventoryNavigator(folder).searchManagedEntity(VIRTUAL_MACHINE, name);
} catch (RemoteException ex) {
LOGGER.error("Error while searching a virtual machine : " + name + " --> " + ex.getMessage());
}
return vm;
}
/**
* Find a virtual machine for a managed object reference id.
*
* @param folder
* (rootFolder etc.)
* @param morId
* @return a VirtualMachine object, null, if none.
*/
public static VirtualMachine findVMForMorId(final Folder folder, final String morId) {
VirtualMachine vm = null;
try {
ManagedEntity[] entities = new InventoryNavigator(folder).searchManagedEntities("VirtualMachine");
if (entities != null && entities.length > 0) {
for (ManagedEntity entity : entities) {
if (entity.getMOR().getVal().equals(morId)) {
vm = (VirtualMachine) entity;
break;
}
}
}
} catch (RemoteException ex) {
LOGGER.error("Error while searching a virtual machine by managed entity id : " + morId + " --> "
+ ex.getMessage());
}
return vm;
}
/**
* Search a VM for name and folder.
*
* @param folder
* (may be a root folder)
* @param name
* @return true if the VM exist else false.
*/
public static boolean isVMExistForName(final Folder folder, final String name) {
boolean isVmExist = false;
VirtualMachine vm = findVMForName(folder, name);
if (vm != null) {
isVmExist = true;
}
return isVmExist;
}
/**
* Build a Scsi Device for a new Virtual Machine
*
* @param cKey
* @return A new Scsi Device
*/
public static VirtualDeviceConfigSpec createScsiSpec(int cKey) {
VirtualDeviceConfigSpec scsiSpec = new VirtualDeviceConfigSpec();
scsiSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
VirtualLsiLogicController scsiCtrl = new VirtualLsiLogicController();
scsiCtrl.setKey(cKey);
scsiCtrl.setBusNumber(0);
scsiCtrl.setSharedBus(VirtualSCSISharing.noSharing);
scsiSpec.setDevice(scsiCtrl);
return scsiSpec;
}
/**
* For use only if you want to create a vm with an existing disk (vmdk
* file).
*
* @param filename
* @param cKey
* @param diskMode
* @return
*/
public static VirtualDeviceConfigSpec createExistingDiskSpec(String filename, int cKey, String diskMode) {
VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
diskSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
// Do not set diskspec.fileoperation !!!!
VirtualDisk vd = new VirtualDisk();
// Value is ignored but necessary for the process.
vd.setCapacityInKB(-1);
vd.setKey(0);
vd.setUnitNumber(1);
vd.setControllerKey(cKey);
VirtualDiskFlatVer2BackingInfo dskFileBacking = new VirtualDiskFlatVer2BackingInfo();
dskFileBacking.setFileName(filename);
dskFileBacking.setDiskMode(diskMode);
vd.setBacking(dskFileBacking);
diskSpec.setDevice(vd);
return diskSpec;
}
/**
* Build a vmDisk Device for a new Virtual Machine
*
* @param dsName
* DatastoreName
* @param cKey
* @param diskSizeKB
* Size of disk in KB
* @param diskMode
* Disk Mode: persistent, independent_persistent and
* independent_nonpersistent
* @return A new Disk Device
*/
public static VirtualDeviceConfigSpec createDiskSpec(String dsName, int cKey, long diskSizeKB, String diskMode) {
VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
diskSpec.setOperation(VirtualDeviceConfigSpecOperation.add);
diskSpec.setFileOperation(VirtualDeviceConfigSpecFileOperation.create);
VirtualDisk vd = new VirtualDisk();
vd.setCapacityInKB(diskSizeKB);
diskSpec.setDevice(vd);
vd.setKey(0);
vd.setUnitNumber(0);
vd.setControllerKey(cKey);
VirtualDiskFlatVer2BackingInfo diskfileBacking = new VirtualDiskFlatVer2BackingInfo();
String fileName = "[" + dsName + "]";
diskfileBacking.setFileName(fileName);
diskfileBacking.setDiskMode(diskMode);
diskfileBacking.setThinProvisioned(true);
vd.setBacking(diskfileBacking);
return diskSpec;
}
/**
* Set or unset the hotReconfig option. (to reconfig a vm cpu and memory,
* hot mode)
*
* @param folder
* (folder to search vm)
* @param name
* (name of the vm)
* @param hotReconfig,
* if true, hotReconfig is enabled, else disabled.
*/
public static void hotReconfigEnable(final Folder folder, String name, boolean hotReconfig) {
// Search the vm.
VirtualMachine vm = VMHelper.findVMForName(folder, name);
Task task = null;
VirtualMachineConfigSpec changeSpec = new VirtualMachineConfigSpec();
changeSpec.setCpuHotAddEnabled(true);
changeSpec.setMemoryHotAddEnabled(true);
boolean retVal = false;
if (vm != null && (!vm.getConfig().getCpuHotAddEnabled() || !vm.getConfig().getMemoryHotAddEnabled())) {
try {
task = vm.powerOffVM_Task();
} catch (RemoteException ex) {
LOGGER.error("Unable to enable/disable hot reconfiguration of this virtual machine : " + vm.getName());
LOGGER.error("Cause : " + ex.getMessage());
return;
}
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vm.getName() + " powered off");
} else {
LOGGER.info("VM cant poweroff");
LOGGER.error("Unable to enable/disable hot reconfiguration of this virtual machine : "
+ vm.getName());
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RuntimeFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (retVal && !vm.getRuntime().getPowerState().equals(VirtualMachinePowerState.poweredOff)) {
// this vm is poweredoff.
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info(
"VM " + name + " configuration updated - HotAdd plugin enabled for CPU and Memory");
} else {
LOGGER.info("VM " + name + " cannot be reconfigured");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RuntimeFault e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
}
/**
* Mount guest vmware tools, it's important to make it accessible directly
* to client.
*
* @param folder
* @param name
* @throws MountVMWareToolsDiskException
*/
public static void mountGuestVmTools(final Folder folder, final String name) throws MountVMWareToolsDiskException {
VirtualMachine vm = VMHelper.findVMForName(folder, name);
try {
vm.mountToolsInstaller();
} catch (RemoteException ex) {
LOGGER.info("Unable to mount VMWare tools installer !");
throw new MountVMWareToolsDiskException("Unable to mount VMWare tools installer !", ex.getCause());
}
}
/**
* Find an hostSystem for a vm, if there is hostSystemName information, and
* compare with the hosted vmName for each vms of each host.
*
* @param vmName
* @return a hostSystem name, may return null if not found.
*/
public static String findHostSystemNameForVM(final Folder rootFolder, final String vmName) {
String hostSystemName = null;
try {
boolean found = false;
HostSystem hostSystem = null;
ManagedEntity[] hostsystems = new InventoryNavigator(rootFolder).searchManagedEntities("HostSystem");
for (ManagedEntity hostsystem : hostsystems) {
HostSystem host = (HostSystem) hostsystem;
VirtualMachine[] vms = host.getVms();
for (VirtualMachine vm : vms) {
if (vm.getName().equals(vmName)) {
hostSystem = host;
found = true;
break;
}
}
if (found)
break;
}
hostSystemName = hostSystem.getName();
} catch (RemoteException ex) {
LOGGER.error("cant find the hostname of this virtual machine : " + vmName);
}
return hostSystemName;
}
/**
* Find an hostSystem Object for a vm, if there is hostSystem information,
* and compare with the hosted vmName for each vms of each host.
*
* @param vmName
* @return a hostSystem, may return null if not found.
*/
public static HostSystem findHostSystemForVM(final Folder rootFolder, final String vmName) {
HostSystem hostSystem = null;
try {
boolean found = false;
ManagedEntity[] hostsystems = new InventoryNavigator(rootFolder).searchManagedEntities("HostSystem");
for (ManagedEntity hostsystem : hostsystems) {
HostSystem host = (HostSystem) hostsystem;
VirtualMachine[] vms = host.getVms();
for (VirtualMachine vm : vms) {
if (vm.getName().equals(vmName)) {
hostSystem = host;
found = true;
break;
}
}
if (found)
break;
}
} catch (RemoteException ex) {
LOGGER.error("cant find the hostname of this virtual machine : " + vmName);
}
return hostSystem;
}
/**
* Get the number of virtual sockets.
*
* @param vm
* @return an Integer that represents the number of cores.
*/
public static Integer getNumSockets(final VirtualMachine vm) {
Integer nbSockets = 0;
if (vm != null) {
VirtualHardware hw = vm.getConfig().getHardware();
nbSockets = hw.getNumCPU() / hw.getNumCoresPerSocket();
}
return nbSockets;
}
public static Integer getNumCPU(final VirtualMachine vm) {
Integer nbCpu = 0;
if (vm != null) {
VirtualHardware hw = vm.getConfig().getHardware();
nbCpu = hw.getNumCPU();
}
return nbCpu;
}
/**
* Get the number of core per socket.
*
* @param vm
* @return an Integer.
*/
public static Integer getNumCorePerSocket(final VirtualMachine vm) {
Integer coresPerSocket = 0;
if (vm != null) {
VirtualHardware hw = vm.getConfig().getHardware();
coresPerSocket = hw.getNumCoresPerSocket();
}
return coresPerSocket;
}
/**
* Get the memory size in GigaBytes.
*
* @param vm
* @return a Float
*/
public static Float getMemoryGB(final VirtualMachine vm) {
Float memoryGB = 0.0f;
if (vm != null) {
VirtualHardware hw = vm.getConfig().getHardware();
Integer memMB = hw.getMemoryMB();
Float memMBFT = memMB.floatValue();
memoryGB = memMBFT / 1024;
}
return memoryGB;
}
/**
* Get the overall disk size in GB for ephemeral disk (system disk).
*
* @param vm
* @return 0 if none, size in GB.
*/
public static Float getEphemalDiskSize(final VirtualMachine vm) {
Float diskSizeGB = 0.0f;
if (vm != null) {
VirtualDevice devices[] = vm.getConfig().getHardware().getDevice();
int unitNumber;
if (devices != null && devices.length > 0) {
for (VirtualDevice device : devices) {
if (device instanceof VirtualDisk) {
VirtualDisk disk = (VirtualDisk) device;
unitNumber = disk.getUnitNumber();
if (unitNumber == 0) {
// This is the main disk storage !
// Get the value of its size.
Long dskSizeKB = disk.getCapacityInKB();
diskSizeGB = dskSizeKB.floatValue() / (1024 * 1024);
break;
}
}
}
}
}
return diskSizeGB;
}
/**
* Get the architecture (occi format) x86 (32 bits) or x64 (64 bits).
*
* @param vm
* @return a String
*/
public static String getArchitecture(final VirtualMachine vm) {
String architecture = "x86";
if (vm != null) {
String guestFullName = vm.getConfig().getGuestFullName();
if (guestFullName != null && guestFullName.contains("64")) {
architecture = "x64";
} // elsewere this is not defined by vmware.
}
return architecture;
}
/**
* Get the cpu speed in Ghz.
*
* @param vm
* @return a Float, the cpu speed current demand by the vm, there is no
* value on exact cpu speed at this time through the VMWare api.
*/
public static Float getCPUSpeed(final VirtualMachine vm) {
Float cpuSpeed = 0.0f;
if (vm != null) {
VirtualMachineQuickStats qstats = vm.getSummary().getQuickStats();
// In MHz.
Integer cpuSpeedDemand = qstats.getOverallCpuDemand();
// In Ghz.
cpuSpeed = cpuSpeedDemand.floatValue() / 1000;
}
return cpuSpeed;
}
/**
* Get the state of this compute (VMWare format). poweredOff The virtual
* machine is currently powered off. poweredOn The virtual machine is
* currently powered on. suspended The virtual machine is currently
* suspended.
*
* @param vm
* @return a String
*/
public static String getPowerState(final VirtualMachine vm) {
// Get the current state of this vm.
String state = null;
if (vm != null) {
state = vm.getSummary().getRuntime().getPowerState().name();
}
return state;
}
/**
* Operation mode of guest operating system, via guestInfo. "running" -
* Guest is running normally. "shuttingdown" - Guest has a pending shutdown
* command. "resetting" - Guest has a pending reset command. "standby" -
* Guest has a pending standby command. "notrunning" - Guest is not running.
* "unknown" - Guest information is not available.
*
* @param vm
* @return
*/
public static String getGuestState(final VirtualMachine vm) {
String state = null;
if (vm != null) {
state = vm.getGuest().getGuestState();
}
return state;
}
/**
* Get the guest hostname if known.
*
* @param vm
* @return if the guest hostname is not known, this may return null.
*/
public static String getGuestHostname(final VirtualMachine vm) {
String hostname = null;
if (vm != null && isToolsInstalled(vm) && isToolsRunning(vm)) {
hostname = vm.getGuest().getHostName();
}
return hostname;
}
/**
* Check if hot add pluging is enabled for CPU
*
* @param vmname
* @return
* @throws InvalidProperty
* @throws RuntimeFault
* @throws RemoteException
*/
public Boolean getHotAddCPU(final VirtualMachine vm) throws RemoteException {
return vm.getConfig().getCpuHotAddEnabled();
}
/**
* Check if hot add plugin is enabled for Memory
*
* @param vm
* @return
* @throws InvalidProperty
* @throws RuntimeFault
* @throws RemoteException
*/
public Boolean getHotAddMemory(final VirtualMachine vm) throws RemoteException {
return vm.getConfig().getMemoryHotAddEnabled();
}
/**
* Enable Hot Add plugin - need Stop and Start task
*
* @param vm
* @throws InvalidProperty
* @throws RuntimeFault
* @throws RemoteException
*/
public static void enableVmHotAddPlugin(final VirtualMachine vm) throws RemoteException {
VirtualMachineConfigSpec changeSpec = new VirtualMachineConfigSpec();
Task task = null;
boolean retVal = false;
String vmName = vm.getName();
String lastPowerState = getPowerState(vm);
if (!vm.getConfig().getCpuHotAddEnabled() || !vm.getConfig().getMemoryHotAddEnabled()) {
task = vm.powerOffVM_Task();
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vmName + " switched off");
} else {
LOGGER.info("VM " + vmName + "cannot powerOff");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
LOGGER.warn("Cannot stop Virtual Machine " + vmName);
}
if (retVal && getPowerState(vm).equals(POWER_OFF)) {
changeSpec.setCpuHotAddEnabled(true);
changeSpec.setMemoryHotAddEnabled(true);
task = vm.reconfigVM_Task(changeSpec);
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vmName
+ " configuration updated - HotAdd plugin enabled for CPU and Memory");
} else {
LOGGER.info("VM " + vmName + " cannot be reconfigured");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// We powerOn if this is the last state.
if (lastPowerState.equals(POWER_ON) && vm.getGuest().getGuestState().equals(POWER_OFF)) {
task = vm.powerOnVM_Task(null);
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vmName + " switched on");
} else {
LOGGER.warn("VM " + vmName + " cannot be switched on");
}
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
LOGGER.info("Cannot start Virtual Machine: " + vmName);
}
}
} else {
LOGGER.info("Something go wrong, cant reconfigure the virtual machine : " + vmName);
}
}
LOGGER.info("HotAdd plugin already enabled");
}
/**
* Change configuration for a VM - Hot or cold.
*
* @param vm
* @param vCPU
* (optional may be null)
* @param vRamSizeGB
* (optional may be null) in GigaBytes
* @param summary
* annotation on vm.
* @return
* @throws InvalidProperty
* @throws RuntimeFault
* @throws RemoteException
*/
public static void reconfigureVm(final VirtualMachine vm, final Integer vCPU, final Float vRamSizeGB,
String summary) throws RemoteException {
if (vm == null) {
LOGGER.warn("The virtual machine object doesnt exist for hot/cold reconfiguration");
return;
}
boolean execReconf = false;
VirtualMachineConfigSpec changeSpec = new VirtualMachineConfigSpec();
String vmName = vm.getName();
String currentPowerState = getPowerState(vm);
if (currentPowerState.equals(SUSPENDED)) {
LOGGER.warn("Cannot reconfigure virtual machine, the virtual machine is in suspended state.");
return;
}
LOGGER.info("Reconfiguration of the virtual machine : " + vmName + " --> state: " + currentPowerState);
Task task = null;
boolean retVal = false;
Long memoryMB = null;
if (summary != null) {
execReconf = true;
changeSpec.setAnnotation(summary);
}
int oldVCPU = getNumCPU(vm);
int currentNbCorePerSocket = getNumCorePerSocket(vm);
LOGGER.info("Current number of vcpu : " + oldVCPU);
LOGGER.info("NumCoresPerSocket " + currentNbCorePerSocket);
// CPU part, to add or remove a cpu, the current VCPU must be different
// from the value VCPU TO set !
if (vCPU != null && vCPU > 0 && vCPU != oldVCPU) {
int approximateNumVSockets = (int) ((vCPU + currentNbCorePerSocket - 1) / currentNbCorePerSocket);
LOGGER.info("Approximate NumVSockets " + approximateNumVSockets);
// Hot cpu reconfig case.
if (currentPowerState.equals(POWER_ON)) {
if ((vm.getConfig().getCpuHotAddEnabled() && vCPU > oldVCPU)
|| (vm.getConfig().getCpuHotRemoveEnabled() && vCPU < oldVCPU)) {
changeSpec.setNumCPUs(approximateNumVSockets * currentNbCorePerSocket);
LOGGER.info("Hot reconfiguration --> VM : " + vmName + " , changing cpu from " + oldVCPU + " to "
+ vCPU.intValue());
execReconf = true;
}
}
// Cold cpu reconfig case.
if (currentPowerState.equals(POWER_OFF)) {
changeSpec.setNumCPUs(1);
changeSpec.setNumCoresPerSocket(1);
task = vm.reconfigVM_Task(changeSpec);
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("Cold reconfiguration --> VM " + vmName + " change cpu from " + oldVCPU
+ " to 1, OK");
changeSpec.setNumCPUs(vCPU);
changeSpec.setCpuHotAddEnabled(true);
changeSpec.setCpuHotRemoveEnabled(true);
changeSpec.setMemoryHotAddEnabled(true);
LOGGER.info("Cold reconfiguration --> VM " + vmName + " change cpu from 1 "
+ "to " + vCPU);
execReconf = true;
} else {
LOGGER.info("Cant reconfigure virtual machine.");
return;
}
} catch (InterruptedException ex) {
LOGGER.error("Cant reconfigure virtual machine.");
return;
}
}
}
}
Float ramInit = getMemoryGB(vm);
// Be warned, the ram size is explained in GB not in MB. VMWare explain
// the ram in MegaBytes.
if (vRamSizeGB != null && vRamSizeGB > 0.0 && vRamSizeGB != ramInit) {
LOGGER.info("VM " + vmName + " change memory from " + ramInit + " to " + vRamSizeGB);
Float memoryMBfl = vRamSizeGB * 1024;
memoryMB = memoryMBfl.longValue();
if (ramInit > vRamSizeGB) {
LOGGER.info("VM : " + vmName
+ " Cannot reconfigure memory, the reconfiguration memory must be superior to the current virtual machine memory.");
return;
}
if (currentPowerState.equals(POWER_ON)) {
if (vm.getConfig().getMemoryHotAddEnabled()) {
changeSpec.setMemoryMB(memoryMB);
LOGGER.info("VM " + vmName + " change memory from " + ramInit + "GB to " + vRamSizeGB + "GB");
execReconf = true;
}
}
if (currentPowerState.equals(POWER_OFF)) {
changeSpec.setMemoryMB(memoryMB);
changeSpec.setMemoryHotAddEnabled(true);
execReconf = true;
}
}
// Exec reconf part.
if (execReconf) {
task = vm.reconfigVM_Task(changeSpec);
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vmName + " configuration updated ");
} else {
LOGGER.warn("VM " + vmName + " cannot be reconfigured");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
LOGGER.error(
"VM " + vmName + " cannot be reconfigured, the reconfiguration task has been interrupted.");
}
}
}
}
/**
* Check if vmware tools are installed on virtual machine.
*
* @param vm
* @return true if installed.
*/
public static boolean isToolsInstalled(final VirtualMachine vm) {
boolean result = false;
VirtualMachineToolsStatus toolsStatus = vm.getGuest().getToolsStatus();
if (!toolsStatus.equals(VirtualMachineToolsStatus.toolsNotInstalled)) {
result = true;
}
return result;
}
/**
* Check if vmware tools are running on virtual machine.
*
* @param vm
* @return
*/
public static boolean isToolsRunning(final VirtualMachine vm) {
boolean result = false;
VirtualMachineToolsStatus toolsStatus = vm.getGuest().getToolsStatus();
if (!toolsStatus.equals(VirtualMachineToolsStatus.toolsNotRunning)) {
result = true;
}
return result;
}
/**
* Power on a virtual machine.
*
* @param vm
*/
public static boolean powerOn(VirtualMachine vm) throws RemoteException, InterruptedException {
Task task = null;
boolean retVal = false;
String vmName = vm.getName();
task = vm.powerOnVM_Task(null);
if (task != null) {
retVal = task.waitForTask().equals(Task.SUCCESS);
} else {
LOGGER.warn("Cannot start Virtual Machine : " + vmName);
}
return retVal;
}
/**
* Graceful power off a virtual machine. (shutdown guest os before
* poweroff).
*
* @param vm
*/
public static boolean graceFulPowerOff(VirtualMachine vm) throws RemoteException, InterruptedException {
String vmName = vm.getName();
boolean result = false;
if (isToolsInstalled(vm) && isToolsRunning(vm)) {
vm.shutdownGuest();
result = true;
LOGGER.info("OS of the VM " + vmName + " will be stopped");
} else {
LOGGER.info("OS of the VM " + vmName + " cannot be stopped, do you have installed the vmware tools ?");
result = powerOff(vm);
}
return result;
}
/**
* Power off a virtual machine.
*
* @param vm
*/
public static boolean powerOff(VirtualMachine vm) throws RemoteException, InterruptedException {
Task task = null;
boolean retVal = false;
String vmName = vm.getName();
task = vm.powerOffVM_Task();
if (task != null) {
retVal = task.waitForTask().equals(Task.SUCCESS);
} else {
LOGGER.warn("Cannot stop Virtual Machine : " + vmName);
}
return retVal;
}
/**
* Reboot guest os. Use by restart method Warm.
*
* @param vm
*/
public static boolean rebootGuest(VirtualMachine vm) throws RemoteException {
boolean result = false;
if (isToolsInstalled(vm) && isToolsRunning(vm)) {
vm.rebootGuest();
result = true;
} else {
LOGGER.error("There is no vmware tools installed and/or running, cant reboot the guest system.");
LOGGER.warn("please install vmware tools to use this operation.");
}
return result;
}
/**
* Suspend a virtual machine (pause).
*
* @param vm
*/
public static boolean suspendVM(VirtualMachine vm) throws RemoteException, InterruptedException {
Task task = null;
boolean retVal = false;
String vmName = vm.getName();
task = vm.suspendVM_Task();
if (task != null) {
try {
retVal = task.waitForTask().equals(Task.SUCCESS);
if (retVal) {
LOGGER.info("VM " + vmName + " suspended");
} else {
LOGGER.info("VM " + vmName + " cannot be suspended");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
LOGGER.warn("Cannot suspend Virtual Machine : " + vmName);
}
return retVal;
}
/**
* Hibernate a virtual machine (standby mode).
*
* @param vm
*/
public static boolean hibernateVM(VirtualMachine vm) throws RemoteException, InterruptedException {
boolean result = false;
if (isToolsInstalled(vm) && isToolsRunning(vm)) {
vm.standbyGuest();
result = true;
} else {
LOGGER.error("There is no vmware tools installed and/or running, cant standby the guest system.");
LOGGER.warn("please install vmware tools to use this operation.");
}
return result;
}
/**
* Load a vm object from vcenter with his name.
*
* @param vmName
* @return a virtual machine object loaded from vcenter and rootFolder.
*/
public static VirtualMachine loadVirtualMachine(final String vmName) {
// Load vm information to check if the vm is already started.
ServiceInstance si = VCenterClient.getServiceInstance();
Folder rootFolder = si.getRootFolder();
if (vmName == null) {
LOGGER.error("The title must be set, as it is used as the VM name (unique).");
return null;
}
VirtualMachine vm = VMHelper.findVMForName(rootFolder, vmName);
if (vm == null) {
LOGGER.warn("The virtual machine " + vmName + " doesn't exist anymore.");
return null;
}
return vm;
}
/**
* Destroy a virtual machine on vcenter.
*
* @param vm
*/
public static void destroyVM(final VirtualMachine vm) {
Task taskDelete = null;
String vmName = vm.getName();
boolean result;
// Delete the vm if this virtual machine exist on vcenter.
// Launch delete task.
LOGGER.info("Destroying vm : " + vmName);
try {
taskDelete = vm.destroy_Task();
if (taskDelete != null) {
try {
result = taskDelete.waitForTask().equals(Task.SUCCESS);
if (result) {
LOGGER.info("The virtual machine : " + vmName + " has been destroyed.");
} else {
LOGGER.warn("The virtual machine : " + vmName + " cannot be destroyed.");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} else {
LOGGER.warn("The virtual machine has not been destroyed, cant launch the destroy task !");
}
} catch (RemoteException ex) {
LOGGER.error("Error while trying to destroy a virtual machine.");
ex.printStackTrace();
}
}
/**
* Rename a vm on vcenter.
*
* @param vmOldName
* @param vmNewName
*/
public static void renameVM(VirtualMachine vm, final String vmNewName) throws RemoteException {
Task taskRename = null;
String vmName = vm.getName();
boolean result;
// Delete the vm if this virtual machine exist on vcenter.
// Launch delete task.
LOGGER.info("renaming vm : " + vmName + " to : " + vmNewName);
taskRename = vm.rename_Task(vmNewName);
if (taskRename != null) {
try {
result = taskRename.waitForTask().equals(Task.SUCCESS);
if (result) {
LOGGER.info("The virtual machine : " + vmName + " has been renamed to " + vmNewName);
} else {
LOGGER.warn("The virtual machine : " + vmName + " cannot be renamed.");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} else {
LOGGER.warn("The virtual machine has not been renamed, cant launch the rename task !");
}
}
/**
* Mark a vm as a template.
*
* @param vm
*/
public static boolean markAsTemplate(VirtualMachine vm) throws RemoteException {
boolean result = false;
if (vm.getConfig().isTemplate()) {
return result;
}
vm.markAsTemplate();
result = true;
return result;
}
/**
* Mark a template as a virtual machine.
*
* @param vmTemplate
* @param host
* @param pool
*/
public static boolean markAsVirtualMachine(VirtualMachine vmTemplate, HostSystem host, ResourcePool pool)
throws RemoteException {
boolean result = false;
if (!vmTemplate.getConfig().isTemplate()) {
return result;
}
vmTemplate.markAsVirtualMachine(pool, host);
result = true;
return result;
}
/**
* Get the TaskInfo object from task in progress on vm.
*
* @param vm
* @return
*/
public static TaskInfo getTaskInfo(VirtualMachine vm) {
TaskInfo taskInfo = null;
// ServiceInstance si = VCenterClient.getServiceInstance();
String vmName = vm.getName();
try {
Task[] tasks = vm.getRecentTasks();
TaskInfo taskInfTmp;
TaskInfoState taskInfoState;
if (tasks != null && tasks.length > 0) {
for (Task task : tasks) {
taskInfTmp = task.getTaskInfo();
taskInfoState = taskInfTmp.getState();
if (taskInfTmp != null && taskInfoState != null
&& (taskInfoState.equals(TaskInfoState.running)
|| taskInfoState.equals(TaskInfoState.success)
|| taskInfoState.equals(TaskInfoState.queued))) {
taskInfo = taskInfTmp;
break;
}
}
}
} catch (RemoteException ex) {
LOGGER.error("Cant retrieve informations about tasks for this virtual machine : " + vmName);
}
return taskInfo;
}
/**
* From inventory path, load the Folder object and return it, if path
* doesn't exist, the folder and subfolders are created.
*
* @param dataCenterVmFolder
* @param inventoryPath
* (format: /myfolder/subfolder1/subfolder2/ etc.
* @return
*/
public static Folder getInventoryFolderFromPath(Folder dataCenterVmFolder, final String inventoryPath) {
Folder folder = findOrCreateFolderFromPath(dataCenterVmFolder, inventoryPath);
if (folder == null) {
LOGGER.error("Folder cannot be created or retrieved.");
} else {
LOGGER.info("Folder on path : " + inventoryPath + " found !");
}
return folder;
}
/**
* Find a folder from a path like : /inria/test/experience1/ Note : This
* method create the missing folders if any on the path.
*
* @param folderPath
* @return A folder if exist, null if none.
*/
public static Folder findOrCreateFolderFromPath(Folder origin, String folderPath) {
Folder folder = null;
if (folderPath == null || folderPath.trim().isEmpty()) {
return folder;
}
if (origin == null) {
return folder;
}
if (folderPath.startsWith("/")) {
folderPath = folderPath.substring(1);
}
if (folderPath.endsWith("/")) {
folderPath = folderPath.substring(0, folderPath.length() - 1);
}
String[] foldersName = folderPath.split("/");
if (foldersName != null && foldersName.length > 0) {
String name = foldersName[0];
try {
if (name == null || name.isEmpty()) {
return null;
}
// Search the first folder name.
Folder myFolder = (Folder) new InventoryNavigator(origin).searchManagedEntity("Folder", name);
if (myFolder == null) {
System.out.println("Folder : " + name + " not found !!");
// Create it if name is not empty.
if (!name.isEmpty()) {
myFolder = origin.createFolder(name);
}
}
// Call recursively until the full path is ok.
int i = 0;
String tmpFolderPath = "";
for (String tmpName : foldersName) {
if (i > 0 && tmpName != null && !tmpName.trim().isEmpty()) {
tmpFolderPath += tmpName + "/";
}
i++;
}
if (!tmpFolderPath.isEmpty()) {
myFolder = findOrCreateFolderFromPath(myFolder, tmpFolderPath);
if (myFolder != null) {
return myFolder;
}
} else {
// End of check tree, return here the last value found.
return myFolder;
}
} catch (RemoteException ex) {
LOGGER.error("Cant retrieve informations about folder : " + folderPath);
}
}
if (folder == null) {
LOGGER.warn("Folder on path : " + folderPath + " not found.");
}
return folder;
}
/**
* Find a vm folder path like /INRIA/test/
*
* @param vm
* a virtual machine object.
* @return a folder path from vmFolder like /INRIA/test/, may return null if
* errors.
*/
public static String getVMFolderPath(VirtualMachine vm) {
String folderPath = "";
if (vm == null) {
return null;
}
// Folder vmFolder = dc.getVmFolder();
boolean folderVmFound = false;
// Get the parent.
ManagedEntity entityParent = vm.getParent();
Folder folder;
if (entityParent instanceof Folder) {
folder = (Folder) entityParent;
if (folder.getParent() instanceof Datacenter) {
return "/";
} else {
folderPath = "/" + folder.getName() + "/";
}
}
while (!folderVmFound && entityParent != null) {
entityParent = entityParent.getParent();
if (entityParent.getParent() instanceof Datacenter) {
folderVmFound = true;
} else if (entityParent instanceof Folder) {
folderPath = "/" + entityParent.getName() + folderPath;
}
}
LOGGER.debug("VM Folder path:---> " + folderPath);
return folderPath;
}
}