package hudson.plugins.ec2; import hudson.Extension; import hudson.plugins.ec2.one.OneEC2Cloud; import hudson.plugins.ec2.one.OneSlaveTemplate; import hudson.util.FormValidation; import hudson.util.IOException2; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.security.GeneralSecurityException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.List; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.ServletException; import org.dom4j.Document; import org.dom4j.Element; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; /** * The original implementation of {@link EC2Cloud}. * * @author Kohsuke Kawaguchi */ public class OpenNebula extends OneEC2Cloud { private transient Metadata metadata; // Used when running unit tests public static boolean testMode; public final URL url; @DataBoundConstructor public OpenNebula(final String url, final String accessId, final String secretKey, final String privateKey, final String instanceCapStr, final List templates) throws MalformedURLException { this(new URL(url), accessId, secretKey, privateKey, instanceCapStr, templates); } @DataBoundConstructor public OpenNebula(final URL url, final String accessId, final String secretKey, final String privateKey, final String instanceCapStr, final List templates) { super("one-", accessId, secretKey, privateKey, instanceCapStr, templates); this.url = url; } private Metadata getMetadata() throws IOException { if (metadata == null) { metadata = new Metadata(url); } return metadata; } @Override public URL getEc2EndpointUrl() throws IOException { return getMetadata().ec2endpoint; } @Override public URL getS3EndpointUrl() throws IOException { return getMetadata().s3endpoint; } @Extension public static class DescriptorImpl extends OneEC2Cloud.DescriptorImpl { @Override public String getDisplayName() { return "OpenNebula"; } @Override public FormValidation doTestConnection( @QueryParameter final URL url, @QueryParameter final String accessId, @QueryParameter final String secretKey, @QueryParameter final String privateKey) throws IOException, ServletException { return super.doTestConnection(new Metadata(url).ec2endpoint, accessId, secretKey, privateKey); } } /** * OpenNebula service endpoint metadata. */ static class Metadata { final URL ec2endpoint, s3endpoint; Metadata(final URL oneUrl) throws IOException { // InputStream is = readMetadata(oneUrl); ec2endpoint = getUrl(oneUrl); s3endpoint = getUrl(oneUrl); } /** * @param oneUrl * @return * @throws MalformedURLException */ private URL getUrl(final URL oneUrl) throws MalformedURLException { return (null != oneUrl) ? oneUrl : new URL( "http://opennebula:4568"); } /** * @param oneUrl * @param metadataUrl * @throws IOException * @throws NoSuchAlgorithmException * @throws KeyManagementException */ private InputStream readMetadata(final URL url) throws IOException, NoSuchAlgorithmException, KeyManagementException { InputStream is = null; URL metadataUrl = new URL(getUrl(url), "/"); try { if (getUrl(url).getProtocol().equals("https")) { HttpsURLConnection con = (HttpsURLConnection) getUrl(metadataUrl) .openConnection(); makeIgnoreCertificate(con); is = con.getInputStream(); } else { URLConnection con = getUrl(metadataUrl).openConnection(); is = con.getInputStream(); } } catch (IOException e) { throw new IOException2( "Failed to parse OpenNebula metadata at " + getUrl(metadataUrl), e); } catch (GeneralSecurityException e) { throw new IOException2( "Failed to parse OpenNebula metadata at " + getUrl(metadataUrl), e); } return is; } /** * Configures the given {@link HttpsURLConnection} so that it'll ignore * all the HTTPS certificate checks, as typical Eucalyptus * implementation doesn't come with a valid certificate. */ private void makeIgnoreCertificate(final HttpsURLConnection con) throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance("SSL"); TrustManager[] tma = {new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( final X509Certificate[] certs, final String authType) { } public void checkServerTrusted( final X509Certificate[] certs, final String authType) { } } }; sc.init(null, tma, null); con.setSSLSocketFactory(sc.getSocketFactory()); con.setHostnameVerifier(new HostnameVerifier() { public boolean verify(final String s, final SSLSession sslSession) { return true; // everything goes } }); } @Deprecated private URL readURLFromMetadata(final Document metadata, final String serviceName) throws MalformedURLException { Element e = (Element) metadata .selectSingleNode("//Service[Name/text()='" + serviceName + "']/EndpointUrl"); if (e == null) { throw new IllegalStateException( "Service metadata didn't contain " + serviceName); } return new URL(e.getTextTrim()); } } }