/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.vsm.monitor.esxi; import java.net.MalformedURLException; import java.net.URL; import java.rmi.RemoteException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.abiquo.vsm.events.VMEventType; import com.abiquo.vsm.exception.MonitorException; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.ObjectSpec; import com.vmware.vim25.PropertyFilterSpec; import com.vmware.vim25.PropertySpec; import com.vmware.vim25.SelectionSpec; import com.vmware.vim25.ServiceContent; import com.vmware.vim25.TraversalSpec; import com.vmware.vim25.VimPortType; import com.vmware.vim25.VirtualMachineConfigInfo; import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.mo.ServiceInstance; /** * WMI Connector for ESXi monitoring tasks. * * @author ibarrera */ public class ESXiConnector { /** The logger. */ private final static Logger LOGGER = LoggerFactory.getLogger(ESXiConnector.class); private ManagedObjectReference rootFolder; private static PropertySpec[] virtualMachineSpec; private ObjectSpec[] rootObjSpecs; private static SelectionSpec[] selectionSpecs; private ServiceInstance serviceInstance; private static final String POWERED_OFF = "poweredOff"; private static final String POWERED_ON = "poweredOn"; public ESXiConnector() { super(); // Set the transactionSpec route to Host. We build the whole inventory tree // to search any 'managedObjectType' selectionSpecs = buildFullTraversal(); virtualMachineSpec = new PropertySpec[] {new PropertySpec()}; virtualMachineSpec[0].setType("VirtualMachine"); virtualMachineSpec[0].setAll(true); } public static VMEventType translateState(String state) { if (state.equalsIgnoreCase(POWERED_OFF)) { return VMEventType.POWER_OFF; } else if (state.equalsIgnoreCase(POWERED_ON)) { return VMEventType.POWER_ON; } else { return VMEventType.PAUSED; } } /** * Connects to the hypervisor. * * @param physicalMachineAddress The address of the hypervisor. * @param username The user name used to connect to the hypervisor. * @param password The password used to connect to the hypervisor. * @throws MonitorException If connection fails. */ public void connect(String physicalMachineAddress, String username, String password) throws MonitorException { LOGGER.trace("Connecting to ESXi host: {}", physicalMachineAddress); try { URL url = new URL(physicalMachineAddress); URL connectionURL = new URL("https://" + url.getHost() + ":" + url.getPort() + "/sdk"); serviceInstance = new ServiceInstance(connectionURL, username, password, true); /* * serviceInstance = new ServiceInstance(new URL("https://" + physicalMachineAddress + * "/sdk"), username, password, true); */ } catch (MalformedURLException ex) { throw new MonitorException("Invalid connection URI: " + physicalMachineAddress, ex); } catch (Exception ex) { throw new MonitorException("Could not connect to ESXi host: " + physicalMachineAddress, ex); } } /** * Get the state of the specified virtual machine. * * @param virtualMachineName The name of the virtual machine. * @return The virtual machine state. * @throws MonitorException If an error occurs retrieving machine state. */ public VMEventType getState(String virtualMachineName) throws MonitorException { try { // Find the concrete virtual machine ObjectContent[] esxiMachines = getManagedObjectReferencesFromInventory(virtualMachineSpec); for (ObjectContent esxiMachine : esxiMachines) { VirtualMachineConfigInfo vmConfig = getVMConfigFromObjectContent(esxiMachine); if (vmConfig != null && vmConfig.getName().equals(virtualMachineName)) { return getStateForObject(esxiMachine); } } } catch (Exception ex) { throw new MonitorException("Could not retrieve the state of machine: " + virtualMachineName, ex); } throw new MonitorException("Could not retrieve the state of machine: " + virtualMachineName); } /** * Get the information of all virtual machines in the target physical machine. * * @return The information of all virtual machines in the target physical machine. * @throws MonitorException If the list of virtual machine information cannot be obtained. */ public ObjectContent[] getAllVMs() throws MonitorException { try { return getManagedObjectReferencesFromInventory(virtualMachineSpec); } catch (Exception ex) { throw new MonitorException("Could not get the list of virtual machines", ex); } } public VMEventType getStateForObject(ObjectContent esxiMachine) throws MonitorException { VirtualMachineConfigInfo vmConfig = getVMConfigFromObjectContent(esxiMachine); try { // Solve [ABICLOUDPREMIUM-321] VirtualMachineRuntimeInfo runInfo = null; boolean found = false; DynamicProperty[] dps = esxiMachine.getPropSet(); for (int i = 0; i < dps.length && !found; i++) { Object dp = dps[i].getVal(); if (dp instanceof VirtualMachineRuntimeInfo) { runInfo = (VirtualMachineRuntimeInfo) dp; found = true; } } if (runInfo == null) { throw new MonitorException("Could not retrieve the state of machine: " + vmConfig.getName()); } return translateState(runInfo.getPowerState().name()); } catch (Exception ex) { throw new MonitorException("Could not retrieve the state of machine: " + vmConfig.getName(), ex); } } /** * Disconnects from the hypervisor. * * @param physicalMachineAddress The hypervisor address. */ public void disconnect(String physicalMachineAddress) { LOGGER.trace("Disconnecting from ESXi host: {}", physicalMachineAddress); if (serviceInstance != null && serviceInstance.getServerConnection() != null) { serviceInstance.getServerConnection().logout(); serviceInstance = null; } } /** * Encapsulates the call to get the {@link VirtualMachineConfigInfo} object. * * @param esxiMachine remote deployed machine * @return the configuration of the deployed machine or null if is not an instance of * VirtualMachineConfigInfo. */ public VirtualMachineConfigInfo getVMConfigFromObjectContent(final ObjectContent esxiMachine) { Object value = esxiMachine.getPropSet()[2].getVal(); VirtualMachineConfigInfo configuration = null; if (value instanceof VirtualMachineConfigInfo) { configuration = (VirtualMachineConfigInfo) esxiMachine.getPropSet()[2].getVal(); } return configuration; } /** * This auxiliar method return a list of ManagedObjectReference encapsulated into an * ObjectContent instance. Informing the name of the managed object reference as a parameter, * will return the list of MORs whatever is its place into the inventory hierarchy of the VI * SDK. * * @param managedObjectType name of the MOR we want to retrieve * @return list of ObjectContent with the result of the search. * @throws RemoteException if there is any problem working with the remote objects */ private ObjectContent[] getManagedObjectReferencesFromInventory(PropertySpec[] propSpec) throws RemoteException { // Set the PropertyFilter Spec previous to put toghether the property Spec // and the objectSpec PropertyFilterSpec propertyFilter = new PropertyFilterSpec(); propertyFilter.setPropSet(propSpec); propertyFilter.setObjectSet(getRootObjectSpec()); // Do the search! This search will return all the matching MOR of the // 'managedObjectType' type ObjectContent[] objectContent = getMyConn().retrieveProperties(getServiceContent().getPropertyCollector(), new PropertyFilterSpec[] {propertyFilter}); return objectContent; } /** * @return the myConn */ public VimPortType getMyConn() { return serviceInstance.getServerConnection().getVimService(); } private ObjectSpec[] getRootObjectSpec() { if (rootObjSpecs == null) { rootObjSpecs = new ObjectSpec[] {new ObjectSpec()}; rootObjSpecs[0].setObj(getRootFolder()); rootObjSpecs[0].setSkip(Boolean.FALSE); rootObjSpecs[0].setSelectSet(selectionSpecs); } return rootObjSpecs; } private ManagedObjectReference getRootFolder() { if (rootFolder == null) { rootFolder = getServiceContent().getRootFolder(); } return rootFolder; } /** * @return the serviceContent */ public ServiceContent getServiceContent() { return serviceInstance.getServiceContent(); } /** * This method creates a SelectionSpec[] to traverses the entire inventory tree starting at a * Folder. * * @return The SelectionSpec[] */ private static SelectionSpec[] buildFullTraversal() { SelectionSpec rpToVmSpec = createSelectionSpec("rpToVm"); SelectionSpec rpToRpSpec = createSelectionSpec("rpToRp"); // ResourcePool to itself TraversalSpec rpToRp = createTraversalSpec("rpToRp", "ResourcePool", "resourcePool", rpToRpSpec, rpToVmSpec); // ResourcePool to Vm TraversalSpec rpToVm = createTraversalSpec("rpToVm", "ResourcePool", "vm", new SelectionSpec[] {}); // ComputerResource to ResourcePool TraversalSpec crToRp = createTraversalSpec("crToRp", "ComputeResource", "resourcePool", rpToRpSpec, rpToVmSpec); // ComputerResource to Host TraversalSpec crToH = createTraversalSpec("crToH", "ComputeResource", "host", new SelectionSpec[] {}); SelectionSpec visitFoldersSpec = createSelectionSpec("visitFolders"); // Datacenter to hostFolder TraversalSpec dcToHf = createTraversalSpec("dcToHf", "Datacenter", "hostFolder", visitFoldersSpec); // Datacenter to vm Folder TraversalSpec dcToVmf = createTraversalSpec("dcToVmf", "Datacenter", "vmFolder", visitFoldersSpec); // Host to Vm TraversalSpec hToVm = createTraversalSpec("HToVm", "HostSystem", "vm", visitFoldersSpec); // Root folder to others TraversalSpec visitFolders = createTraversalSpec("visitFolders", "Folder", "childEntity", visitFoldersSpec, createSelectionSpec("dcToHf"), createSelectionSpec("dcToVmf"), createSelectionSpec("crToH"), createSelectionSpec("crToRp"), createSelectionSpec("HToVm"), rpToVmSpec); return new SelectionSpec[] {visitFolders, dcToVmf, dcToHf, crToH, crToRp, rpToRp, hToVm, rpToVm}; } private static SelectionSpec createSelectionSpec(String name) { SelectionSpec s = new SelectionSpec(); s.setName(name); return s; } private static TraversalSpec createTraversalSpec(String name, String type, String path, SelectionSpec... selectSet) { TraversalSpec traversalSpec = new TraversalSpec(); traversalSpec.setName(name); traversalSpec.setType(type); traversalSpec.setPath(path); traversalSpec.setSkip(false); traversalSpec.setSelectSet(selectSet); return traversalSpec; } }