package com.intel.mtwilson.agent.vmware;
import com.intel.mountwilson.as.common.ASException;
import com.intel.mtwilson.datatypes.ConnectionString;
import com.intel.mtwilson.i18n.ErrorCode;
import com.intel.mtwilson.datatypes.TxtHostRecord;
import com.intel.dcsg.cpg.tls.policy.impl.InsecureTlsPolicy;
import com.intel.dcsg.cpg.tls.policy.TlsClient;
import com.intel.dcsg.cpg.tls.policy.TlsConnection;
import com.intel.dcsg.cpg.tls.policy.TlsPolicy;
import com.intel.dcsg.cpg.tls.policy.TlsUtil;
import com.vmware.vim25.*;
import com.vmware.vim25.InvalidProperty;
import com.vmware.vim25.RuntimeFault;
import java.rmi.RemoteException;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.ServiceInstance;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* How to use secure SSL connections:
*
* setSslHostnameVerifier();
* setSslTrustManager(SslUtil.createX509TrustManagerWithKeystore(simpleKeystore));
* connect(...)
*
* @author dsmagadX
*/
public class VMwareClient implements TlsClient {
private Logger log = LoggerFactory.getLogger(getClass());
private static final ManagedObjectReference SVC_INST_REF = new ManagedObjectReference();
private static final String SVC_INST_NAME = "ServiceInstance";
protected ServiceContent serviceContent;
private ManagedObjectReference propCollectorRef;
private ManagedObjectReference rootRef;
private ServiceInstance servInst;
private VimPortType vimPort;
private Folder rootFolder;
private static final double MIN_VCENTER_VERSION_FOR_MODULE_ATTESTATION = 5.1;
private static final double MIN_ESX_VERSION_FOR_MODULE_ATTESTATION = 5.1;
//private VimService vimService;
//private VimPortType vimPort;
UserSession session = null;
private String vcenterEndpoint = null;
private String vmwareConnectionString;
private TlsPolicy tlsPolicy = null;
//private HostnameVerifier hostnameVerifier = null;
//private X509TrustManager trustManager = null;
private boolean isConnected = false;
private static String[] meTree = {
"ManagedEntity",
"ComputeResource",
"ClusterComputeResource",
"Datacenter",
"Folder",
"HostSystem",
"ResourcePool",
"VirtualMachine"
};
private static String[] crTree = {
"ComputeResource",
"ClusterComputeResource"
};
private static String[] hcTree = {
"HistoryCollector",
"EventHistoryCollector",
"TaskHistoryCollector"
};
public VMwareClient() {
}
// Bug: 579 - This method is added so that we can connect to the vCenter without any TLS policy settings and connection pooling options.
// This would be needed by the Management Console to retrive the list of hosts from the cluster.
protected void connect2(URL url, String userName, String password) throws KeyManagementException, NoSuchAlgorithmException, IOException {
log.debug("VMwareClient: connect2 | setting TlsPolicy...");
setTlsPolicy(new InsecureTlsPolicy());
log.debug("VMwareClient: calling connect...");
connect(url.toExternalForm(), userName, password);
}
/*
public void setSslHostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}
public void setSslCertificateTrustManager(X509TrustManager trustManager) {
this.trustManager = trustManager;
}
*/
/**
* Disconnects the user session.
*
* @throws Exception
*/
public void disconnect() {
try {
if (isConnected()) {
isConnected = false;
servInst.getServerConnection().logout();
}
} catch (Exception e) {
log.error("Error while logging out from VCenter Api.", e);
}
}
/**
* Establishes session with the virtual center server.
*
* @throws RuntimeFaultFaultMsg
* @throws InvalidLoginFaultMsg
* @throws InvalidLocaleFaultMsg
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*
* @throws Exception the exception
*/
public void connect(String url, String userName, String password) throws KeyManagementException, NoSuchAlgorithmException, IOException {
vcenterEndpoint = url;
vmwareConnectionString = url + ";" + userName + ";" + password;
/*
if( hostnameVerifier == null ) {
log.warn("SSL Hostname Verifier not set; will accept any remote hostname");
HttpsURLConnection.setDefaultHostnameVerifier(new NopX509HostnameVerifier());
}
else {
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
}*/
log.debug("Connecting to vcenter with URL: {}", url);
log.debug("Connecting to vcenter with TlsPolicy: {}", tlsPolicy.getClass().getName());
log.debug("Connecting to vcenter with HostnameVerifier: {}", tlsPolicy.getHostnameVerifier().getClass().getName());
log.debug("Connecting to vcenter with TrustManager: {}", tlsPolicy.getTrustManager().getClass().getName());
log.debug("Connecting to vcenter with ProtocolSelector: {}", tlsPolicy.getProtocolSelector().preferred());
// TlsConnection tlsConnection = new TlsConnection(new URL(url), tlsPolicy);
// javax.net.ssl.SSLContext sc = tlsConnection.getSSLContext();
// javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance(tlsPolicy.getProtocolSelector().preferred()); // issue #871 ssl protocol should be configurable; was hardcoded to "SSL"
// javax.net.ssl.SSLSessionContext sslsc = sc.getServerSessionContext();
// sslsc.setSessionTimeout(0);
// sc.init(null, new javax.net.ssl.TrustManager[]{tlsPolicy.getTrustManager()}, null);
// HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// HttpsURLConnection.setDefaultHostnameVerifier(TlsPolicyManager.getInstance().getHostnameVerifier());
// HttpsURLConnection.setDefaultSSLSocketFactory(new TlsPolicyAwareSSLSocketFactory());
// HttpsURLConnection.setDefaultHostnameVerifier(TlsPolicyManager.getInstance().getHostnameVerifier());
TlsConnection tlsConnection = new TlsConnection(new URL(url), tlsPolicy);
TlsUtil.setHttpsURLConnectionDefaults(tlsConnection);
SVC_INST_REF.setType(SVC_INST_NAME);
SVC_INST_REF.setVal(SVC_INST_NAME);
try {
log.debug("VSPHERE: login to vcenter with username: {} {}", userName, password == null || password.isEmpty() ? "without password" : "with password");
servInst = new ServiceInstance(new URL(url), userName, password, false);
log.debug("VSPHERE: ServiceInstance created.");
vimPort = servInst.getServerConnection().getVimService();
log.debug("VSPHERE: vimPort created.");
serviceContent = servInst.getServiceContent();
log.debug("VSPHERE: serviceContent created.");
rootFolder = servInst.getRootFolder();
log.debug("VSPHERE: rootFolder retrieved.");
session = servInst.getServerConnection().getUserSession(); //vimPort.login(serviceContent.getSessionManager(), userName, password, null);
log.debug("VSPHERE: login complete.");
} catch (Exception e) {
throw new IOException("Cannot login to vcenter: " + e.toString(), e);
}
// Map<String, Object> ctxt = ((BindingProvider)vimPort).getRequestContext();
// ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
// ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);
printSessionDetails();
isConnected = true;
propCollectorRef = serviceContent.getPropertyCollector();
rootRef = serviceContent.getRootFolder();
}
private void printSessionDetails() {
if (session != null) {
log.debug("Logged in Session key " + session.getKey());
} else {
log.info("session is null");
}
}
public boolean isConnected() {
if (!isConnected) {
return false;
}
try {
return vimPort.sessionIsActive(serviceContent.getSessionManager(), session.getKey(), session.getUserName());
} catch (Exception e) {
log.warn("session not active: {}", e.toString());
return false;
} catch (Error e) {
log.warn("session not active: {}", e.toString());
return false;
}
}
public String getEndpoint() {
return vcenterEndpoint;
}
public void connect(String vCenterConnectionString) throws KeyManagementException, NoSuchAlgorithmException, MalformedURLException, IOException {
//ConnectionString cs = ConnectionString.forVmware(new URL(vCenterConnectionString));
/*
String[] vcenterConn = vCenterConnectionString.split(";");
if (vcenterConn.length != 3) {
throw new ASException(ErrorCode.AS_VMWARE_INVALID_CONNECT_STRING,
vCenterConnectionString);
}
// Connect to the vCenter server with the passed in parameters
connect(vcenterConn[0], vcenterConn[1], vcenterConn[2]);
*/
// log.debug("VSPHERE: Connection string: {}", vCenterConnectionString);
ConnectionString.VmwareConnectionString vmware = ConnectionString.VmwareConnectionString.forURL(vCenterConnectionString);
log.debug("VSPHERE: Connecting to vcenter: {} for host: {}", vmware.getVCenter().toString(), vmware.getHost().toString());
connect(vmware.toURL().toExternalForm(), vmware.getUsername(), vmware.getPassword());
}
public static byte[] toByteArray(List<Byte> list) {
byte[] ret = new byte[list.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = list.get(i);
}
return ret;
}
/**
* Issue #784 performance This method returns just the requested host, in
* contrast to getEntitiesByType which returns all the hosts and then we
* have to query each one to see if it's the one we want
*/
public ManagedObjectReference getHostReference(String hostname) throws RemoteException {
//ManagedObjectReference searchIndex;
//vimPort.findByDnsName and vimPort.findByIp .... first parameter is the searchindex mor, second is datacenter (optional, can be null), , third is the dnsname/ip, fourth is true for vm or false for host.
// page 20: obtain manageed obejct reference by accessor method, for searchindex
// ServiceContent sc = vimPort.retrieveServiceContent(hostRef)
ManagedObjectReference searchIndex = serviceContent.getSearchIndex();
ManagedObjectReference hostRef = vimPort.findByDnsName(searchIndex, null, hostname, false);
if (hostRef == null) {
hostRef = vimPort.findByIp(searchIndex, null, hostname, false);
}
return hostRef;
}
// / <summary>
// / Based on the Entity type this function searches through all the objects
// and returns
// / the matching objects.
// / For getting just clusters call it with "ClusterComputeResource"
// / For getting just Datacenters call it with "Datacenter"
// / For getting just hosts call it with "ComputeResource"
// / </summary>
// / <param name="entityType">Type of the Entity that should be returned
// back</param>
// / <returns>Array of Management Oject References to all the objects of the
// type specified.</returns>
protected ManagedEntity[] getEntitiesByType(String entityType) throws InvalidProperty, RuntimeFault, RemoteException {
return new InventoryNavigator(rootFolder).searchManagedEntities(entityType);
}
protected String getHostInfo(ManagedObjectReference hostObj) throws InvalidProperty, RuntimeFault, RemoteException {
ManagedEntity me = new InventoryNavigator(rootFolder).searchManagedEntity(hostObj.type, hostObj.val);
return me.getName();
}
protected String getHostInfo(ManagedEntity hostObj) throws InvalidProperty, RuntimeFault, RemoteException {
return hostObj.getName();
}
public String getStringMEProperty(String meType, String meName, String propertyName) throws InvalidProperty, RuntimeFault, RemoteException {
Object value = getMEProperty(meType, meName, propertyName);
if( value == null ) { return null; }
return value.toString();
}
public Object getMEProperty(String meType, String meName, String propertyName)
throws InvalidProperty, RuntimeFault, RemoteException {
return getMEProperties(meType, meName, new String[]{propertyName}).get(propertyName);
}
protected Hashtable getMEProperties(String meType, String meName, String[] properties)
throws InvalidProperty, RuntimeFault, RemoteException {
log.debug("VSPHERE: meType: " + meType);
log.debug("VSPHERE: meName: " + meName);
for (String s : properties) {
log.debug("VSPHERE: properties: " + s);
}
ManagedEntity me = new InventoryNavigator(rootFolder).searchManagedEntity(meType, meName);
log.debug("VSPHERE: ManagedEntity: " + me.toString());
Hashtable ht = me.getPropertiesByPaths(properties);
log.debug("VSPHERE: Hashtable: " + ht.toString());
return ht;
}
public List<String> getPropertyNames(TxtHostRecord hostObj) throws InvalidProperty, RuntimeFault, RemoteException, VMwareConnectionException {
// Return object array
ArrayList<String> list = new ArrayList<>();
ManagedObjectReference moRef = getDecendentMoRef(null, "HostSystem", hostObj.HostName);
if(moRef == null ) { throw new IllegalArgumentException("Cannot get reference to specified host"); }
// PropertySpec specifiesgetHostAttestationReport what properties to
// retrieve and from type of Managed Object
PropertySpec pSpec = new PropertySpec();
pSpec.setType(moRef.getType());
//pSpec.getPathSet().addAll(new ArrayList<String>());
for (String s : new ArrayList<String>()) {
pSpec.getPathSet()[pSpec.getPathSet().length] = s;
}
// ObjectSpec specifies the starting object and
// any TraversalSpecs used to specify other objects
// for consideration
ObjectSpec oSpec = new ObjectSpec();
oSpec.setObj(moRef);
// PropertyFilterSpec is used to hold the ObjectSpec and
// PropertySpec for the call
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.getPropSet()[0] = pSpec;
pfSpec.getObjectSet()[0] = oSpec;
// retrieveProperties() returns the properties
// selected from the PropertyFilterSpec
List<PropertyFilterSpec> pfSpecs = new ArrayList<PropertyFilterSpec>();
pfSpecs.add(pfSpec);
ObjectContent[] ocs = vimPort.retrieveProperties(propCollectorRef, (PropertyFilterSpec[])pfSpecs.toArray());
for (ObjectContent oc : ocs) {
DynamicProperty[] dps = oc.getPropSet();
for (DynamicProperty dp : dps) {
list.add(dp.getName()); // and dp.getVal()
}
}
return list;
}
public String getVCenterVersion() {
return serviceContent.getAbout().getVersion();
}
public HostTpmAttestationReport getAttestationReport(
ManagedObjectReference hostObj) throws RuntimeFault, RemoteException {
return vimPort.queryTpmAttestationReport(hostObj);
}
/**
* performance of this method is very bad, it has been observed at 1 second
* per iteration of the comparison loop. see getHostReference for obtaining
* a managed object reference for a specific host (instead of for all hosts
* and then querying each one for the name)
*/
public ManagedEntity getManagedObjectReference(String hostName) throws InvalidProperty, RuntimeFault, RemoteException {
// Get the host objects in the vcenter
ManagedEntity[] hostObjects = getEntitiesByType("HostSystem");
if (hostObjects != null && hostObjects.length != 0) {
for (ManagedEntity hostObj : hostObjects) {
String hostNameFromVC = getHostInfo(hostObj);
log.debug("getHostObject - comparing hostNameFromVC {} requested hostName {}", new Object[]{hostNameFromVC, hostName});
if (hostNameFromVC.equals(hostName)) {
log.debug(String.format("Found Managed Object Reference for host %s ", hostName));
return hostObj;
}
}
}
// If the code reaches here that means that we did not find the host
throw new ASException(ErrorCode.AS_HOST_NOT_FOUND_IN_VCENTER, hostName);
}
@Override
public void setTlsPolicy(TlsPolicy tlsPolicy) {
this.tlsPolicy = tlsPolicy;
}
/*
private class TrustAllTrustManager implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
for (java.security.cert.X509Certificate cert : certs) {
cert.checkValidity();
}
return;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
for (java.security.cert.X509Certificate cert : certs) {
cert.checkValidity();
}
return;
}
} */
public String byteArrayToBase64String(List<Byte> digestValue) {
String digest = Base64.encodeBase64String(toByteArray(digestValue));
return digest;
}
public static String byteArrayToHexString(List<Byte> digestValue) {
return byteArrayToHexString(toByteArray(digestValue));
}
public static String byteArrayToHexString(byte[] bytes) {
BigInteger bi = new BigInteger(1, bytes);
return String.format("%0" + (bytes.length << 1) + "X", bi);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
/**
* Added By: Sudhir on June 15, 2012
*
* Retrieves the list of Virtual machines for the specified host along with
* the power state of the VM.
*
* @param hostName : Name of the host for which the VM details need to be
* retrieved.
* @param vCenterConnectionString : Connection string of the vCenter on
* which the host is configured
* @return : ArrayList consisting of all the VM along with the power state
* information. VM Name::POWERED_ON
* @throws Exception
*/
// public ArrayList getVMsForHost(String hostName, String vCenterConnectionString) throws VMwareConnectionException {
// ArrayList vmList;
// ManagedObjectReference hostMOR = null;
// try {
// connect(vCenterConnectionString);
//
// if (hostName != null) {
// hostMOR = getDecendentMoRef(null, "HostSystem", hostName);
// if (hostMOR == null) {
// throw new Exception("Host configuration not found in the vCenter database.");
// }
// }
//
// vmList = getDecendentMoRefs(hostMOR, "VirtualMachine", null);
// if (vmList.isEmpty()) {
// return vmList;
// }
//
// for (int i = 0; i < vmList.size(); i++) {
// String vmName = getMORProperty((ManagedObjectReference) vmList.get(i), "name").toString();
// String vmPowerState = getMORProperty((ManagedObjectReference) vmList.get(i), "runtime.powerState").toString();
// vmList.set(i, vmName + "::" + vmPowerState);
// }
// } catch (Exception ex) {
// throw new VMwareConnectionException(ex);
// } finally {
// disconnect();
// }
// return vmList;
// }
/**
* Added By: Sudhir on June 15, 2012
*
* Retrieves the h/w & s/w details of the host including BIOS, OS
* information
*
* @param hostName : Name of the host for which the details need to be
* retrieved
* @param vCenterConnectionString : Connection string to the vCenter server
* where the host is configured.
*
* NOTE: this method modifies the input object and then returns the same
* object; it does NOT return a new object or a copy
*
* @deprecated use VmwareHostAgent.getHostDetails()
*
*
* @return : Host object containing all the details.
* @throws Exception
*/
public TxtHostRecord getHostDetails(TxtHostRecord hostObj) throws VMwareConnectionException {
ManagedObjectReference hostMOR;
boolean doNotDisconnect = false;
try {
// If we have already established a connection, we use it. This will
// happen when this function will be called by the getHostDetailsForCluster
// function, which would have opened the connection to vCenter server.
if (!isConnected) {
connect(hostObj.AddOn_Connection_String);
} else {
doNotDisconnect = true;
}
hostMOR = getDecendentMoRef(null, "HostSystem", hostObj.HostName);
if (hostMOR == null) {
throw new Exception("Host specified does not exist in the vCenter.");
}
hostObj.HostName = getStringMEProperty("HostSystem", hostObj.HostName, "name");
// hostObj.Description = serviceContent.getAbout().getVersion();
hostObj.VMM_OSName = getStringMEProperty("HostSystem", hostObj.HostName, "config.product.name");
hostObj.VMM_OSVersion = getStringMEProperty("HostSystem", hostObj.HostName, "config.product.version");
hostObj.VMM_Version = getStringMEProperty("HostSystem", hostObj.HostName, "config.product.build");
hostObj.BIOS_Oem = getStringMEProperty("HostSystem", hostObj.HostName, "hardware.systemInfo.vendor");
hostObj.BIOS_Version = getStringMEProperty("HostSystem", hostObj.HostName, "hardware.biosInfo.biosVersion");
} catch (Exception ex) {
throw new VMwareConnectionException(ex);
} finally {
if (!doNotDisconnect) {
disconnect();
}
}
return hostObj;
}
/**
* Added By: Sudhir on June 15, 2012
*
* Retrieves the list of hosts along with the s/w and h/w configuration
* details within the VMware Cluster.
*
* @param clusterName : Name of the cluster from which we need to retrieve
* the host details
* @param vCenterConnectionString : Connection string to the vCenter server
* @return : Array list of all the host names
* @throws Exception
*/
public ArrayList getHostDetailsForCluster(String clusterName, String vCenterConnectionString) throws VMwareConnectionException, ASException {
ArrayList hostList;
ArrayList hostDetailList = new ArrayList<TxtHostRecord>();
ManagedObjectReference clusterMOR = null;
ConnectionString.VmwareConnectionString vmwareURL;
try {
vmwareURL = ConnectionString.VmwareConnectionString.forURL(vCenterConnectionString);
} catch (Exception e) {
throw new ASException(ErrorCode.AS_VMWARE_INVALID_CONNECT_STRING, vCenterConnectionString);
}
try {
// Connect to the vCenter server with the passed in parameters, but insecure tls policy since we don't know this host yet
connect2(vmwareURL.toURL(), vmwareURL.getUsername(), vmwareURL.getPassword());
if (clusterName != null) {
clusterMOR = getDecendentMoRef(null, "ClusterComputeResource", clusterName);
if (clusterMOR == null) {
throw new Exception("Cluster configuration not found in the vCenter database.");
}
}
hostList = getDecendentMoRefs(clusterMOR, "HostSystem", null);
if (hostList.isEmpty()) {
return hostList;
}
for (int i = 0; i < hostList.size(); i++) {
log.debug("VSPHERE: Host " + i + " = " + hostList.get(i).toString());
String hostName = getStringMEProperty("HostSystem", hostList.get(i).toString(), "name");
TxtHostRecord hostObj = new TxtHostRecord();
hostObj.HostName = hostName;
hostObj.AddOn_Connection_String = vCenterConnectionString;
hostObj = getHostDetails(hostObj);
hostDetailList.add(hostObj);
}
} catch (Exception ex) {
throw new VMwareConnectionException(ex);
} finally {
disconnect();
}
return hostDetailList;
}
/**
* Added By: Savino on June 28, 2013
*
* Retrieves the list of datacenters from the vcenter to populate dropdown
* on webform.
*
* @param vCenterConnectionString : Connection string to the vCenter server
* @return : string list of datacenter names
* @throws Exception
*/
public List<String> getDatacenterNames() throws InvalidProperty, RuntimeFault, RemoteException {
List<String> ret = new ArrayList<>();
log.debug("Acquiring datacenters...");
ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("Datacenter");
for (ManagedEntity me : mes) {
log.debug("Datacenter found: " + me.getName());
ret.add(me.getName());
}
return ret;
}
/**
* Added By: Savino on June 28, 2013
*
* Retrieves the list of clusters from the vcenter to populate dropdown on
* webform.
*
* @param vCenterConnectionString : Connection string to the vCenter server
* @param datacenterName : Specify the datacenter that contains the desired
* clusters
* @return : string list of cluster names
* @throws Exception
*/
public List<String> getClusterNamesWithDC() throws InvalidProperty, RuntimeFault, RemoteException {
List<String> ret = new ArrayList<String>();
log.debug("Acquiring clusters...");
ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("ComputeResource");
for (ManagedEntity me : mes) {
log.debug("Cluster found: " + "[" + me.getParent().getParent().getName() + "] " + me.getName());
ret.add("[" + me.getParent().getParent().getName() + "] " + me.getName());
}
return ret;
}
public ArrayList getHostNamesForCluster(String clusterName) throws InvalidProperty, RuntimeFault, RemoteException {
ArrayList<TxtHostRecord> hostDetailList = new ArrayList<>();
log.debug("Acquiring host systems...");
ManagedEntity[] mes = new InventoryNavigator(rootFolder).searchManagedEntities("HostSystem");
for (ManagedEntity me : mes) {
if (me.getParent().getName().trim().equalsIgnoreCase(clusterName.trim())) {
log.debug("Host System found for cluster " + clusterName + ": " + me.getName());
String connectionState = getMEProperty("HostSystem", me.getName(), "runtime.connectionState").toString().trim();
if (connectionState.equalsIgnoreCase("connected")) {
log.debug("Adding host {} to the list of connected servers.", me.getName());
TxtHostRecord hostObj = new TxtHostRecord();
hostObj.HostName = me.getName();
hostObj.AddOn_Connection_String = vmwareConnectionString;
hostObj.VMM_OSName = getMEProperty("HostSystem", hostObj.HostName, "config.product.name").toString();
hostObj.VMM_OSVersion = getMEProperty("HostSystem", hostObj.HostName, "config.product.version").toString();
hostObj.VMM_Version = getMEProperty("HostSystem", hostObj.HostName, "config.product.build").toString();
hostObj.BIOS_Oem = getMEProperty("HostSystem", hostObj.HostName, "hardware.systemInfo.vendor").toString();
hostObj.BIOS_Version = getMEProperty("HostSystem", hostObj.HostName, "hardware.biosInfo.biosVersion").toString();
hostDetailList.add(hostObj);
} else {
log.info("Host {} is not currently connected to the vCenter. So, it would not be used for registration.", me.getName());
}
}
else {
log.debug(me.getName() + ": parent \"" + me.getParent().getName() + "\" does not match cluster name \"" + clusterName + "\"");
}
}
return hostDetailList;
}
/**
* Added By: Sudhir on June 14, 2012
*
* This function provides the power on and power off functionality virtual
* machines
*
* @param vmName : Name of the VM
* @param hostName: Name of the host on which VM should be powered on. For
* Power Off, this parameter is not needed.
* @param powerOn: Flag that indicates whether to power on or off the VM
* @param vCenterConnectionString : Connection string to the vCenter server.
* @throws Exception
*/
public void powerOnOffVM(String vmName, String hostName, Boolean powerOn, String vCenterConnectionString) throws VMwareConnectionException {
ManagedObjectReference hostMOR;
ManagedObjectReference vmMOR;
ManagedObjectReference powerTaskMOR;
try {
connect(vCenterConnectionString);
vmMOR = getDecendentMoRef(null, "VirtualMachine", vmName);
if (vmMOR == null) {
throw new Exception("Invalid virtual machine specified for the power operation.");
}
if (powerOn) {
hostMOR = getDecendentMoRef(null, "HostSystem", hostName);
if (hostMOR == null) {
throw new VMwareConnectionException("Invalid host specified for the virtual machine power on operation.");
}
powerTaskMOR = vimPort.powerOnVM_Task(vmMOR, hostMOR);
} else {
powerTaskMOR = vimPort.powerOffVM_Task(vmMOR);
}
// Wait for the power operation to complete and return back
String result = waitForTask(powerTaskMOR);
if (!result.toLowerCase().contentEquals("success")) {
if (result.contains(".") || result.contains("\n")) {
String delims = "[.\\n]+";
result = result.split(delims)[0];
}
throw new Exception("Error during the VM power operation." + result);
}
} catch (Exception ex) {
throw new VMwareConnectionException(ex);
} finally {
disconnect();
}
}
/**
* Added By: Sudhir on June 14, 2012
*
* Migrates the VM to the specified destination
*
* @param vmName : VM that needs to be migrated
* @param destHostName : Target host on which the VM has to be migrated
* @param vCenterConnectionString : Connection string to the vCenter server
* @throws Exception
*/
public void migrateVM(String vmName, String destHostName, String vCenterConnectionString) throws VMwareConnectionException {
ManagedObjectReference hostMOR;
ManagedObjectReference vmMOR;
ManagedObjectReference migrateTaskMOR;
try {
connect(vCenterConnectionString);
hostMOR = getDecendentMoRef(null, "HostSystem", destHostName);
vmMOR = getDecendentMoRef(null, "VirtualMachine", vmName);
if (vmMOR == null || hostMOR == null) {
throw new Exception("Invalid virtual machine or host specified for the VM migration.");
}
String vmPowerState = getStringMEProperty("VirtualMachine", vmName, "runtime.powerState");
if (vmPowerState != null && vmPowerState.equalsIgnoreCase("powered_on")) {
migrateTaskMOR = vimPort.migrateVM_Task(vmMOR, null, hostMOR,
VirtualMachineMovePriority.highPriority, VirtualMachinePowerState.poweredOn);
} else {
migrateTaskMOR = vimPort.migrateVM_Task(vmMOR, null, hostMOR,
VirtualMachineMovePriority.highPriority, VirtualMachinePowerState.poweredOff);
}
// Wait for the power operation to complete and return back
String result = waitForTask(migrateTaskMOR);
if (!result.equalsIgnoreCase("success")) {
if (result.contains(".") || result.contains("\n")) {
String delims = "[.\\n]+";
result = result.split(delims)[0];
}
throw new Exception("Error during the VM migration." + result);
}
} catch (Exception ex) {
throw new VMwareConnectionException(ex);
} finally {
disconnect();
}
}
/**
* Added By: Sudhir on June 15, 2012
*
* Retrieves the BIOS PCR 0 value from the attestation reports for the
* specified host
*
* @param hostMOR: ManagedObjectReference for the host
* @return : String containing the BIOS PCR 0 value.
* @throws Exception
*/
/*public String getHostBIOSPCRHash(ManagedObjectReference hostMOR, String hostName) throws VMwareConnectionException {
String biosPCRHash = "";
HostTpmDigestInfo[] pcrList;
try {
boolean tpmSupport = Boolean.parseBoolean(getMEProperty(hostMOR.type, hostName, "capability.tpmSupported").toString());
if (tpmSupport == true && serviceContent.getAbout().getVersion().contains("5.1")) {
HostTpmAttestationReport hostTrustReport = vimPort.queryTpmAttestationReport(hostMOR);
if (hostTrustReport != null) {
pcrList = hostTrustReport.getTpmPcrValues();
for (int k = 0; k < pcrList.length; k++) {
HostTpmDigestInfo pcrInfo = (HostTpmDigestInfo) pcrList[k];
switch (pcrInfo.getPcrNumber()) {
case 0:
biosPCRHash = byteArrayToHexString(pcrInfo.getDigestValue());
break;
default:
break;
}
}
}
} else if (tpmSupport == true && serviceContent.getAbout().getVersion().contains("5.0")) {
// Refresh the runtime information
HostRuntimeInfo runtimeInfo = (HostRuntimeInfo) getMEProperty(hostMOR.type, hostName, "runtime");
// Now process the digest information
pcrList = runtimeInfo.getTpmPcrValues();
for (int k = 0; k < pcrList.length; k++) {
HostTpmDigestInfo pcrInfo = (HostTpmDigestInfo) pcrList[k];
switch (pcrInfo.getPcrNumber()) {
case 0:
biosPCRHash = byteArrayToHexString(pcrInfo.getDigestValue());
break;
default:
break;
}
}
} else {
// Since the host does not support TPM, we will not have these values.
biosPCRHash = "";
}
} catch (Exception ex) {
throw new VMwareConnectionException(ex);
}
return biosPCRHash;
}*/
/**
* @deprecated just an adapter for now ; VmwareHostAgent uses
* getHostAttestationReport(MOR,HostName,PcrList)
* @param hostObj
* @param pcrList
* @return
* @throws VMwareConnectionException
*/
public String getHostAttestationReport(TxtHostRecord hostObj, String pcrList) throws VMwareConnectionException {
ManagedObjectReference hostMOR = getDecendentMoRef(null, "HostSystem", hostObj.HostName);
if (hostMOR == null) {
throw new VMwareConnectionException("Host specified does not exist in the vCenter.");
}
return getHostAttestationReport(hostMOR, hostObj.HostName, pcrList);
}
public boolean isModuleAttestationSupportedByVcenter(String vCenterVersion) {
double version = Double.parseDouble(vCenterVersion.substring(0, vCenterVersion.lastIndexOf(".")));
return (version >= MIN_VCENTER_VERSION_FOR_MODULE_ATTESTATION);
}
public boolean isModuleAttestationSupportedByESX(String esxVersion) {
double version = Double.parseDouble(esxVersion.substring(0, esxVersion.lastIndexOf(".")));
return (version >= MIN_VCENTER_VERSION_FOR_MODULE_ATTESTATION);
}
/**
* Added By: Sudhir on June 18, 2012
*
* Retrieves the attestation report as a XML string
*
* @param hostName : Name of the host for which the attestation report has
* to be retrieved
* @param pcrList : Required PCR list separated by comma
* @param vCenterConnectionString : Connection string to the vCenter server
* on which the host is configured
* @return : XML string equivalent of the attestation report.
* @throws Exception
*/
public String getHostAttestationReport(ManagedObjectReference hostMOR, String hostName, String pcrList) throws VMwareConnectionException {
log.debug("getHostAttestationReport >> START");
// boolean doNotDisconnect;
XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter xtw;
StringWriter sw = new StringWriter();
try {
// Verify if the PCRList is sent. If not set the default values.
if (pcrList == null || pcrList.isEmpty()) {
pcrList = "0,17,18,20";
}
// If we have already established a connection, we use it. This will
// happen when this function will be called by the getHostDetailsForCluster
// function, which would have opened the connection to vCenter server.
/*
if (!isConnected)
connect(hostObj.AddOn_Connection_String);
else
doNotDisconnect = true;
*/
Boolean tpmSupport = Boolean.parseBoolean(getStringMEProperty(hostMOR.type, hostName, "capability.tpmSupported"));
// Lets create the start of the XML document
// xtw = xof.createXMLStreamWriter(new FileWriter("c:\\temp\\nb_xml.xml"));
xtw = xof.createXMLStreamWriter(sw);
xtw.writeStartDocument();
xtw.writeStartElement("Host_Attestation_Report");
xtw.writeAttribute("Host_Name", hostName);
xtw.writeAttribute("vCenterVersion", serviceContent.getAbout().getVersion());
String hostVer = getStringMEProperty(hostMOR.type, hostName, "config.product.version");
xtw.writeAttribute("HostVersion", hostVer);
xtw.writeAttribute("TXT_Support", tpmSupport.toString());
// if (tpmSupport == true && serviceContent.getAbout().getVersion().contains("5.1")) {
if (tpmSupport == true && (isModuleAttestationSupportedByVcenter(getVCenterVersion()))) {
log.debug("Querying TPM attestation report...");
HostTpmAttestationReport hostTrustReport = vimPort.queryTpmAttestationReport(hostMOR);
log.debug("Query finished.");
// Process the event log only for the ESXi 5.1 or higher
// if (hostTrustReport != null && hostVer.contains("5.1")) {
if (hostTrustReport != null && hostVer != null && (isModuleAttestationSupportedByESX(hostVer))) {
log.debug("Retrieving TPM events...");
int numOfEvents = hostTrustReport.getTpmEvents().length;
for (int k = 0; k < numOfEvents; k++) {
log.debug("");
HostTpmEventLogEntry eventInfo = (HostTpmEventLogEntry) hostTrustReport.getTpmEvents()[k];
switch (eventInfo.getPcrIndex()) {
// We will process only the components that gets extended into PCR 19. We
// will ignore the rest of the event entries.
case 0:
break;
case 17:
break;
case 18:
break;
case 20:
break;
// All the static components hash values are in this index. So, we will process
// all the entries and store them into the database.
case 19:
log.debug("PCR 19: writing attributes...");
String eventName = eventInfo.getEventDetails().getClass().getSimpleName();
if (eventName.equalsIgnoreCase("HostTpmSoftwareComponentEventDetails")) {
HostTpmSoftwareComponentEventDetails swEventLog = (HostTpmSoftwareComponentEventDetails) eventInfo.getEventDetails();
xtw.writeStartElement("EventDetails");
xtw.writeAttribute("EventName", "Vim25Api.HostTpmSoftwareComponentEventDetails");
//xtw.writeAttribute("ComponentName", swEventLog.getComponentName());
// Bug Fix #491 set componentName == to packageName - packageVersion
// instead of componentName
// Bug: 931: To uniquely identify the component name we need to use a combination of the component name without the autogenerated version,
// VIB name and VIB version. First let us trim the component name to remove the autogenerated version.
String compName = swEventLog.getComponentName().substring(0, swEventLog.getComponentName().lastIndexOf("."));
xtw.writeAttribute("ComponentName", compName+ "-" + swEventLog.getVibName()+ "-" +swEventLog.getVibVersion());
xtw.writeAttribute("DigestValue", byteArrayToHexString(swEventLog.getDataHash()));
xtw.writeAttribute("ExtendedToPCR", String.valueOf(eventInfo.getPcrIndex()));
xtw.writeAttribute("PackageName", swEventLog.getVibName());
xtw.writeAttribute("PackageVendor", swEventLog.getVibVendor());
xtw.writeAttribute("PackageVersion", swEventLog.getVibVersion());
xtw.writeAttribute("UseHostSpecificDigest", "False");
xtw.writeEndElement();
} else if (eventName.equalsIgnoreCase("HostTpmOptionEventDetails")) {
HostTpmOptionEventDetails optEventLog = (HostTpmOptionEventDetails) eventInfo.getEventDetails();
xtw.writeStartElement("EventDetails");
xtw.writeAttribute("EventName", "Vim25Api.HostTpmOptionEventDetails");
xtw.writeAttribute("ComponentName", optEventLog.getOptionsFileName());
xtw.writeAttribute("DigestValue", byteArrayToHexString(optEventLog.getDataHash()));
xtw.writeAttribute("ExtendedToPCR", String.valueOf(eventInfo.getPcrIndex()));
xtw.writeAttribute("PackageName", "");
xtw.writeAttribute("PackageVendor", "");
xtw.writeAttribute("PackageVersion", "");
xtw.writeAttribute("UseHostSpecificDigest", "False");
xtw.writeEndElement();
} else if (eventName.equalsIgnoreCase("HostTpmBootSecurityOptionEventDetails")) {
HostTpmBootSecurityOptionEventDetails bootEventLog = (HostTpmBootSecurityOptionEventDetails) eventInfo.getEventDetails();
xtw.writeStartElement("EventDetails");
xtw.writeAttribute("EventName", "Vim25Api.HostTpmBootSecurityOptionEventDetails");
xtw.writeAttribute("ComponentName", bootEventLog.getBootSecurityOption());
xtw.writeAttribute("DigestValue", byteArrayToHexString(bootEventLog.getDataHash()));
xtw.writeAttribute("ExtendedToPCR", String.valueOf(eventInfo.getPcrIndex()));
xtw.writeAttribute("PackageName", "");
xtw.writeAttribute("PackageVendor", "");
xtw.writeAttribute("PackageVersion", "");
xtw.writeAttribute("UseHostSpecificDigest", "False");
xtw.writeEndElement();
} else if (eventName.equalsIgnoreCase("HostTpmCommandEventDetails")) {
HostTpmCommandEventDetails cmdEventLog = (HostTpmCommandEventDetails) eventInfo.getEventDetails();
xtw.writeStartElement("EventDetails");
xtw.writeAttribute("EventName", "Vim25Api.HostTpmCommandEventDetails");
// We should not store the actual command line data here since it is host specific.
xtw.writeAttribute("ComponentName", ""); //cmdEventLog.commandLine);
xtw.writeAttribute("DigestValue", byteArrayToHexString(cmdEventLog.getDataHash()));
xtw.writeAttribute("ExtendedToPCR", String.valueOf(eventInfo.getPcrIndex()));
xtw.writeAttribute("PackageName", "");
xtw.writeAttribute("PackageVendor", "");
xtw.writeAttribute("PackageVersion", "");
xtw.writeAttribute("UseHostSpecificDigest", "True");
xtw.writeAttribute("HostName", hostName);
xtw.writeEndElement();
}
break;
default:
break;
}
}
}
// The TPM values have to be captured for both ESXi 5.0 or 5.1 hosts
if (hostTrustReport != null) {
log.debug("Getting TPM PCR values...");
List<String> pcrs = Arrays.asList(pcrList.split(","));
int numTPMValues = hostTrustReport.getTpmPcrValues().length;
for (int j = 0; j < numTPMValues; j++) {
HostTpmDigestInfo pcrInfo = hostTrustReport.getTpmPcrValues()[j];
if (pcrs.contains(String.valueOf(pcrInfo.getPcrNumber()))) {
xtw.writeStartElement("PCRInfo");
xtw.writeAttribute("ComponentName", String.valueOf(pcrInfo.getPcrNumber()));
xtw.writeAttribute("DigestValue", byteArrayToHexString(pcrInfo.getDigestValue()));
xtw.writeEndElement();
}
}
}
} else if (tpmSupport == true && serviceContent.getAbout().getVersion().contains("5.0")) {
// Refresh the runtime information
HostRuntimeInfo runtimeInfo = (HostRuntimeInfo) getMEProperty(hostMOR.type, hostName, "runtime");
if( runtimeInfo != null ) {
// Now process the digest information
List<String> pcrs = Arrays.asList(pcrList.split(","));
int numTPMValues = runtimeInfo.getTpmPcrValues().length;
for (int j = 0; j < numTPMValues; j++) {
HostTpmDigestInfo pcrInfo = runtimeInfo.getTpmPcrValues()[j];
if (pcrs.contains(String.valueOf(pcrInfo.getPcrNumber()))) {
xtw.writeStartElement("PCRInfo");
xtw.writeAttribute("ComponentName", String.valueOf(pcrInfo.getPcrNumber()));
xtw.writeAttribute("DigestValue", byteArrayToHexString(pcrInfo.getDigestValue()));
xtw.writeEndElement();
}
}
}
} else {
xtw.writeStartElement("PCRInfo");
xtw.writeAttribute("Error", "Host does not support TPM.");
xtw.writeEndElement();
}
xtw.writeEndElement();
xtw.writeEndDocument();
xtw.flush();
xtw.close();
String attestationReport = sw.toString();
return attestationReport;
} catch (RemoteException | XMLStreamException ex) {
throw new VMwareConnectionException(ex);
} finally {/*
if (!doNotDisconnect)
disconnect();*/
log.debug("getHostAttestationReport >> FINISH");
}
}
// <editor-fold defaultstate="collapsed" desc="Code copied from VMware SDK's VMPowerOps.Java file.">
/**
* Uses the new RetrievePropertiesEx method to emulate the now deprecated
* RetrieveProperties method
*
* @param listpfs
* @return list of object content
* @throws Exception
*/
private List<ObjectContent> retrievePropertiesAllObjects(List<PropertyFilterSpec> listpfs)
throws VMwareConnectionException {
RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();
List<ObjectContent> listobjcontent = new ArrayList<>();
try {
RetrieveResult rslts = vimPort.retrievePropertiesEx(propCollectorRef, (PropertyFilterSpec[])listpfs.toArray(), propObjectRetrieveOpts);
if (rslts != null && rslts.getObjects() != null && rslts.getObjects().length != 0) {
listobjcontent = Arrays.asList(rslts.objects);
}
String token = null;
if (rslts != null && rslts.getToken() != null) {
token = rslts.getToken();
}
while (token != null && !token.isEmpty()) {
rslts = vimPort.continueRetrievePropertiesEx(propCollectorRef, token);
token = null;
if (rslts != null) {
token = rslts.getToken();
if (rslts.getObjects() != null && rslts.getObjects().length != 0) {
listobjcontent = Arrays.asList(rslts.getObjects());
}
}
}
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
return listobjcontent;
}
/**
* This code takes an array of [typename, property, property, ...] and
* converts it into a PropertySpec[]. handles case where multiple references
* to the same typename are specified.
*
* @param typeinfo 2D array of type and properties to retrieve
*
* @return Array of container filter specs
*/
private List<PropertySpec> buildPropertySpecArray(String[][] typeinfo) {
// Eliminate duplicates
HashMap<String, Set> tInfo = new HashMap<String, Set>();
for (int ti = 0; ti < typeinfo.length; ++ti) {
Set props = (Set) tInfo.get(typeinfo[ti][0]);
if (props == null) {
props = new HashSet<String>();
tInfo.put(typeinfo[ti][0], props);
}
boolean typeSkipped = false;
for (int pi = 0; pi < typeinfo[ti].length; ++pi) {
String prop = typeinfo[ti][pi];
if (typeSkipped) {
props.add(prop);
} else {
typeSkipped = true;
}
}
}
// Create PropertySpecs
ArrayList<PropertySpec> pSpecs = new ArrayList<PropertySpec>();
for (Iterator<String> ki = tInfo.keySet().iterator(); ki.hasNext();) {
String type = (String) ki.next();
PropertySpec pSpec = new PropertySpec();
Set props = (Set) tInfo.get(type);
pSpec.setType(type);
pSpec.setAll(props.isEmpty() ? Boolean.TRUE : Boolean.FALSE);
for (Iterator pi = props.iterator(); pi.hasNext();) {
String prop = (String) pi.next();
pSpec.getPathSet().equals(prop);
}
pSpecs.add(pSpec);
}
return pSpecs;
}
/**
* Retrieve content recursively with multiple properties. the typeinfo array
* contains typename + properties to retrieve.
*
* @param collector a property collector if available or null for default
* @param root a root folder if available, or null for default
* @param typeinfo 2D array of properties for each typename
* @param recurse retrieve contents recursively from the root down
*
* @return retrieved object contents
*/
private List<ObjectContent> getContentsRecursively(ManagedObjectReference collector,
ManagedObjectReference root,
String[][] typeinfo, boolean recurse)
throws VMwareConnectionException {
if (typeinfo == null || typeinfo.length == 0) {
return null;
}
ManagedObjectReference usecoll = collector;
if (usecoll == null) {
usecoll = serviceContent.getPropertyCollector();
if (usecoll != null) {
log.debug("usecoll = " + usecoll.getType());
}
}
ManagedObjectReference useroot = root;
if (useroot == null) {
useroot = serviceContent.getRootFolder();
}
List<SelectionSpec> selectionSpecs = null;
if (recurse) {
selectionSpecs = buildFullTraversal();
}
List<PropertySpec> propspecary = buildPropertySpecArray(typeinfo);
ObjectSpec objSpec = new ObjectSpec();
objSpec.setObj(useroot);
objSpec.setSkip(Boolean.FALSE);
objSpec.getSelectSet().equals((PropertySpec[])selectionSpecs.toArray());
List<ObjectSpec> objSpecList = new ArrayList<>();
objSpecList.add(objSpec);
PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getPropSet().equals(propspecary);
spec.getObjectSet().equals(objSpecList);
List<PropertyFilterSpec> listpfs = new ArrayList<>();
listpfs.add(spec);
List<ObjectContent> listobjcont = retrievePropertiesAllObjects(listpfs);
return listobjcont;
}
private boolean typeIsA(String searchType,
String foundType) {
if (searchType.equals(foundType)) {
return true;
} else if (searchType.equals("ManagedEntity")) {
for (int i = 0; i < meTree.length; ++i) {
if (meTree[i].equals(foundType)) {
return true;
}
}
} else if (searchType.equals("ComputeResource")) {
for (int i = 0; i < crTree.length; ++i) {
if (crTree[i].equals(foundType)) {
return true;
}
}
} else if (searchType.equals("HistoryCollector")) {
for (int i = 0; i < hcTree.length; ++i) {
if (hcTree[i].equals(foundType)) {
return true;
}
}
}
return false;
}
/**
* Get the ManagedObjectReference for an item under the specified root
* folder that has the type and name specified.
*
* @param root a root folder if available, or null for default
* @param type type of the managed object
* @param name name to match
*
* @return First ManagedObjectReference of the type / name pair found
*/
private ManagedObjectReference getDecendentMoRef(ManagedObjectReference root,
String type,
String name)
throws VMwareConnectionException {
if (name == null || name.length() == 0) {
return null;
}
String[][] typeinfo =
new String[][]{new String[]{type, "name"},};
List<ObjectContent> ocary =
getContentsRecursively(null, root, typeinfo, true);
if (ocary == null || ocary.size() == 0) {
return null;
}
ObjectContent oc;
ManagedObjectReference mor = null;
List<DynamicProperty> propary;
String propval;
boolean found = false;
for (int oci = 0; oci < ocary.size() && !found; oci++) {
oc = ocary.get(oci);
mor = oc.getObj();
DynamicProperty[] temp_propary = oc.getPropSet();
propary = Arrays.asList(temp_propary);
propval = null;
if (type == null || typeIsA(type, mor.getType())) {
if (propary != null && !propary.isEmpty()) {
propval = (String) propary.get(0).getVal();
}
found = propval != null && name.equals(propval);
}
}
if (!found) {
mor = null;
}
return mor;
}
private String getProp(ManagedObjectReference obj,
String prop) throws VMwareConnectionException {
String propVal = null;
try {
List<DynamicProperty> dynaProArray = getDynamicProarray(obj, obj.getType(), prop);
if (dynaProArray != null && !dynaProArray.isEmpty()) {
if (dynaProArray.get(0).getVal() != null) {
propVal = (String) dynaProArray.get(0).getVal();
}
}
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
return propVal;
}
private ArrayList filterMOR(ArrayList mors,
String[][] filter)
throws VMwareConnectionException {
ArrayList filteredmors =
new ArrayList();
for (int i = 0; i < mors.size(); i++) {
for (int k = 0; k < filter.length; k++) {
String prop = filter[k][0];
String reqVal = filter[k][1];
String value = getProp(((ManagedObjectReference) mors.get(i)), prop);
if (value == null && reqVal == null) {
continue;
} else if (value == null && reqVal != null) {
k = filter.length + 1;
} else if (value != null && value.equalsIgnoreCase(reqVal)) {
filteredmors.add(mors.get(i));
} else {
k = filter.length + 1;
}
}
}
return filteredmors;
}
private ArrayList getDecendentMoRefs(ManagedObjectReference root,
String type,
String[][] filter)
throws VMwareConnectionException {
String[][] typeinfo = new String[][]{new String[]{type, "name"},};
List<ObjectContent> ocary =
getContentsRecursively(null, root, typeinfo, true);
ArrayList refs = new ArrayList();
if (ocary == null || ocary.size() == 0) {
return refs;
}
for (int oci = 0; oci < ocary.size(); oci++) {
refs.add(ocary.get(oci).getObj());
}
if (filter != null) {
ArrayList filtermors = filterMOR(refs, filter);
return filtermors;
} else {
return refs;
}
}
/**
*
* @return TraversalSpec specification to get to the VirtualMachine managed
* object.
*/
/* not used ...
private TraversalSpec getVMTraversalSpec() {
// Create a traversal spec that starts from the 'root' objects
// and traverses the inventory tree to get to the VirtualMachines.
// Build the traversal specs bottoms up
//Traversal to get to the VM in a VApp
TraversalSpec vAppToVM = new TraversalSpec();
vAppToVM.setName("vAppToVM");
vAppToVM.setType("VirtualApp");
vAppToVM.setPath("vm");
//Traversal spec for VApp to VApp
TraversalSpec vAppToVApp = new TraversalSpec();
vAppToVApp.setName("vAppToVApp");
vAppToVApp.setType("VirtualApp");
vAppToVApp.setPath("resourcePool");
//SelectionSpec for VApp to VApp recursion
SelectionSpec vAppRecursion = new SelectionSpec();
vAppRecursion.setName("vAppToVApp");
//SelectionSpec to get to a VM in the VApp
SelectionSpec vmInVApp = new SelectionSpec();
vmInVApp.setName("vAppToVM");
//SelectionSpec for both VApp to VApp and VApp to VM
List<SelectionSpec> vAppToVMSS = new ArrayList<SelectionSpec>();
vAppToVMSS.add(vAppRecursion);
vAppToVMSS.add(vmInVApp);
vAppToVApp.getSelectSet().addAll(vAppToVMSS);
//This SelectionSpec is used for recursion for Folder recursion
SelectionSpec sSpec = new SelectionSpec();
sSpec.setName("VisitFolders");
// Traversal to get to the vmFolder from DataCenter
TraversalSpec dataCenterToVMFolder = new TraversalSpec();
dataCenterToVMFolder.setName("DataCenterToVMFolder");
dataCenterToVMFolder.setType("Datacenter");
dataCenterToVMFolder.setPath("vmFolder");
dataCenterToVMFolder.setSkip(false);
dataCenterToVMFolder.getSelectSet().add(sSpec);
// TraversalSpec to get to the DataCenter from rootFolder
TraversalSpec traversalSpec = new TraversalSpec();
traversalSpec.setName("VisitFolders");
traversalSpec.setType("Folder");
traversalSpec.setPath("childEntity");
traversalSpec.setSkip(false);
List<SelectionSpec> sSpecArr = new ArrayList<SelectionSpec>();
sSpecArr.add(sSpec);
sSpecArr.add(dataCenterToVMFolder);
sSpecArr.add(vAppToVM);
sSpecArr.add(vAppToVApp);
traversalSpec.getSelectSet().addAll(sSpecArr);
return traversalSpec;
}*/
// unused
/**
* Get the MOR of the Virtual Machine by its name.
*
* @param vmName The name of the Virtual Machine
* @return The Managed Object reference for this VM
*/
/*
private ManagedObjectReference getVmByVMname(String vmname) throws VMwareConnectionException {
ManagedObjectReference retVal = null;
try {
TraversalSpec tSpec = getVMTraversalSpec();
// Create Property Spec
PropertySpec propertySpec = new PropertySpec();
propertySpec.setAll(Boolean.FALSE);
propertySpec.getPathSet().add("name");
propertySpec.setType("VirtualMachine");
// Now create Object Spec
ObjectSpec objectSpec = new ObjectSpec();
objectSpec.setObj(rootRef);
objectSpec.setSkip(Boolean.TRUE);
objectSpec.getSelectSet().add(tSpec);
// Create PropertyFilterSpec using the PropertySpec and ObjectPec
// created above.
PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec();
propertyFilterSpec.getPropSet().add(propertySpec);
propertyFilterSpec.getObjectSet().add(objectSpec);
List<PropertyFilterSpec> listpfs = new ArrayList<PropertyFilterSpec>(1);
listpfs.add(propertyFilterSpec);
List<ObjectContent> listobjcont = retrievePropertiesAllObjects(listpfs);
if (listobjcont != null) {
for (ObjectContent oc : listobjcont) {
ManagedObjectReference mr = oc.getObj();
String vmnm = null;
List<DynamicProperty> dps = oc.getPropSet();
if (dps != null) {
for (DynamicProperty dp : dps) {
vmnm = (String) dp.getVal();
}
}
if (vmnm != null && vmnm.equals(vmname)) {
retVal = mr;
break;
}
}
}
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
return retVal;
}*/
/*
* @return An array of SelectionSpec covering VM, Host, Resource pool,
* Cluster Compute Resource and Datastore.
*/
private List<SelectionSpec> buildFullTraversal() {
// Terminal traversal specs
// RP -> VM
TraversalSpec rpToVm = new TraversalSpec();
rpToVm.setName("rpToVm");
rpToVm.setType("ResourcePool");
rpToVm.setPath("vm");
rpToVm.setSkip(Boolean.FALSE);
// vApp -> VM
TraversalSpec vAppToVM = new TraversalSpec();
vAppToVM.setName("vAppToVM");
vAppToVM.setType("VirtualApp");
vAppToVM.setPath("vm");
// HostSystem -> VM
TraversalSpec hToVm = new TraversalSpec();
hToVm.setType("HostSystem");
hToVm.setPath("vm");
hToVm.setName("hToVm");
hToVm.getSelectSet().equals(getSelectionSpec("visitFolders"));
hToVm.setSkip(Boolean.FALSE);
// DC -> DS
TraversalSpec dcToDs = new TraversalSpec();
dcToDs.setType("Datacenter");
dcToDs.setPath("datastore");
dcToDs.setName("dcToDs");
dcToDs.setSkip(Boolean.FALSE);
// Recurse through all ResourcePools
TraversalSpec rpToRp = new TraversalSpec();
rpToRp.setType("ResourcePool");
rpToRp.setPath("resourcePool");
rpToRp.setSkip(Boolean.FALSE);
rpToRp.setName("rpToRp");
List<SelectionSpec> respools = new ArrayList<SelectionSpec>();
respools.add(getSelectionSpec("rpToRp"));
respools.add(getSelectionSpec("rpToVm"));
rpToRp.getSelectSet().equals((SelectionSpec[])respools.toArray());
TraversalSpec crToRp = new TraversalSpec();
crToRp.setType("ComputeResource");
crToRp.setPath("resourcePool");
crToRp.setSkip(Boolean.FALSE);
crToRp.setName("crToRp");
List<SelectionSpec> crrp = new ArrayList<SelectionSpec>();
crrp.add(getSelectionSpec("rpToRp"));
crrp.add(getSelectionSpec("rpToVm"));
crToRp.getSelectSet().equals((SelectionSpec[])crrp.toArray());
TraversalSpec crToH = new TraversalSpec();
crToH.setSkip(Boolean.FALSE);
crToH.setType("ComputeResource");
crToH.setPath("host");
crToH.setName("crToH");
TraversalSpec dcToHf = new TraversalSpec();
dcToHf.setSkip(Boolean.FALSE);
dcToHf.setType("Datacenter");
dcToHf.setPath("hostFolder");
dcToHf.setName("dcToHf");
dcToHf.getSelectSet().equals(getSelectionSpec("visitFolders"));
TraversalSpec vAppToRp = new TraversalSpec();
vAppToRp.setName("vAppToRp");
vAppToRp.setType("VirtualApp");
vAppToRp.setPath("resourcePool");
vAppToRp.getSelectSet().equals(getSelectionSpec("rpToRp"));
TraversalSpec dcToVmf = new TraversalSpec();
dcToVmf.setType("Datacenter");
dcToVmf.setSkip(Boolean.FALSE);
dcToVmf.setPath("vmFolder");
dcToVmf.setName("dcToVmf");
dcToVmf.getSelectSet().equals(getSelectionSpec("visitFolders"));
// For Folder -> Folder recursion
TraversalSpec visitFolders = new TraversalSpec();
visitFolders.setType("Folder");
visitFolders.setPath("childEntity");
visitFolders.setSkip(Boolean.FALSE);
visitFolders.setName("visitFolders");
List<SelectionSpec> sspecarrvf = new ArrayList<SelectionSpec>();
sspecarrvf.add(getSelectionSpec("visitFolders"));
sspecarrvf.add(getSelectionSpec("dcToVmf"));
sspecarrvf.add(getSelectionSpec("dcToHf"));
sspecarrvf.add(getSelectionSpec("dcToDs"));
sspecarrvf.add(getSelectionSpec("crToRp"));
sspecarrvf.add(getSelectionSpec("crToH"));
sspecarrvf.add(getSelectionSpec("hToVm"));
sspecarrvf.add(getSelectionSpec("rpToVm"));
sspecarrvf.add(getSelectionSpec("rpToRp"));
sspecarrvf.add(getSelectionSpec("vAppToRp"));
sspecarrvf.add(getSelectionSpec("vAppToVM"));
visitFolders.getSelectSet().equals((SelectionSpec[])sspecarrvf.toArray());
List<SelectionSpec> resultspec = new ArrayList<SelectionSpec>();
resultspec.add(visitFolders);
resultspec.add(dcToVmf);
resultspec.add(dcToHf);
resultspec.add(dcToDs);
resultspec.add(crToRp);
resultspec.add(crToH);
resultspec.add(hToVm);
resultspec.add(rpToVm);
resultspec.add(vAppToRp);
resultspec.add(vAppToVM);
resultspec.add(rpToRp);
return resultspec;
}
private SelectionSpec getSelectionSpec(String name) {
SelectionSpec genericSpec = new SelectionSpec();
genericSpec.setName(name);
return genericSpec;
}
private List<DynamicProperty> getDynamicProarray(ManagedObjectReference ref,
String type,
String propertyString)
throws VMwareConnectionException {
PropertySpec propertySpec = new PropertySpec();
propertySpec.setAll(Boolean.FALSE);
propertySpec.getPathSet().equals(propertyString);
propertySpec.setType(type);
// Now create Object Spec
ObjectSpec objectSpec = new ObjectSpec();
objectSpec.setObj(ref);
objectSpec.setSkip(Boolean.FALSE);
objectSpec.getSelectSet().equals((SelectionSpec[])buildFullTraversal().toArray());
// Create PropertyFilterSpec using the PropertySpec and ObjectPec
// created above.
PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec();
propertyFilterSpec.getPropSet().equals(propertySpec);
propertyFilterSpec.getObjectSet().equals(objectSpec);
List<PropertyFilterSpec> listpfs = new ArrayList<PropertyFilterSpec>(1);
listpfs.add(propertyFilterSpec);
List<ObjectContent> listobjcont = retrievePropertiesAllObjects(listpfs);
ObjectContent contentObj = listobjcont.get(0);
List<DynamicProperty> objList = Arrays.asList(contentObj.getPropSet());
return objList;
}
// unused
/*
private boolean getTaskInfo(ManagedObjectReference taskmor)
throws VMwareConnectionException {
boolean valid = false;
String res = waitForTask(taskmor);
if(res.equalsIgnoreCase("success")) {
valid = true;
} else {
valid = false;
}
return valid;
}
*/
private void updateValues(List<String> props,
Object[] vals,
PropertyChange propchg) {
for (int findi = 0; findi < props.size(); findi++) {
if (propchg.getName().lastIndexOf(props.get(findi)) >= 0) {
if (propchg.getOp() == PropertyChangeOp.remove) {
vals[findi] = "";
} else {
vals[findi] = propchg.getVal();
}
}
}
}
/**
* Handle Updates for a single object. waits till expected values of
* properties to check are reached Destroys the ObjectFilter when done.
*
* @param objmor MOR of the Object to wait for </param>
* @param filterProps Properties list to filter
* @param endWaitProps Properties list to check for expected values these be
* properties of a property in the filter properties list
* @param expectedVals values for properties to end the wait
* @return true indicating expected values were met, and false otherwise
*/
private Object[] waitForValues(ManagedObjectReference objmor,
List<String> filterProps,
List<String> endWaitProps,
Object[][] expectedVals)
throws VMwareConnectionException {
// version string is initially null
String version = "";
Object[] endVals = new Object[endWaitProps.size()];
Object[] filterVals = new Object[filterProps.size()];
ObjectSpec objSpec = new ObjectSpec();
objSpec.setObj(objmor);
objSpec.setSkip(Boolean.FALSE);
PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getObjectSet().equals(objSpec);
PropertySpec propSpec = new PropertySpec();
propSpec.getPathSet().equals((String[])filterProps.toArray());
propSpec.setType(objmor.getType());
spec.getPropSet().equals(propSpec);
ManagedObjectReference filterSpecRef;
try {
filterSpecRef = vimPort.createFilter(propCollectorRef, spec, true);
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
boolean reached = false;
UpdateSet updateset = null;
List<PropertyFilterUpdate> filtupary;
PropertyFilterUpdate filtup;
List<ObjectUpdate> objupary;
ObjectUpdate objup;
List<PropertyChange> propchgary;
PropertyChange propchg;
while (!reached) {
boolean retry = true;
while (retry) {
try {
updateset =
vimPort.waitForUpdates(propCollectorRef, version);
retry = false;
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
}
if (updateset != null) {
version = updateset.getVersion();
}
if (updateset == null || updateset.getFilterSet() == null) {
continue;
}
// Make this code more general purpose when PropCol changes later.
filtupary = Arrays.asList(updateset.getFilterSet());
for (int fi = 0; fi < filtupary.size(); fi++) {
filtup = filtupary.get(fi);
objupary = Arrays.asList(filtup.getObjectSet());
for (int oi = 0; oi < objupary.size(); oi++) {
objup = objupary.get(oi);
if (objup.getKind() == ObjectUpdateKind.modify
|| objup.getKind() == ObjectUpdateKind.enter
|| objup.getKind() == ObjectUpdateKind.leave) {
propchgary = Arrays.asList(objup.getChangeSet());
for (int ci = 0; ci < propchgary.size(); ci++) {
propchg = propchgary.get(ci);
updateValues(endWaitProps, endVals, propchg);
updateValues(filterProps, filterVals, propchg);
}
}
}
}
Object expctdval;
// Check if the expected values have been reached and exit the loop if done.
// Also exit the WaitForUpdates loop if this is the case.
for (int chgi = 0; chgi < endVals.length && !reached; chgi++) {
for (int vali = 0; vali < expectedVals[chgi].length && !reached; vali++) {
expctdval = expectedVals[chgi][vali];
reached = expctdval.equals(endVals[chgi]) || reached;
}
}
}
// Destroy the filter when we are done.
try {
vimPort.destroyPropertyFilter(filterSpecRef);
} catch (Exception e) {
throw new VMwareConnectionException(e);
}
return filterVals;
}
private String waitForTask(ManagedObjectReference taskmor) throws VMwareConnectionException {
List<String> infoList = new ArrayList<String>();
infoList.add("info.state");
infoList.add("info.error");
List<String> stateList = new ArrayList<String>();
stateList.add("state");
Object[] result = waitForValues(
taskmor, infoList, stateList,
new Object[][]{new Object[]{
TaskInfoState.success, TaskInfoState.error}});
if (result[0].equals(TaskInfoState.success)) {
return "success";
} else {
List<DynamicProperty> tinfoProps;
tinfoProps = getDynamicProarray(taskmor, "Task", "info");
TaskInfo tinfo = (TaskInfo) tinfoProps.get(0).getVal();
LocalizedMethodFault fault = tinfo.getError();
String error = "Error Occured";
if (fault != null) {
error = fault.getLocalizedMessage();
log.error("Message " + fault.getLocalizedMessage());
}
return error;
}
}
// </editor-fold>
}