/** * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander 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, either version 3 of the License, or * (at your option) any later version. * * muCommander 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 for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mucommander.commons.file.protocol.vsphere; import java.io.Closeable; import java.io.IOException; import java.rmi.RemoteException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.xml.ws.BindingProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mucommander.commons.util.StringUtils; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.InvalidLocaleFaultMsg; import com.vmware.vim25.InvalidLoginFaultMsg; import com.vmware.vim25.InvalidPropertyFaultMsg; 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.RuntimeFaultFaultMsg; import com.vmware.vim25.ServiceContent; import com.vmware.vim25.UserSession; import com.vmware.vim25.VimPortType; import com.vmware.vim25.VimService; /** * Wrapper over the vSphere API * * @author Yuval Kohavi <yuval.kohavi@intigua.com> * */ public class VSphereClient implements Closeable { public static final String TYPE_SERVICE_INSTANCE = "ServiceInstance"; private static Logger log = LoggerFactory.getLogger(VSphereClient.class); private final String server; private final String user; private final String password; private ServiceContent serviceContent; private VimPortType vimPort; private boolean connected = false; private Integer port; public String getServer() { return server; } public boolean isConnected() { return connected; } public VSphereClient(String server, String user, String password) { this.server = server; this.user = user; this.password = password; } protected String getVSphereServiceUrl() { if (StringUtils.isNullOrEmpty((server))) { log.warn("Can't construct vim service url, vSphere host name is empty"); throw new IllegalArgumentException(); } StringBuilder builder = new StringBuilder(); builder.append("https://"); builder.append(server); if (port != null) { builder.append(":"); builder.append(port); } builder.append("/sdk/vimService"); return builder.toString(); } /** * Establishes session with the vSphere server. * * @return true if connected successfully * @throws RuntimeFaultFaultMsg * @throws InvalidLoginFaultMsg * @throws InvalidLocaleFaultMsg * @throws NoSuchAlgorithmException * @throws KeyManagementException * * @throws Exception * the exception */ public void connect() throws RuntimeFaultFaultMsg, InvalidLocaleFaultMsg, InvalidLoginFaultMsg { String connectionUrl = getVSphereServiceUrl(); doTrust(); ManagedObjectReference serviceInstanceMOR = getServiceInstance(); VimService vimService = new VimService(); log.trace("Getting vimPort from vimService"); vimPort = vimService.getVimPort(); log.trace("vimPort is gotT successfully"); log.trace("Getting context from vimPort"); Map<String, Object> requestContext = ((BindingProvider) vimPort) .getRequestContext(); log.trace("Context from vimPort is got successfully"); log.trace("URL to connect to vSphere host '{}'", connectionUrl); requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, connectionUrl); requestContext.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true); // do trust ? TODO /* requestContext.put(JAXWSProperties.SSL_SOCKET_FACTORY, getSSLContext() .getSocketFactory()); HostnameVerifier hv = new HostnameVerifier() { @Override public boolean verify(String urlHostName, SSLSession session) { return true; } }; requestContext.put(JAXWSProperties.HOSTNAME_VERIFIER, hv); */ log.trace("Retrieving service content"); serviceContent = vimPort.retrieveServiceContent(serviceInstanceMOR); log.trace("Service content retrieved successfully"); log.trace("Logging in to vSphere host '{}'", server); UserSession userSession = vimPort.login(serviceContent.getSessionManager(), user, password, null); log.trace("Logged in successfully to vSphere host '{}'", server); connected = true; } public ManagedObjectReference getServiceInstance() { ManagedObjectReference serviceInstanceMOR = new ManagedObjectReference(); serviceInstanceMOR.setType(TYPE_SERVICE_INSTANCE); serviceInstanceMOR.setValue(TYPE_SERVICE_INSTANCE); return serviceInstanceMOR; } private void doTrust() { HostnameVerifier hv = new HostnameVerifier() { @Override public boolean verify(String urlHostName, SSLSession session) { return true; } }; try { trustAllHttpsCertificates(); } catch (KeyManagementException e) { throw new IllegalStateException("SSL init problems", e); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("SSL init problems", e); } HttpsURLConnection.setDefaultHostnameVerifier(hv); } @Override public void close() throws IOException { try { disconnect(); } catch (RuntimeFaultFaultMsg e) { throw new IOException(e); } } /** * Disconnects the user session. * * @throws RuntimeFaultFaultMsg * * @throws Exception */ public void disconnect() throws RuntimeFaultFaultMsg { if (connected) { log.trace("Logging out from vSphere host '{}'", server); vimPort.logout(serviceContent.getSessionManager()); log.trace("Logged out successfully from vSphere host '{}'", server); } connected = false; } public ManagedObjectReference findVmByUuid(String uuid, boolean instanceUuid) throws RuntimeFaultFaultMsg { return vimPort.findByUuid(this.serviceContent.getSearchIndex(), null, uuid, true, instanceUuid); } public ManagedObjectReference findVmByIp(String ip) throws RuntimeFaultFaultMsg { return vimPort.findByIp(this.serviceContent.getSearchIndex(), null, ip, true); } /* taken from vmware samples */ public Object[] getProperties(ManagedObjectReference moRef, String... properties) throws RemoteException, InvalidPropertyFaultMsg, RuntimeFaultFaultMsg { // PropertySpec specifies what properties to // retrieve and from type of Managed Object PropertySpec pSpec = new PropertySpec(); pSpec.setType(moRef.getType()); pSpec.getPathSet().addAll(Arrays.asList(properties)); // 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().addAll(Arrays.asList(new PropertySpec[] { pSpec })); pfSpec.getObjectSet().addAll(Arrays.asList(new ObjectSpec[] { oSpec })); // retrieveProperties() returns the properties // selected from the PropertyFilterSpec List<ObjectContent> ocs = vimPort.retrieveProperties( serviceContent.getPropertyCollector(), Arrays.asList(new PropertyFilterSpec[] { pfSpec })); // Return value, one object for each property specified Object[] ret = new Object[properties.length]; if (ocs != null) { for (ObjectContent oc : ocs) { List<DynamicProperty> dps = oc.getPropSet(); if (dps != null) { for (DynamicProperty dp : dps) { // find property path index for (int p = 0; p < ret.length; ++p) { if (properties[p].equals(dp.getName())) { ret[p] = dp.getVal(); } } } } } } return ret; } private void trustAllHttpsCertificates() throws NoSuchAlgorithmException, KeyManagementException { javax.net.ssl.SSLContext sc = getSSLContext(); javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc .getSocketFactory()); } private javax.net.ssl.SSLContext getSSLContext() { // Create a trust manager that does not validate certificate chains: javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new TrustAllTrustManager(); trustAllCerts[0] = tm; try { javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext .getInstance("SSL"); javax.net.ssl.SSLSessionContext sslsc = sc .getServerSessionContext(); sslsc.setSessionTimeout(0); sc.init(null, trustAllCerts, null); return sc; } catch (KeyManagementException e) { throw new IllegalStateException("SSL init problems", e); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("SSL init problems", e); } } 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 { return; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } } public VimPortType getVimPort() { return this.vimPort; } public ServiceContent getServiceContent() { return this.serviceContent; } }