| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| package com.cloud.hypervisor.vmware.util; |
| |
| import java.io.BufferedInputStream; |
| import java.io.BufferedOutputStream; |
| import java.io.BufferedReader; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.io.UnsupportedEncodingException; |
| import java.net.HttpURLConnection; |
| import java.net.URL; |
| import java.net.URLEncoder; |
| import java.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| 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.soap.SOAPFaultException; |
| |
| import org.apache.cloudstack.utils.security.SSLUtils; |
| import org.apache.cloudstack.utils.security.SecureSSLSocketFactory; |
| import org.apache.log4j.Logger; |
| |
| import com.cloud.hypervisor.vmware.mo.DatacenterMO; |
| import com.cloud.hypervisor.vmware.mo.DatastoreFile; |
| import com.cloud.utils.ActionDelegate; |
| import com.cloud.utils.StringUtils; |
| import com.vmware.pbm.PbmPortType; |
| import com.vmware.pbm.PbmServiceInstanceContent; |
| 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.ServiceContent; |
| import com.vmware.vim25.TaskInfo; |
| import com.vmware.vim25.TraversalSpec; |
| import com.vmware.vim25.VimPortType; |
| |
| public class VmwareContext { |
| private static final Logger s_logger = Logger.getLogger(VmwareContext.class); |
| |
| private static final int MAX_CONNECT_RETRY = 5; |
| private static final int CONNECT_RETRY_INTERVAL = 1000; |
| |
| private static final int ChunkSize = 1 * 1024 * 1024; // 1M |
| |
| private final VmwareClient _vimClient; |
| private final String _serverAddress; |
| |
| private final Map<String, Object> _stockMap = new HashMap<String, Object>(); |
| |
| private VmwareContextPool _pool; |
| private String _poolKey; |
| |
| private static volatile int s_outstandingCount = 0; |
| |
| static { |
| try { |
| javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; |
| javax.net.ssl.TrustManager tm = new TrustAllManager(); |
| trustAllCerts[0] = tm; |
| javax.net.ssl.SSLContext sc = SSLUtils.getSSLContext(); |
| sc.init(null, trustAllCerts, null); |
| javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(new SecureSSLSocketFactory(sc)); |
| |
| HostnameVerifier hv = new HostnameVerifier() { |
| @Override |
| public boolean verify(String urlHostName, SSLSession session) { |
| return true; |
| } |
| }; |
| HttpsURLConnection.setDefaultHostnameVerifier(hv); |
| } catch (Exception e) { |
| s_logger.error("Unexpected exception ", e); |
| } |
| } |
| |
| public VmwareContext(VmwareClient client, String address) { |
| assert (client != null) : "Invalid parameter in constructing VmwareContext object"; |
| |
| _vimClient = client; |
| _serverAddress = address; |
| |
| registerOutstandingContext(); |
| if (s_logger.isInfoEnabled()) |
| s_logger.info("New VmwareContext object, current outstanding count: " + getOutstandingContextCount()); |
| } |
| |
| public boolean validate() { |
| return _vimClient.validate(); |
| } |
| |
| public void registerStockObject(String name, Object obj) { |
| synchronized (_stockMap) { |
| _stockMap.put(name, obj); |
| } |
| } |
| |
| public void uregisterStockObject(String name) { |
| synchronized (_stockMap) { |
| _stockMap.remove(name); |
| } |
| } |
| |
| public void clearStockObjects() { |
| synchronized (_stockMap) { |
| _stockMap.clear(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <T> T getStockObject(String name) { |
| synchronized (_stockMap) { |
| return (T)_stockMap.get(name); |
| } |
| } |
| |
| public String getServerAddress() { |
| return _serverAddress; |
| } |
| |
| public VimPortType getService() { |
| return _vimClient.getService(); |
| } |
| |
| public ServiceContent getServiceContent() { |
| return _vimClient.getServiceContent(); |
| } |
| |
| public PbmPortType getPbmService() { |
| return _vimClient.getPbmService(); |
| } |
| |
| public PbmServiceInstanceContent getPbmServiceContent() { |
| return _vimClient.getPbmServiceContent(); |
| } |
| |
| public ManagedObjectReference getPropertyCollector() { |
| return _vimClient.getPropCol(); |
| } |
| |
| public ManagedObjectReference getRootFolder() { |
| return _vimClient.getRootFolder(); |
| } |
| |
| public VmwareClient getVimClient() { |
| return _vimClient; |
| } |
| |
| public void setPoolInfo(VmwareContextPool pool, String poolKey) { |
| _pool = pool; |
| _poolKey = poolKey; |
| } |
| |
| public VmwareContextPool getPool() { |
| return _pool; |
| } |
| |
| public String getPoolKey() { |
| return _poolKey; |
| } |
| |
| public void idleCheck() throws Exception { |
| getRootFolder(); |
| } |
| |
| public static int getOutstandingContextCount() { |
| return s_outstandingCount; |
| } |
| |
| public static void registerOutstandingContext() { |
| s_outstandingCount++; |
| } |
| |
| public static void unregisterOutstandingContext() { |
| s_outstandingCount--; |
| } |
| |
| public ManagedObjectReference getHostMorByPath(String inventoryPath) throws Exception { |
| assert (inventoryPath != null); |
| |
| String[] tokens; |
| if (inventoryPath.startsWith("/")) |
| tokens = inventoryPath.substring(1).split("/"); |
| else |
| tokens = inventoryPath.split("/"); |
| |
| ManagedObjectReference mor = getRootFolder(); |
| for (int i = 0; i < tokens.length; i++) { |
| String token = tokens[i]; |
| List<ObjectContent> ocs; |
| PropertySpec pSpec = null; |
| ObjectSpec oSpec = null; |
| if (mor.getType().equalsIgnoreCase("Datacenter")) { |
| pSpec = new PropertySpec(); |
| pSpec.setAll(false); |
| pSpec.setType("ManagedEntity"); |
| pSpec.getPathSet().add("name"); |
| |
| TraversalSpec dcHostFolderTraversal = new TraversalSpec(); |
| dcHostFolderTraversal.setType("Datacenter"); |
| dcHostFolderTraversal.setPath("hostFolder"); |
| dcHostFolderTraversal.setName("dcHostFolderTraversal"); |
| |
| oSpec = new ObjectSpec(); |
| oSpec.setObj(mor); |
| oSpec.setSkip(Boolean.TRUE); |
| oSpec.getSelectSet().add(dcHostFolderTraversal); |
| |
| } else if (mor.getType().equalsIgnoreCase("Folder")) { |
| pSpec = new PropertySpec(); |
| pSpec.setAll(false); |
| pSpec.setType("ManagedEntity"); |
| pSpec.getPathSet().add("name"); |
| |
| TraversalSpec folderChildrenTraversal = new TraversalSpec(); |
| folderChildrenTraversal.setType("Folder"); |
| folderChildrenTraversal.setPath("childEntity"); |
| folderChildrenTraversal.setName("folderChildrenTraversal"); |
| |
| oSpec = new ObjectSpec(); |
| oSpec.setObj(mor); |
| oSpec.setSkip(Boolean.TRUE); |
| oSpec.getSelectSet().add(folderChildrenTraversal); |
| |
| } else if (mor.getType().equalsIgnoreCase("ClusterComputeResource")) { |
| pSpec = new PropertySpec(); |
| pSpec.setType("ManagedEntity"); |
| pSpec.getPathSet().add("name"); |
| |
| TraversalSpec clusterHostTraversal = new TraversalSpec(); |
| clusterHostTraversal.setType("ClusterComputeResource"); |
| clusterHostTraversal.setPath("host"); |
| clusterHostTraversal.setName("folderChildrenTraversal"); |
| |
| oSpec = new ObjectSpec(); |
| oSpec.setObj(mor); |
| oSpec.setSkip(Boolean.TRUE); |
| oSpec.getSelectSet().add(clusterHostTraversal); |
| |
| } else { |
| s_logger.error("Invalid inventory path, path element can only be datacenter and folder"); |
| return null; |
| } |
| |
| PropertyFilterSpec pfSpec = new PropertyFilterSpec(); |
| pfSpec.getPropSet().add(pSpec); |
| pfSpec.getObjectSet().add(oSpec); |
| List<PropertyFilterSpec> pfSpecArr = new ArrayList<PropertyFilterSpec>(); |
| pfSpecArr.add(pfSpec); |
| ocs = getService().retrieveProperties(getPropertyCollector(), pfSpecArr); |
| |
| if (ocs != null && ocs.size() > 0) { |
| boolean found = false; |
| for (ObjectContent oc : ocs) { |
| String name = oc.getPropSet().get(0).getVal().toString(); |
| if (name.equalsIgnoreCase(token) || name.equalsIgnoreCase("host")) { |
| mor = oc.getObj(); |
| found = true; |
| if (name.equalsIgnoreCase("host")) |
| i--; |
| break; |
| } |
| } |
| if (!found) { |
| s_logger.error("Path element points to an un-existing inventory entity"); |
| return null; |
| } |
| } else { |
| s_logger.error("Path element points to an un-existing inventory entity"); |
| return null; |
| } |
| } |
| return mor; |
| } |
| |
| // path in format of <datacenter name>/<datastore name> |
| public ManagedObjectReference getDatastoreMorByPath(String inventoryPath) throws Exception { |
| assert (inventoryPath != null); |
| |
| String[] tokens; |
| if (inventoryPath.startsWith("/")) |
| tokens = inventoryPath.substring(1).split("/"); |
| else |
| tokens = inventoryPath.split("/"); |
| |
| if (tokens == null || tokens.length != 2) { |
| s_logger.error("Invalid datastore inventory path. path: " + inventoryPath); |
| return null; |
| } |
| |
| DatacenterMO dcMo = new DatacenterMO(this, tokens[0]); |
| if (dcMo.getMor() == null) { |
| s_logger.error("Unable to locate the datacenter specified in path: " + inventoryPath); |
| return null; |
| } |
| |
| return dcMo.findDatastore(tokens[1]); |
| } |
| |
| // path in format of <datacenter name>/<datastore name> |
| public String getDatastoreNameFromPath(String inventoryPath) throws Exception { |
| assert (inventoryPath != null); |
| |
| String[] tokens; |
| if (inventoryPath.startsWith("/")) |
| tokens = inventoryPath.substring(1).split("/"); |
| else |
| tokens = inventoryPath.split("/"); |
| |
| if (tokens == null || tokens.length != 2) { |
| s_logger.error("Invalid datastore inventory path. path: " + inventoryPath); |
| return null; |
| } |
| |
| return tokens[1]; |
| } |
| |
| public void waitForTaskProgressDone(ManagedObjectReference morTask) throws Exception { |
| while (true) { |
| TaskInfo tinfo = (TaskInfo)_vimClient.getDynamicProperty(morTask, "info"); |
| Integer progress = tinfo.getProgress(); |
| if (progress == null) |
| break; |
| |
| if (progress.intValue() >= 100) |
| break; |
| |
| Thread.sleep(1000); |
| } |
| } |
| |
| public void getFile(String urlString, String localFileFullName) throws Exception { |
| HttpURLConnection conn = getHTTPConnection(urlString); |
| |
| InputStream in = conn.getInputStream(); |
| OutputStream out = new FileOutputStream(new File(localFileFullName)); |
| byte[] buf = new byte[ChunkSize]; |
| int len = 0; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| } |
| in.close(); |
| out.close(); |
| } |
| |
| public void uploadFile(String httpMethod, String urlString, String localFileName) throws Exception { |
| HttpURLConnection conn = getRawHTTPConnection(urlString); |
| |
| conn.setDoOutput(true); |
| conn.setUseCaches(false); |
| |
| conn.setChunkedStreamingMode(ChunkSize); |
| conn.setRequestMethod(httpMethod); |
| conn.setRequestProperty("Connection", "Keep-Alive"); |
| String contentType = "application/octet-stream"; |
| conn.setRequestProperty("content-type", contentType); |
| conn.setRequestProperty("content-length", Long.toString(new File(localFileName).length())); |
| connectWithRetry(conn); |
| OutputStream out = null; |
| InputStream in = null; |
| BufferedReader br = null; |
| |
| try { |
| out = conn.getOutputStream(); |
| in = new FileInputStream(localFileName); |
| byte[] buf = new byte[ChunkSize]; |
| int len = 0; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| } |
| out.flush(); |
| } finally { |
| if (in != null) |
| in.close(); |
| |
| if (out != null) |
| out.close(); |
| |
| if (br != null) |
| br.close(); |
| conn.disconnect(); |
| } |
| } |
| |
| private Charset getCharSetFromConnection(HttpURLConnection conn) { |
| String charsetName = conn.getContentEncoding(); |
| Charset charset; |
| try { |
| charset = Charset.forName(charsetName); |
| } catch (IllegalArgumentException e) { |
| s_logger.warn("Illegal/unsupported/null charset name from connection. charsetname from connection is " + charsetName); |
| charset = StringUtils.getPreferredCharset(); |
| } |
| return charset; |
| } |
| |
| public void uploadVmdkFile(String httpMethod, String urlString, String localFileName, long totalBytesUpdated, ActionDelegate<Long> progressUpdater) throws Exception { |
| |
| HttpURLConnection conn = getRawHTTPConnection(urlString); |
| |
| conn.setDoOutput(true); |
| conn.setUseCaches(false); |
| |
| conn.setChunkedStreamingMode(ChunkSize); |
| conn.setRequestMethod(httpMethod); |
| if (urlString.endsWith(".iso")) { |
| conn.setRequestProperty("Overwrite", "t"); |
| } |
| conn.setRequestProperty("Connection", "Keep-Alive"); |
| String contentType = urlString.endsWith(".iso") ? |
| "application/octet-stream" : |
| "application/x-vnd.vmware-streamVmdk"; |
| conn.setRequestProperty("content-type", contentType); |
| conn.setRequestProperty("content-length", Long.toString(new File(localFileName).length())); |
| connectWithRetry(conn); |
| |
| BufferedOutputStream bos = null; |
| BufferedInputStream is = null; |
| try { |
| bos = new BufferedOutputStream(conn.getOutputStream()); |
| is = new BufferedInputStream(new FileInputStream(localFileName)); |
| int bufferSize = ChunkSize; |
| byte[] buffer = new byte[bufferSize]; |
| while (true) { |
| int bytesRead = is.read(buffer, 0, bufferSize); |
| if (bytesRead == -1) { |
| break; |
| } |
| bos.write(buffer, 0, bytesRead); |
| totalBytesUpdated += bytesRead; |
| bos.flush(); |
| if (progressUpdater != null) |
| progressUpdater.action(new Long(totalBytesUpdated)); |
| } |
| bos.flush(); |
| } finally { |
| if (is != null) |
| is.close(); |
| if (bos != null) |
| bos.close(); |
| |
| conn.disconnect(); |
| } |
| } |
| |
| public long downloadVmdkFile(String urlString, String localFileName, long totalBytesDownloaded, ActionDelegate<Long> progressUpdater) throws Exception { |
| HttpURLConnection conn = getRawHTTPConnection(urlString); |
| |
| String cookie = _vimClient.getServiceCookie(); |
| if (cookie == null) { |
| s_logger.error("No cookie is found in vwware web service request context!"); |
| throw new Exception("No cookie is found in vmware web service request context!"); |
| } |
| conn.addRequestProperty("Cookie", cookie); |
| conn.setDoInput(true); |
| conn.setDoOutput(true); |
| conn.setAllowUserInteraction(true); |
| connectWithRetry(conn); |
| |
| long bytesWritten = 0; |
| InputStream in = null; |
| OutputStream out = null; |
| try { |
| in = conn.getInputStream(); |
| out = new FileOutputStream(new File(localFileName)); |
| |
| byte[] buf = new byte[ChunkSize]; |
| int len = 0; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| bytesWritten += len; |
| totalBytesDownloaded += len; |
| |
| if (progressUpdater != null) |
| progressUpdater.action(new Long(totalBytesDownloaded)); |
| } |
| } finally { |
| if (in != null) |
| in.close(); |
| if (out != null) |
| out.close(); |
| |
| conn.disconnect(); |
| } |
| return bytesWritten; |
| } |
| |
| public byte[] getResourceContent(String urlString) throws Exception { |
| HttpURLConnection conn = getHTTPConnection(urlString); |
| InputStream in = conn.getInputStream(); |
| |
| ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| byte[] buf = new byte[ChunkSize]; |
| int len = 0; |
| while ((len = in.read(buf)) > 0) { |
| out.write(buf, 0, len); |
| } |
| in.close(); |
| out.close(); |
| return out.toByteArray(); |
| } |
| |
| public void uploadResourceContent(String urlString, byte[] content) throws Exception { |
| // vSphere does not support POST |
| HttpURLConnection conn = getHTTPConnection(urlString, "PUT"); |
| |
| OutputStream out = conn.getOutputStream(); |
| out.write(content); |
| out.flush(); |
| |
| BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), getCharSetFromConnection(conn))); |
| String line; |
| while ((in.ready()) && (line = in.readLine()) != null) { |
| if (s_logger.isTraceEnabled()) |
| s_logger.trace("Upload " + urlString + " response: " + line); |
| } |
| out.close(); |
| in.close(); |
| } |
| |
| /* |
| * Sample content returned by query a datastore directory |
| * |
| * Url for the query |
| * https://vsphere-1.lab.vmops.com/folder/Fedora-clone-test?dcPath=cupertino&dsName=NFS+datastore |
| * |
| * Returned conent from vSphere |
| * |
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <head> |
| <meta http-equiv="content-type" content="text/html; charset=utf-8"> |
| <title>Index of Fedora-clone-test on datastore NFS datastore in datacenter cupertino</title></head> |
| <body> |
| <h1>Index of Fedora-clone-test on datastore NFS datastore in datacenter cupertino</h1> |
| <table> |
| <tr><th>Name</th><th>Last modified</th><th>Size</th></tr><tr><th colspan="3"><hr></th></tr> |
| <tr><td><a href="/folder?dcPath=cupertino&dsName=NFS%20datastore">Parent Directory</a></td><td> </td><td align="right"> - </td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2ehlog?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test-a2013465.hlog</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">1</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2da2013465%2evswp?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test-a2013465.vswp</a></td><td align="right">14-Aug-2010 23:01</td><td align="right">402653184</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2dflat%2evmdk?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test-flat.vmdk</a></td><td align="right">26-Aug-2010 18:43</td><td align="right">17179869184</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2envram?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test.nvram</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">8684</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmdk?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test.vmdk</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">479</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmsd?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test.vmsd</a></td><td align="right">14-Aug-2010 16:59</td><td align="right">0</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmx?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test.vmx</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">3500</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/Fedora%2dclone%2dtest%2evmxf?dcPath=cupertino&dsName=NFS%20datastore"> |
| Fedora-clone-test.vmxf</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">272</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/test%2etxt?dcPath=cupertino&dsName=NFS%20datastore">test.txt</a></td> |
| <td align="right">24-Aug-2010 01:03</td><td align="right">12</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d2%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-2.log</a></td><td align="right">14-Aug-2010 16:51</td><td align="right">80782</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d3%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-3.log</a></td><td align="right">14-Aug-2010 19:07</td><td align="right">58573</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d4%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-4.log</a></td><td align="right">14-Aug-2010 23:00</td><td align="right">49751</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d5%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-5.log</a></td><td align="right">15-Aug-2010 00:04</td><td align="right">64024</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d6%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-6.log</a></td><td align="right">15-Aug-2010 00:11</td><td align="right">59742</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2d7%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware-7.log</a></td><td align="right">15-Aug-2010 00:13</td><td align="right">59859</td></tr> |
| <tr><td><a href="/folder/Fedora%2dclone%2dtest/vmware%2elog?dcPath=cupertino&dsName=NFS%20datastore"> |
| vmware.log</a></td><td align="right">15-Aug-2010 00:23</td><td align="right">47157</td></tr> |
| <tr><th colspan="5"><hr></th></tr> |
| </table> |
| </body> |
| </html> |
| */ |
| public String[] listDatastoreDirContent(String urlString) throws Exception { |
| List<String> fileList = new ArrayList<String>(); |
| String content = new String(getResourceContent(urlString),"UTF-8"); |
| String marker = "</a></td><td "; |
| int parsePos = -1; |
| do { |
| parsePos = content.indexOf(marker, parsePos < 0 ? 0 : parsePos); |
| if (parsePos > 0) { |
| int beginPos = content.lastIndexOf('>', parsePos - 1); |
| if (beginPos < 0) |
| beginPos = 0; |
| |
| fileList.add((content.substring(beginPos + 1, parsePos))); |
| parsePos += marker.length(); |
| } else { |
| break; |
| } |
| } while (parsePos > 0); |
| return fileList.toArray(new String[0]); |
| } |
| |
| public String composeDatastoreBrowseUrl(String dcName, String fullPath) { |
| DatastoreFile dsFile = new DatastoreFile(fullPath); |
| return composeDatastoreBrowseUrl(dcName, dsFile.getDatastoreName(), dsFile.getRelativePath()); |
| } |
| |
| public String composeDatastoreBrowseUrl(String dcName, String datastoreName, String relativePath) { |
| assert (relativePath != null); |
| assert (datastoreName != null); |
| |
| StringBuffer sb = new StringBuffer(); |
| sb.append("https://"); |
| sb.append(_serverAddress); |
| sb.append("/folder/"); |
| try { |
| sb.append(URLEncoder.encode(relativePath, "UTF-8")); |
| sb.append("?dcPath=").append(URLEncoder.encode(dcName, "UTF-8")); |
| sb.append("&dsName=").append(URLEncoder.encode(datastoreName, "UTF-8")); |
| } catch (UnsupportedEncodingException e) { |
| s_logger.error(String.format("Unable to encode URL. relativePath : %s, dcPath : %s, dsName : %s", relativePath, dcName, datastoreName), e); |
| } |
| return sb.toString(); |
| } |
| |
| public HttpURLConnection getHTTPConnection(String urlString) throws Exception { |
| return getHTTPConnection(urlString, "GET"); |
| } |
| |
| public HttpURLConnection getHTTPConnection(String urlString, String httpMethod) throws Exception { |
| String cookie = _vimClient.getServiceCookie(); |
| if (cookie == null) { |
| s_logger.error("No cookie is found in vmware web service request context!"); |
| throw new Exception("No cookie is found in vmware web service request context!"); |
| } |
| URL url = new URL(urlString); |
| HttpURLConnection conn = (HttpURLConnection)url.openConnection(); |
| |
| conn.setDoInput(true); |
| conn.setDoOutput(true); |
| conn.setAllowUserInteraction(true); |
| conn.addRequestProperty("Cookie", cookie); |
| conn.setRequestMethod(httpMethod); |
| connectWithRetry(conn); |
| return conn; |
| } |
| |
| public HttpURLConnection getRawHTTPConnection(String urlString) throws Exception { |
| URL url = new URL(urlString); |
| return (HttpURLConnection)url.openConnection(); |
| } |
| |
| private static void connectWithRetry(HttpURLConnection conn) throws Exception { |
| boolean connected = false; |
| for (int i = 0; i < MAX_CONNECT_RETRY && !connected; i++) { |
| try { |
| conn.connect(); |
| connected = true; |
| s_logger.info("Connected, conn: " + conn.toString() + ", retry: " + i); |
| } catch (Exception e) { |
| s_logger.warn("Unable to connect, conn: " + conn.toString() + ", message: " + e.toString() + ", retry: " + i); |
| |
| try { |
| Thread.sleep(CONNECT_RETRY_INTERVAL); |
| } catch (InterruptedException ex) { |
| s_logger.debug("[ignored] interrupted while connecting."); |
| } |
| } |
| } |
| |
| if (!connected) |
| throw new Exception("Unable to connect to " + conn.toString()); |
| } |
| |
| public void close() { |
| clearStockObjects(); |
| try { |
| s_logger.info("Disconnecting VMware session"); |
| _vimClient.disconnect(); |
| } catch(SOAPFaultException sfe) { |
| s_logger.debug("Tried to disconnect a session that is no longer valid"); |
| } catch (Exception e) { |
| s_logger.warn("Unexpected exception: ", e); |
| } finally { |
| if (_pool != null) { |
| _pool.unregisterContext(this); |
| } |
| unregisterOutstandingContext(); |
| } |
| } |
| |
| public static class TrustAllManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { |
| @Override |
| public java.security.cert.X509Certificate[] getAcceptedIssuers() { |
| return null; |
| } |
| |
| public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) { |
| return true; |
| } |
| |
| public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) { |
| return true; |
| } |
| |
| @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; |
| } |
| } |
| } |