Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: jenkinsci/ec2-plugin
base: master
...
head fork: jenkinsci/ec2-plugin
compare: svn
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 49 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 20, 2011
kohsuke moving to GitHub 364f6aa
Showing with 1 addition and 2,420 deletions.
  1. +1 −0  README.TXT
  2. +0 −2  TODO.txt
  3. +0 −58 pom.xml
  4. +0 −67 src/main/java/hudson/plugins/ec2/AmazonEC2Cloud.java
  5. +0 −50 src/main/java/hudson/plugins/ec2/AwsRegion.java
  6. +0 −485 src/main/java/hudson/plugins/ec2/EC2Cloud.java
  7. +0 −108 src/main/java/hudson/plugins/ec2/EC2Computer.java
  8. +0 −61 src/main/java/hudson/plugins/ec2/EC2ComputerLauncher.java
  9. +0 −115 src/main/java/hudson/plugins/ec2/EC2PrivateKey.java
  10. +0 −51 src/main/java/hudson/plugins/ec2/EC2RetentionStrategy.java
  11. +0 −128 src/main/java/hudson/plugins/ec2/EC2Slave.java
  12. +0 −187 src/main/java/hudson/plugins/ec2/Eucalyptus.java
  13. +0 −21 src/main/java/hudson/plugins/ec2/InstanceState.java
  14. +0 −47 src/main/java/hudson/plugins/ec2/PluginImpl.java
  15. +0 −204 src/main/java/hudson/plugins/ec2/SlaveTemplate.java
  16. +0 −26 src/main/java/hudson/plugins/ec2/ebs/ZPoolExpandNotice.java
  17. +0 −65 src/main/java/hudson/plugins/ec2/ebs/ZPoolMonitor.java
  18. +0 −9 src/main/java/hudson/plugins/ec2/ebs/package-info.java
  19. +0 −208 src/main/java/hudson/plugins/ec2/ssh/EC2UnixLauncher.java
  20. +0 −55 src/main/java/hudson/plugins/ec2/ssh/HostKeyVerifierImpl.java
  21. +0 −21 src/main/resources/hudson/plugins/ec2/AmazonEC2Cloud/config-entries.jelly
  22. +0 −6 src/main/resources/hudson/plugins/ec2/AmazonEC2Cloud/help-region.html
  23. +0 −26 src/main/resources/hudson/plugins/ec2/EC2Cloud/computerSet.jelly
  24. +0 −1  src/main/resources/hudson/plugins/ec2/EC2Cloud/computerSet.properties
  25. +0 −52 src/main/resources/hudson/plugins/ec2/EC2Cloud/config.jelly
  26. +0 −6 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-accessId.html
  27. +0 −10 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-ec2EndpointUrl.html
  28. +0 −15 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-instanceCapStr.html
  29. +0 −1  src/main/resources/hudson/plugins/ec2/EC2Cloud/help-jvmopts.html
  30. +0 −12 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-privateKey.html
  31. +0 −8 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-remoteAdmin.html
  32. +0 −6 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-rootCommandPrefix.html
  33. +0 −10 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-s3EndpointUrl.html
  34. +0 −7 src/main/resources/hudson/plugins/ec2/EC2Cloud/help-userData.html
  35. +0 −78 src/main/resources/hudson/plugins/ec2/EC2Computer/configure.jelly
  36. +0 −4 src/main/resources/hudson/plugins/ec2/EC2Slave/help-initScript.html
  37. +0 −3  src/main/resources/hudson/plugins/ec2/EC2Slave/help-numExecutors.html
  38. +0 −8 src/main/resources/hudson/plugins/ec2/EC2Slave/help-remoteAdmin.html
  39. +0 −6 src/main/resources/hudson/plugins/ec2/EC2Slave/help-rootCommandPrefix.html
  40. +0 −21 src/main/resources/hudson/plugins/ec2/Eucalyptus/config-entries.jelly
  41. +0 −4 src/main/resources/hudson/plugins/ec2/Eucalyptus/help-url.html
  42. +0 −7 src/main/resources/hudson/plugins/ec2/Messages.properties
  43. +0 −40 src/main/resources/hudson/plugins/ec2/ebs/ZPoolExpandNotice/index.jelly
  44. +0 −33 src/main/resources/hudson/plugins/ec2/ebs/ZPoolExpandNotice/message.jelly
  45. +0 −5 src/main/resources/index.jelly
  46. +0 −3  src/main/webapp/help/instanceType.html
  47. +0 −18 src/test/java/hudson/plugins/ec2/AmazonEC2CloudTest.java
  48. +0 −37 src/test/java/hudson/plugins/ec2/EC2PrivateKeyTest.java
  49. +0 −25 src/test/java/hudson/plugins/ec2/SlaveTemplateTest.java
View
1  README.TXT
@@ -0,0 +1 @@
+sources are in git https://github.com/hudson/ec2-plugin
View
2  TODO.txt
@@ -1,2 +0,0 @@
-- the uptime should be displayed there
-- cloud configuration page should be moved elsewhere, like how we configure slaves
View
58 pom.xml
@@ -1,58 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.jvnet.hudson.plugins</groupId>
- <artifactId>plugin</artifactId>
- <version>1.346</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>ec2</artifactId>
- <version>1.11-SNAPSHOT</version>
- <packaging>hpi</packaging>
- <name>Hudson Amazon EC2 plugin</name>
- <url>http://wiki.hudson-ci.org/display/HUDSON/Amazon+EC2+Plugin</url>
-
- <dependencies>
- <dependency>
- <groupId>net.java.dev.jets3t</groupId>
- <artifactId>jets3t</artifactId>
- <version>0.7.2</version>
- <exclusions>
- <!-- they come from core -->
- <exclusion>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <!-- we only use this to handle key fingerprint. should be able to replace this with trilead -->
- <groupId>bouncycastle</groupId>
- <artifactId>bcprov-jdk15</artifactId>
- <version>135</version>
- </dependency>
- <dependency>
- <groupId>com.google.code.typica</groupId>
- <artifactId>typica</artifactId>
- <version>1.6</version>
- </dependency>
- </dependencies>
-
- <developers>
- <developer>
- <id>kohsuke</id>
- <name>Kohsuke Kawaguchi</name>
- <email>kohsuke@infradna.com</email>
- </developer>
- </developers>
-
-</project>
-
-
-
View
67 src/main/java/hudson/plugins/ec2/AmazonEC2Cloud.java
@@ -1,67 +0,0 @@
-package hudson.plugins.ec2;
-
-import hudson.Extension;
-import hudson.util.FormValidation;
-import org.kohsuke.stapler.DataBoundConstructor;
-import org.kohsuke.stapler.QueryParameter;
-import org.kohsuke.stapler.StaplerResponse;
-
-import javax.servlet.ServletException;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-/**
- * The original implementation of {@link EC2Cloud}.
- *
- * @author Kohsuke Kawaguchi
- */
-public class AmazonEC2Cloud extends EC2Cloud {
- /**
- * Represents the region. Can be null for backward compatibility reasons.
- */
- private AwsRegion region;
-
- @DataBoundConstructor
- public AmazonEC2Cloud(AwsRegion region, String accessId, String secretKey, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) {
- super("ec2-"+region.name(), accessId, secretKey, privateKey, instanceCapStr, templates);
- this.region = region;
- }
-
- public AwsRegion getRegion() {
- if (region==null)
- region = AwsRegion.US_EAST_1; // backward data compatibility with earlier versions
- return region;
- }
-
- @Override
- public URL getEc2EndpointUrl() {
- return getRegion().ec2Endpoint;
- }
-
- @Override
- public URL getS3EndpointUrl() {
- return getRegion().s3Endpoint;
- }
-
- @Extension
- public static class DescriptorImpl extends EC2Cloud.DescriptorImpl {
- public String getDisplayName() {
- return "Amazon EC2";
- }
-
- public FormValidation doTestConnection(
- @QueryParameter AwsRegion region,
- @QueryParameter String accessId,
- @QueryParameter String secretKey,
- @QueryParameter String privateKey) throws IOException, ServletException {
- return super.doTestConnection(region.ec2Endpoint,accessId,secretKey,privateKey);
- }
-
- public FormValidation doGenerateKey(
- StaplerResponse rsp, @QueryParameter AwsRegion region, @QueryParameter String accessId, @QueryParameter String secretKey) throws IOException, ServletException {
- return super.doGenerateKey(rsp,region.ec2Endpoint,accessId,secretKey);
- }
- }
-}
View
50 src/main/java/hudson/plugins/ec2/AwsRegion.java
@@ -1,50 +0,0 @@
-package hudson.plugins.ec2;
-
-import org.jvnet.localizer.Localizable;
-import org.kohsuke.stapler.Stapler;
-
-import hudson.model.Node.Mode;
-import hudson.util.EnumConverter;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Locale;
-
-/**
- * Represents Amazon EC2 regions.
- *
- * @author Kohsuke Kawaguchi
- */
-public enum AwsRegion {
- US_EAST_1(Messages._AwsRegion_UsEast()),
- US_WEST_1(Messages._AwsRegion_UsWest()),
- EU_WEST_1(Messages._AwsRegion_EuWest()),
- AP_SOUTHEAST_1(Messages._AwsRegion_ApSouthEast());
-
- public final URL ec2Endpoint,s3Endpoint;
-
- /**
- * Localized human readable description of this region in a few words.
- */
- public final Localizable displayName;
-
- AwsRegion(Localizable displayName) {
- try {
- String host = name().toLowerCase(Locale.ENGLISH).replace('_','-');
- ec2Endpoint = new URL("https://"+host+".ec2.amazonaws.com/");
- s3Endpoint = new URL("https://"+host+".s3.amazonaws.com/");
- this.displayName = displayName;
- } catch (MalformedURLException e) {
- throw new Error(e); // impossible
- }
- }
-
- @Override
- public String toString() {
- return displayName.toString();
- }
-
- static {
- Stapler.CONVERT_UTILS.register(new EnumConverter(), AwsRegion.class);
- }
-}
View
485 src/main/java/hudson/plugins/ec2/EC2Cloud.java
@@ -1,485 +0,0 @@
-package hudson.plugins.ec2;
-
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.InstanceType;
-import com.xerox.amazonws.ec2.Jec2;
-import com.xerox.amazonws.ec2.KeyPairInfo;
-import com.xerox.amazonws.ec2.ReservationDescription;
-import com.xerox.amazonws.ec2.ReservationDescription.Instance;
-import hudson.model.Computer;
-import hudson.model.Descriptor;
-import hudson.model.Hudson;
-import hudson.model.Label;
-import hudson.model.Node;
-import hudson.slaves.Cloud;
-import hudson.slaves.NodeProvisioner.PlannedNode;
-import hudson.util.FormValidation;
-import hudson.util.Secret;
-import hudson.util.StreamTaskListener;
-import java.net.MalformedURLException;
-
-import org.jets3t.service.Constants;
-import org.jets3t.service.S3Service;
-import org.jets3t.service.S3ServiceException;
-import org.jets3t.service.impl.rest.httpclient.RestS3Service;
-import org.jets3t.service.security.AWSCredentials;
-import org.jets3t.service.utils.ServiceUtils;
-import org.kohsuke.stapler.QueryParameter;
-import org.kohsuke.stapler.StaplerRequest;
-import org.kohsuke.stapler.StaplerResponse;
-
-import javax.servlet.ServletException;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.logging.Logger;
-
-import org.jets3t.service.Jets3tProperties;
-import static java.util.logging.Level.WARNING;
-
-/**
- * Hudson's view of EC2.
- *
- * @author Kohsuke Kawaguchi
- */
-public abstract class EC2Cloud extends Cloud {
-
- private final String accessId;
- private final Secret secretKey;
- private final EC2PrivateKey privateKey;
-
- /**
- * Upper bound on how many instances we may provision.
- */
- public final int instanceCap;
- private final List<SlaveTemplate> templates;
- private transient KeyPairInfo usableKeyPair;
-
- protected EC2Cloud(String id, String accessId, String secretKey, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) {
- super(id);
- this.accessId = accessId.trim();
- this.secretKey = Secret.fromString(secretKey.trim());
- this.privateKey = new EC2PrivateKey(privateKey);
- if(instanceCapStr.equals(""))
- this.instanceCap = Integer.MAX_VALUE;
- else
- this.instanceCap = Integer.parseInt(instanceCapStr);
- if(templates==null) templates=Collections.emptyList();
- this.templates = templates;
- readResolve(); // set parents
- }
-
- public abstract URL getEc2EndpointUrl() throws IOException;
- public abstract URL getS3EndpointUrl() throws IOException;
-
- protected Object readResolve() {
- for (SlaveTemplate t : templates)
- t.parent = this;
- return this;
- }
-
- public String getAccessId() {
- return accessId;
- }
-
- public String getSecretKey() {
- return secretKey.getEncryptedValue();
- }
-
- public EC2PrivateKey getPrivateKey() {
- return privateKey;
- }
-
- public String getInstanceCapStr() {
- if(instanceCap==Integer.MAX_VALUE)
- return "";
- else
- return String.valueOf(instanceCap);
- }
-
- public List<SlaveTemplate> getTemplates() {
- return Collections.unmodifiableList(templates);
- }
-
- public SlaveTemplate getTemplate(String ami) {
- for (SlaveTemplate t : templates)
- if(t.ami.equals(ami))
- return t;
- return null;
- }
-
- /**
- * Gets {@link SlaveTemplate} that has the matching {@link Label}.
- */
- public SlaveTemplate getTemplate(Label label) {
- for (SlaveTemplate t : templates)
- if(t.containsLabel(label))
- return t;
- return null;
- }
-
- /**
- * Gets the {@link KeyPairInfo} used for the launch.
- */
- public synchronized KeyPairInfo getKeyPair() throws EC2Exception, IOException {
- if(usableKeyPair==null)
- usableKeyPair = privateKey.find(connect());
- return usableKeyPair;
- }
-
- /**
- * Counts the number of instances in EC2 currently running.
- *
- * <p>
- * This includes those instances that may be started outside Hudson.
- */
- public int countCurrentEC2Slaves() throws EC2Exception {
- int n=0;
- for (ReservationDescription r : connect().describeInstances(Collections.<String>emptyList())) {
- for (Instance i : r.getInstances()) {
- if(!i.isTerminated())
- n++;
- }
- }
- return n;
- }
-
- /**
- * Debug command to attach to a running instance.
- */
- public void doAttach(StaplerRequest req, StaplerResponse rsp, @QueryParameter String id) throws ServletException, IOException, EC2Exception {
- checkPermission(PROVISION);
- SlaveTemplate t = getTemplates().get(0);
-
- StringWriter sw = new StringWriter();
- StreamTaskListener listener = new StreamTaskListener(sw);
- EC2Slave node = t.attach(id,listener);
- Hudson.getInstance().addNode(node);
-
- rsp.sendRedirect2(req.getContextPath()+"/computer/"+node.getNodeName());
- }
-
- public void doProvision(StaplerRequest req, StaplerResponse rsp, @QueryParameter String ami) throws ServletException, IOException {
- checkPermission(PROVISION);
- if(ami==null) {
- sendError("The 'ami' query parameter is missing",req,rsp);
- return;
- }
- SlaveTemplate t = getTemplate(ami);
- if(t==null) {
- sendError("No such AMI: "+ami,req,rsp);
- return;
- }
-
- StringWriter sw = new StringWriter();
- StreamTaskListener listener = new StreamTaskListener(sw);
- try {
- EC2Slave node = t.provision(listener);
- Hudson.getInstance().addNode(node);
-
- rsp.sendRedirect2(req.getContextPath()+"/computer/"+node.getNodeName());
- } catch (EC2Exception e) {
- e.printStackTrace(listener.error(e.getMessage()));
- sendError(sw.toString(),req,rsp);
- }
- }
-
- public Collection<PlannedNode> provision(Label label, int excessWorkload) {
- try {
-
- final SlaveTemplate t = getTemplate(label);
-
- List<PlannedNode> r = new ArrayList<PlannedNode>();
- for( ; excessWorkload>0; excessWorkload-- ) {
- if(countCurrentEC2Slaves()>=instanceCap)
- break; // maxed out
-
- r.add(new PlannedNode(t.getDisplayName(),
- Computer.threadPoolForRemoting.submit(new Callable<Node>() {
- public Node call() throws Exception {
- // TODO: record the output somewhere
- EC2Slave s = t.provision(new StreamTaskListener(System.out));
- Hudson.getInstance().addNode(s);
- // EC2 instances may have a long init script. If we declare
- // the provisioning complete by returning without the connect
- // operation, NodeProvisioner may decide that it still wants
- // one more instance, because it sees that (1) all the slaves
- // are offline (because it's still being launched) and
- // (2) there's no capacity provisioned yet.
- //
- // deferring the completion of provisioning until the launch
- // goes successful prevents this problem.
- s.toComputer().connect(false).get();
- return s;
- }
- })
- ,t.getNumExecutors()));
- }
- return r;
- } catch (EC2Exception e) {
- LOGGER.log(WARNING,"Failed to count the # of live instances on EC2",e);
- return Collections.emptyList();
- }
- }
-
- public boolean canProvision(Label label) {
- return getTemplate(label)!=null;
- }
-
- /**
- * Gets the first {@link EC2Cloud} instance configured in the current Hudson, or null if no such thing exists.
- */
- public static EC2Cloud get() {
- return Hudson.getInstance().clouds.get(EC2Cloud.class);
- }
-
- /**
- * Connects to EC2 and returns {@link Jec2}, which can then be used to communicate with EC2.
- */
- public Jec2 connect() throws EC2Exception {
- try {
- return connect(accessId, secretKey, getEc2EndpointUrl());
- } catch (IOException e) {
- throw new EC2Exception("Failed to retrieve the endpoint",e);
- }
- }
-
- /***
- * Connect to an EC2 instance.
- * @return Jec2
- */
- public static Jec2 connect(String accessId, String secretKey, URL endpoint) {
- return connect(accessId, Secret.fromString(secretKey), endpoint);
- }
-
- /***
- * Connect to an EC2 instance.
- * @return Jec2
- */
- public static Jec2 connect(String accessId, Secret secretKey, URL endpoint) {
- int ec2Port = portFromURL(endpoint);
- boolean SSL = isSSL(endpoint);
- Jec2 result = new Jec2(accessId, secretKey.toString(), SSL, endpoint.getHost(), ec2Port);
- String path = endpoint.getPath();
- if (path.length() != 0) /* '/' is the default, not '' */
- result.setResourcePrefix(path);
- return result;
- }
-
- /***
- * Convert a configured hostname like 'us-east-1' to a FQDN or ip address
- */
- public static String convertHostName(String ec2HostName) {
- if (ec2HostName == null || ec2HostName.length()==0)
- ec2HostName = "us-east-1";
- if (!ec2HostName.contains("."))
- ec2HostName = ec2HostName + ".ec2.amazonaws.com";
- return ec2HostName;
- }
-
- /***
- * Convert a configured s3 endpoint to a FQDN or ip address
- */
- public static String convertS3HostName(String s3HostName) {
- if (s3HostName == null || s3HostName.length()==0)
- s3HostName = "s3";
- if (!s3HostName.contains("."))
- s3HostName = s3HostName + ".amazonaws.com";
- return s3HostName;
- }
-
- /***
- * Convert a user entered string into a port number
- * "" -> -1 to indicate default based on SSL setting
- */
- public static Integer convertPort(String ec2Port) {
- if (ec2Port == null || ec2Port.length() == 0)
- return -1;
- else
- return Integer.parseInt(ec2Port);
- }
-
- /**
- * Connects to S3 and returns {@link S3Service}.
- */
- public S3Service connectS3() throws S3ServiceException, IOException {
- URL s3 = getS3EndpointUrl();
-
- return new RestS3Service(new AWSCredentials(accessId,secretKey.toString()),
- null, null, buildJets3tProperties(s3));
- }
-
- /**
- * Builds the connection parameters for S3.
- */
- protected Jets3tProperties buildJets3tProperties(URL s3) {
- Jets3tProperties props = Jets3tProperties.getInstance(Constants.JETS3T_PROPERTIES_FILENAME);
- final String s3Host = s3.getHost();
- if (!s3Host.equals("s3.amazonaws.com"))
- props.setProperty("s3service.s3-endpoint", s3Host);
- int s3Port = portFromURL(s3);
- if (s3Port != -1)
- props.setProperty("s3service.s3-endpoint-http-port", String.valueOf(s3Port));
- if (s3.getPath().length() > 1)
- props.setProperty("s3service.s3-endpoint-virtual-path", s3.getPath());
- props.setProperty("s3service.https-only", String.valueOf(isSSL(s3)));
- return props;
- }
-
- /**
- * Computes the presigned URL for the given S3 resource.
- *
- * @param path
- * String like "/bucketName/folder/folder/abc.txt" that represents the resource to request.
- */
- public URL buildPresignedURL(String path) throws IOException, S3ServiceException {
- long expires = System.currentTimeMillis()/1000+60*60;
- String token = "GET\n\n\n" + expires + "\n" + path;
-
- String url = "http://s3.amazonaws.com"+path+"?AWSAccessKeyId="+accessId+"&Expires="+expires+"&Signature="+
- URLEncoder.encode(
- ServiceUtils.signWithHmacSha1(secretKey.toString(),token),"UTF-8");
- return new URL(url);
- }
-
- /* Parse a url or return a sensible error */
- public static URL checkEndPoint(String url) throws FormValidation {
- try {
- return new URL(url);
- } catch (MalformedURLException ex) {
- throw FormValidation.error("Endpoint URL is not a valid URL");
- }
- }
-
-
- public static abstract class DescriptorImpl extends Descriptor<Cloud> {
- public InstanceType[] getInstanceTypes() {
- return InstanceType.values();
- }
-
- /**
- * TODO: once 1.304 is released, revert to FormValidation.validateBase64
- */
- private FormValidation validateBase64(String value, boolean allowWhitespace, boolean allowEmpty, String errorMessage) {
- try {
- String v = value;
- if(!allowWhitespace) {
- if(v.indexOf(' ')>=0 || v.indexOf('\n')>=0)
- return FormValidation.error(errorMessage);
- }
- v=v.trim();
- if(!allowEmpty && v.length()==0)
- return FormValidation.error(errorMessage);
-
- com.trilead.ssh2.crypto.Base64.decode(v.toCharArray());
- return FormValidation.ok();
- } catch (IOException e) {
- return FormValidation.error(errorMessage);
- }
- }
-
- public FormValidation doCheckAccessId(@QueryParameter String value) throws IOException, ServletException {
- return validateBase64(value,false,false,Messages.EC2Cloud_InvalidAccessId());
- }
-
- public FormValidation doCheckSecretKey(@QueryParameter String value) throws IOException, ServletException {
- return validateBase64(value,false,false,Messages.EC2Cloud_InvalidSecretKey());
- }
-
- public FormValidation doCheckPrivateKey(@QueryParameter String value) throws IOException, ServletException {
- boolean hasStart=false,hasEnd=false;
- BufferedReader br = new BufferedReader(new StringReader(value));
- String line;
- while ((line = br.readLine()) != null) {
- if (line.equals("-----BEGIN RSA PRIVATE KEY-----"))
- hasStart=true;
- if (line.equals("-----END RSA PRIVATE KEY-----"))
- hasEnd=true;
- }
- if(!hasStart)
- return FormValidation.error("This doesn't look like a private key at all");
- if(!hasEnd)
- return FormValidation.error("The private key is missing the trailing 'END RSA PRIVATE KEY' marker. Copy&paste error?");
- return FormValidation.ok();
- }
-
- protected FormValidation doTestConnection( URL ec2endpoint,
- String accessId, String secretKey, String privateKey) throws IOException, ServletException {
- try {
- Jec2 jec2 = connect(accessId, secretKey, ec2endpoint);
- jec2.describeInstances(Collections.<String>emptyList());
-
- if(accessId==null)
- return FormValidation.error("Access ID is not specified");
- if(secretKey==null)
- return FormValidation.error("Secret key is not specified");
- if(privateKey==null)
- return FormValidation.error("Private key is not specified. Click 'Generate Key' to generate one.");
-
- if(privateKey.trim().length()>0) {
- // check if this key exists
- EC2PrivateKey pk = new EC2PrivateKey(privateKey);
- if(pk.find(jec2)==null)
- return FormValidation.error("The private key entered below isn't registered to EC2 (fingerprint is "+pk.getFingerprint()+")");
- }
-
- return FormValidation.ok(Messages.EC2Cloud_Success());
- } catch (EC2Exception e) {
- LOGGER.log(WARNING, "Failed to check EC2 credential",e);
- return FormValidation.error(e.getMessage());
- }
- }
-
- public FormValidation doGenerateKey(StaplerResponse rsp, URL ec2EndpointUrl, String accessId, String secretKey
- ) throws IOException, ServletException {
- try {
- Jec2 jec2 = connect(accessId, secretKey, ec2EndpointUrl);
- List<KeyPairInfo> existingKeys = jec2.describeKeyPairs(Collections.<String>emptyList());
-
- int n = 0;
- while(true) {
- boolean found = false;
- for (KeyPairInfo k : existingKeys) {
- if(k.getKeyName().equals("hudson-"+n))
- found=true;
- }
- if(!found)
- break;
- n++;
- }
-
- KeyPairInfo key = jec2.createKeyPair("hudson-" + n);
-
-
- rsp.addHeader("script","findPreviousFormItem(button,'privateKey').value='"+key.getKeyMaterial().replace("\n","\\n")+"'");
-
- return FormValidation.ok(Messages.EC2Cloud_Success());
- } catch (EC2Exception e) {
- LOGGER.log(WARNING, "Failed to check EC2 credential",e);
- return FormValidation.error(e.getMessage());
- }
- }
- }
-
- private static final Logger LOGGER = Logger.getLogger(EC2Cloud.class.getName());
-
- private static boolean isSSL(URL endpoint) {
- return endpoint.getProtocol().equals("https");
- }
-
- private static int portFromURL(URL endpoint) {
- int ec2Port = endpoint.getPort();
- if (ec2Port == -1) {
- ec2Port = endpoint.getDefaultPort();
- }
- return ec2Port;
- }
-}
View
108 src/main/java/hudson/plugins/ec2/EC2Computer.java
@@ -1,108 +0,0 @@
-package hudson.plugins.ec2;
-
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.Jec2;
-import com.xerox.amazonws.ec2.ReservationDescription;
-import com.xerox.amazonws.ec2.ReservationDescription.Instance;
-import hudson.Util;
-import hudson.slaves.SlaveComputer;
-import org.kohsuke.stapler.HttpRedirect;
-import org.kohsuke.stapler.HttpResponse;
-import org.kohsuke.stapler.StaplerResponse;
-
-import java.io.IOException;
-import java.util.Collections;
-
-/**
- * @author Kohsuke Kawaguchi
- */
-public class EC2Computer extends SlaveComputer {
- /**
- * Cached description of this EC2 instance. Lazily fetched.
- */
- private volatile Instance ec2InstanceDescription;
-
- public EC2Computer(EC2Slave slave) {
- super(slave);
- }
-
- @Override
- public EC2Slave getNode() {
- return (EC2Slave)super.getNode();
- }
-
- public String getInstanceId() {
- return getName();
- }
-
- /**
- * Gets the EC2 console output.
- */
- public String getConsoleOutput() throws EC2Exception {
- Jec2 ec2 = EC2Cloud.get().connect();
- return ec2.getConsoleOutput(getInstanceId()).getOutput();
- }
-
- /**
- * Obtains the instance state description in EC2.
- *
- * <p>
- * This method returns a cached state, so it's not suitable to check {@link Instance#getState()}
- * and {@link Instance#getStateCode()} from the returned instance (but all the other fields are valid as it won't change.)
- */
- public Instance describeInstance() throws EC2Exception {
- if(ec2InstanceDescription==null)
- ec2InstanceDescription = _describeInstance();
- return ec2InstanceDescription;
- }
-
- /**
- * Gets the current state of the instance.
- *
- * <p>
- * Unlike {@link #describeInstance()}, this method always return the current status by calling EC2.
- */
- public InstanceState getState() throws EC2Exception {
- ec2InstanceDescription=_describeInstance();
- return InstanceState.find(ec2InstanceDescription.getState());
- }
-
- /**
- * Number of milli-secs since the instance was started.
- */
- public long getUptime() throws EC2Exception {
- return System.currentTimeMillis()-describeInstance().getLaunchTime().getTimeInMillis();
- }
-
- /**
- * Returns uptime in the human readable form.
- */
- public String getUptimeString() throws EC2Exception {
- return Util.getTimeSpanString(getUptime());
- }
-
- private ReservationDescription.Instance _describeInstance() throws EC2Exception {
- return EC2Cloud.get().connect().describeInstances(Collections.<String>singletonList(getNode().getInstanceId())).get(0).getInstances().get(0);
- }
-
- /**
- * When the slave is deleted, terminate the instance.
- */
- @Override
- public HttpResponse doDoDelete() throws IOException {
- checkPermission(DELETE);
- getNode().terminate();
- return new HttpRedirect("..");
- }
-
- /** What username to use to run root-like commands
- *
- */
- public String getRemoteAdmin() {
- return getNode().getRemoteAdmin();
- }
-
- public String getRootCommandPrefix() {
- return getNode().getRootCommandPrefix();
- }
-}
View
61 src/main/java/hudson/plugins/ec2/EC2ComputerLauncher.java
@@ -1,61 +0,0 @@
-package hudson.plugins.ec2;
-
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.ReservationDescription.Instance;
-import hudson.model.TaskListener;
-import hudson.slaves.ComputerLauncher;
-import hudson.slaves.SlaveComputer;
-
-import java.io.IOException;
-import java.io.PrintStream;
-
-import org.jets3t.service.S3ServiceException;
-
-/**
- * {@link ComputerLauncher} for EC2 that waits for the instance to really come up before proceeding to
- * the real user-specified {@link ComputerLauncher}.
- *
- * @author Kohsuke Kawaguchi
- */
-public abstract class EC2ComputerLauncher extends ComputerLauncher {
- @Override
- public void launch(SlaveComputer _computer, TaskListener listener) {
- try {
- EC2Computer computer = (EC2Computer)_computer;
- PrintStream logger = listener.getLogger();
-
- OUTER:
- while(true) {
- switch (computer.getState()) {
- case PENDING:
- Thread.sleep(5000); // check every 5 secs
- continue OUTER;
- case RUNNING:
- break OUTER;
- case SHUTTING_DOWN:
- case TERMINATED:
- // abort
- logger.println("The instance "+computer.getInstanceId()+" appears to be shut down. Aborting launch.");
- return;
- }
- }
-
- launch(computer, logger, computer.describeInstance());
- } catch (EC2Exception e) {
- e.printStackTrace(listener.error(e.getMessage()));
- } catch (IOException e) {
- e.printStackTrace(listener.error(e.getMessage()));
- } catch (InterruptedException e) {
- e.printStackTrace(listener.error(e.getMessage()));
- } catch (S3ServiceException e) {
- e.printStackTrace(listener.error(e.getMessage()));
- }
-
- }
-
- /**
- * Stage 2 of the launch. Called after the EC2 instance comes up.
- */
- protected abstract void launch(EC2Computer computer, PrintStream logger, Instance inst)
- throws EC2Exception, IOException, InterruptedException, S3ServiceException;
-}
View
115 src/main/java/hudson/plugins/ec2/EC2PrivateKey.java
@@ -1,115 +0,0 @@
-package hudson.plugins.ec2;
-
-import hudson.util.Secret;
-import org.apache.commons.codec.binary.Hex;
-import org.bouncycastle.openssl.PEMReader;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.security.DigestInputStream;
-import java.security.KeyPair;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.Security;
-
-import com.xerox.amazonws.ec2.KeyPairInfo;
-import com.xerox.amazonws.ec2.Jec2;
-import com.xerox.amazonws.ec2.EC2Exception;
-
-/**
- * RSA private key (the one that you generate with ec2-add-keypair.)
- *
- * Starts with "----- BEGIN RSA PRIVATE KEY------\n".
- *
- * @author Kohsuke Kawaguchi
- */
-final class EC2PrivateKey {
- private final Secret privateKey;
-
- EC2PrivateKey(String privateKey) {
- this.privateKey = Secret.fromString(privateKey.trim());
- }
-
- /**
- * Obtains the fingerprint of the key in the "ab:cd:ef:...:12" format.
- */
- /**
- * Obtains the fingerprint of the key in the "ab:cd:ef:...:12" format.
- */
- public String getFingerprint() throws IOException {
- Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
- Reader r = new BufferedReader(new StringReader(privateKey.toString()));
- PEMReader pem = new PEMReader(r);
- KeyPair pair = (KeyPair) pem.readObject();
- if(pair==null) return null;
- PrivateKey key = pair.getPrivate();
- return digest(key);
- }
-
- /**
- * Is this file really a private key?
- */
- public boolean isPrivateKey() throws IOException {
- BufferedReader br = new BufferedReader(new StringReader(privateKey.toString()));
- String line;
- while ((line = br.readLine()) != null) {
- if (line.equals("-----BEGIN RSA PRIVATE KEY-----"))
- return true;
- }
- return false;
- }
-
- /**
- * Finds the {@link KeyPairInfo} that corresponds to this key in EC2.
- */
- public KeyPairInfo find(Jec2 ec2) throws IOException, EC2Exception {
- String fp = getFingerprint();
- for(KeyPairInfo kp : ec2.describeKeyPairs(new String[0])) {
- if(kp.getKeyFingerprint().equalsIgnoreCase(fp))
- return new KeyPairInfo(kp.getKeyName(),fp,privateKey.toString());
- }
- return null;
- }
-
- @Override
- public int hashCode() {
- return privateKey.hashCode();
- }
-
- @Override
- public boolean equals(Object that) {
- return that instanceof EC2PrivateKey && this.privateKey.equals(((EC2PrivateKey)that).privateKey);
- }
-
- @Override
- public String toString() {
- return privateKey.toString();
- }
-
- /*package*/ static String digest(PrivateKey k) throws IOException {
- try {
- MessageDigest md5 = MessageDigest.getInstance("SHA1");
-
- DigestInputStream in = new DigestInputStream(new ByteArrayInputStream(k.getEncoded()), md5);
- try {
- while (in.read(new byte[128]) > 0)
- ; // simply discard the input
- } finally {
- in.close();
- }
- StringBuilder buf = new StringBuilder();
- char[] hex = Hex.encodeHex(md5.digest());
- for( int i=0; i<hex.length; i+=2 ) {
- if(buf.length()>0) buf.append(':');
- buf.append(hex,i,2);
- }
- return buf.toString();
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- }
- }
-}
View
51 src/main/java/hudson/plugins/ec2/EC2RetentionStrategy.java
@@ -1,51 +0,0 @@
-package hudson.plugins.ec2;
-
-import hudson.model.Descriptor;
-import hudson.slaves.RetentionStrategy;
-import hudson.util.TimeUnit2;
-import org.kohsuke.stapler.DataBoundConstructor;
-
-import java.util.logging.Logger;
-
-/**
- * {@link RetentionStrategy} for EC2.
- *
- * @author Kohsuke Kawaguchi
- */
-public class EC2RetentionStrategy extends RetentionStrategy<EC2Computer> {
- @DataBoundConstructor
- public EC2RetentionStrategy() {
- }
-
- public synchronized long check(EC2Computer c) {
- if (c.isIdle() && !disabled) {
- // TODO: really think about the right strategy here
- final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds();
- if (idleMilliseconds > TimeUnit2.MINUTES.toMillis(30)) {
- LOGGER.info("Disconnecting "+c.getName());
- c.getNode().terminate();
- }
- }
- return 1;
- }
-
- /**
- * Try to connect to it ASAP.
- */
- @Override
- public void start(EC2Computer c) {
- c.connect(false);
- }
-
- // no registration since this retention strategy is used only for EC2 nodes that we provision automatically.
- // @Extension
- public static class DescriptorImpl extends Descriptor<RetentionStrategy<?>> {
- public String getDisplayName() {
- return "EC2";
- }
- }
-
- private static final Logger LOGGER = Logger.getLogger(EC2RetentionStrategy.class.getName());
-
- public static boolean disabled = Boolean.getBoolean(EC2RetentionStrategy.class.getName()+".disabled");
-}
View
128 src/main/java/hudson/plugins/ec2/EC2Slave.java
@@ -1,128 +0,0 @@
-package hudson.plugins.ec2;
-
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.InstanceType;
-import com.xerox.amazonws.ec2.Jec2;
-import hudson.model.Computer;
-import hudson.model.Descriptor.FormException;
-import hudson.model.Hudson;
-import hudson.model.Slave;
-import hudson.plugins.ec2.ssh.EC2UnixLauncher;
-import hudson.slaves.NodeProperty;
-import hudson.Extension;
-import hudson.Util;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.kohsuke.stapler.DataBoundConstructor;
-
-/**
- * Slave running on EC2.
- *
- * @author Kohsuke Kawaguchi
- */
-public final class EC2Slave extends Slave {
- /**
- * Comes from {@link SlaveTemplate#initScript}.
- */
- public final String initScript;
- public final String remoteAdmin; // e.g. 'ubuntu'
- public final String rootCommandPrefix; // e.g. 'sudo'
- public final String jvmopts; //e.g. -Xmx1g
-
- public EC2Slave(String instanceId, String description, String remoteFS, int numExecutors, String labelString, String initScript, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
- this(instanceId, description, remoteFS, numExecutors, Mode.NORMAL, labelString, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts);
- }
-
- @DataBoundConstructor
- public EC2Slave(String instanceId, String description, String remoteFS, int numExecutors, Mode mode, String labelString, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts) throws FormException, IOException {
- super(instanceId, description, remoteFS, numExecutors, mode, labelString, new EC2UnixLauncher(), new EC2RetentionStrategy(), nodeProperties);
- this.initScript = initScript;
- this.remoteAdmin = remoteAdmin;
- this.rootCommandPrefix = rootCommandPrefix;
- this.jvmopts = jvmopts;
- }
-
- /**
- * Constructor for debugging.
- */
- public EC2Slave(String instanceId) throws FormException, IOException {
- this(instanceId,"debug","/tmp/hudson",1, Mode.NORMAL, "debug", "", Collections.<NodeProperty<?>>emptyList(), null, null, null);
- }
-
- /**
- * See http://aws.amazon.com/ec2/instance-types/
- */
- /*package*/ static int toNumExecutors(InstanceType it) {
- switch (it) {
- case DEFAULT: return 1;
- case MEDIUM_HCPU: return 5;
- case LARGE: return 4;
- case XLARGE: return 8;
- case XLARGE_HCPU: return 20;
- default: throw new AssertionError();
- }
- }
-
- /**
- * EC2 instance ID.
- */
- public String getInstanceId() {
- return getNodeName();
- }
-
- @Override
- public Computer createComputer() {
- return new EC2Computer(this);
- }
-
- /**
- * Terminates the instance in EC2.
- */
- public void terminate() {
- try {
- Jec2 ec2 = EC2Cloud.get().connect();
- ec2.terminateInstances(Collections.singletonList(getInstanceId()));
- LOGGER.info("Terminated EC2 instance: "+getInstanceId());
- Hudson.getInstance().removeNode(this);
- } catch (EC2Exception e) {
- LOGGER.log(Level.WARNING,"Failed to terminate EC2 instance: "+getInstanceId(),e);
- } catch (IOException e) {
- LOGGER.log(Level.WARNING,"Failed to terminate EC2 instance: "+getInstanceId(),e);
- }
- }
-
- String getRemoteAdmin() {
- if (remoteAdmin == null || remoteAdmin.length() == 0)
- return "root";
- return remoteAdmin;
- }
-
- String getRootCommandPrefix() {
- if (rootCommandPrefix == null || rootCommandPrefix.length() == 0)
- return "";
- return rootCommandPrefix + " ";
- }
-
- String getJvmopts() {
- return Util.fixNull(jvmopts);
- }
-
- @Extension
- public static final class DescriptorImpl extends SlaveDescriptor {
- public String getDisplayName() {
- return "Amazon EC2";
- }
-
- @Override
- public boolean isInstantiable() {
- return false;
- }
- }
-
- private static final Logger LOGGER = Logger.getLogger(EC2Slave.class.getName());
-}
View
187 src/main/java/hudson/plugins/ec2/Eucalyptus.java
@@ -1,187 +0,0 @@
-package hudson.plugins.ec2;
-
-import hudson.Extension;
-import hudson.util.FormValidation;
-import hudson.util.IOException2;
-import org.dom4j.Document;
-import org.dom4j.DocumentException;
-import org.dom4j.Element;
-import org.dom4j.io.SAXReader;
-import org.jets3t.service.Jets3tProperties;
-import org.kohsuke.stapler.DataBoundConstructor;
-import org.kohsuke.stapler.QueryParameter;
-import org.kohsuke.stapler.StaplerResponse;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import javax.servlet.ServletException;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-
-/**
- * Eucalyptus.
- *
- * @author Kohsuke Kawaguchi
- */
-public class Eucalyptus extends EC2Cloud {
- private transient Metadata metadata;
-
- public final URL url;
-
- @DataBoundConstructor
- public Eucalyptus(URL url, String accessId, String secretKey, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) throws IOException {
- super("eucalyptus", 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;
- }
-
- @Override
- protected Jets3tProperties buildJets3tProperties(URL s3) {
- Jets3tProperties props = super.buildJets3tProperties(s3);
-
- /* For eucalyptus as of 1.6.0 */
- props.setProperty("s3service.disable-dns-buckets", "true");
-
- return props;
- }
-
- @Extension
- public static class DescriptorImpl extends EC2Cloud.DescriptorImpl {
- public String getDisplayName() {
- return "Eucalyptus";
- }
-
- public FormValidation doTestConnection(
- @QueryParameter URL url,
- @QueryParameter String accessId,
- @QueryParameter String secretKey,
- @QueryParameter String privateKey) throws IOException, ServletException {
- return super.doTestConnection(new Metadata(url).ec2endpoint,accessId,secretKey,privateKey);
- }
-
- public FormValidation doGenerateKey(
- StaplerResponse rsp, @QueryParameter URL url, @QueryParameter String accessId, @QueryParameter String secretKey) throws IOException, ServletException {
- return super.doGenerateKey(rsp, new Metadata(url).ec2endpoint, accessId,secretKey);
- }
- }
-
- /**
- * Eucalyptus service endpoint metadata.
- */
- static class Metadata {
- final URL ec2endpoint,s3endpoint;
-
- Metadata(URL eucalyptus) throws IOException {
- if (!eucalyptus.getProtocol().equals("https"))
- throw new IOException("Expecting an HTTPS URL but got "+eucalyptus);
- URL metadataUrl = new URL(eucalyptus, "/register");
- try {
- HttpsURLConnection con = (HttpsURLConnection)metadataUrl.openConnection();
- makeIgnoreCertificate(con);
- Document metadata = new SAXReader().read(con.getInputStream());
- /*
- Metadata, as of Eucalyptus 1.5.2, looks like this:
-
- <Signature>
- <SignedInfo>
- <SignatureMethod>http://www.w3.org/2001/04/xmldsig-more#hmac-sha256</SignatureMethod>
- </SignedInfo>
- <SignatureValue>62595777525d7dbba4b5f361b3e9041d3d37e92611684557e67e85a9222a3ffb </SignatureValue>
- <Object>
- <CloudSchema>
- <Services type="array">
- <Service>
- <Name>ec2</Name>
- <EndpointUrl>http://eucalyptus.hudson-slaves.sfbay.sun.com:8773/services/Eucalyptus</EndpointUrl>
- <Resources type="array">
- ...
- </Resources>
- </Service>
- <Service>
- <Name>s3</Name>
- <EndpointUrl>http://eucalyptus.hudson-slaves.sfbay.sun.com:8773/services/Walrus</EndpointUrl>
- <Resources type="array">
- ...
- </Resources>
- </Service>
- </Services>
- <id>a002c56e-b994-4ed8-956b-b30eda9b6153</id> <CloudType>eucalyptus</CloudType>
- <CloudVersion>1.5.2</CloudVersion>
- <SchemaVersion>1.0</SchemaVersion>
- <Description>Public cloud in the new cluster</Description>
- </CloudSchema>
-
- */
-
- this.ec2endpoint = readURLFromMetadata(metadata, "ec2");
- this.s3endpoint = readURLFromMetadata(metadata, "s3");
- } catch (DocumentException e) {
- throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
- } catch (IOException e) {
- throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
- } catch (GeneralSecurityException e) {
- throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
- }
- }
-
- /**
- * 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(HttpsURLConnection con) throws NoSuchAlgorithmException, KeyManagementException {
- SSLContext sc = SSLContext.getInstance("SSL");
- TrustManager[] tma = {new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(X509Certificate[] certs, String authType) {
- }
- }};
- sc.init(null, tma, null);
-
- con.setSSLSocketFactory(sc.getSocketFactory());
- con.setHostnameVerifier(new HostnameVerifier() {
- public boolean verify(String s, SSLSession sslSession) {
- return true; // everything goes
- }
- });
- }
-
- private URL readURLFromMetadata(Document metadata, 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());
- }
- }
-}
View
21 src/main/java/hudson/plugins/ec2/InstanceState.java
@@ -1,21 +0,0 @@
-package hudson.plugins.ec2;
-
-/**
- * Constants that represent the running state of EC2.
- *
- * @author Kohsuke Kawaguchi
- */
-public enum InstanceState {
- PENDING,
- RUNNING,
- SHUTTING_DOWN,
- TERMINATED;
-
- public String getCode() {
- return name().toLowerCase().replace('_','-');
- }
-
- public static InstanceState find(String name) {
- return Enum.valueOf(InstanceState.class,name.toUpperCase().replace('-','_'));
- }
-}
View
47 src/main/java/hudson/plugins/ec2/PluginImpl.java
@@ -1,47 +0,0 @@
-package hudson.plugins.ec2;
-
-import hudson.Extension;
-import hudson.Plugin;
-import hudson.model.Describable;
-import hudson.model.Descriptor;
-import hudson.model.Descriptor.FormException;
-import hudson.model.Hudson;
-import hudson.model.Items;
-import hudson.util.FormValidation;
-import hudson.util.Secret;
-import net.sf.json.JSONObject;
-import org.kohsuke.stapler.QueryParameter;
-import org.kohsuke.stapler.StaplerRequest;
-
-import javax.servlet.ServletException;
-import java.io.IOException;
-
-/**
- * Added to handle backwards compatibility of xstream class name mapping.
- */
-@Extension
-public class PluginImpl extends Plugin implements Describable<PluginImpl> {
- @Override
- public void start() throws Exception {
- // backward compatibility with the legacy class name
- Hudson.XSTREAM.alias("hudson.plugins.ec2.EC2Cloud",AmazonEC2Cloud.class);
-
- load();
- }
-
- public DescriptorImpl getDescriptor() {
- return (DescriptorImpl)Hudson.getInstance().getDescriptorOrDie(getClass());
- }
-
- public static PluginImpl get() {
- return Hudson.getInstance().getPlugin(PluginImpl.class);
- }
-
- @Extension
- public static final class DescriptorImpl extends Descriptor<PluginImpl> {
- @Override
- public String getDisplayName() {
- return "EC2 PluginImpl";
- }
- }
-}
View
204 src/main/java/hudson/plugins/ec2/SlaveTemplate.java
@@ -1,204 +0,0 @@
-package hudson.plugins.ec2;
-
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.ImageDescription;
-import com.xerox.amazonws.ec2.InstanceType;
-import com.xerox.amazonws.ec2.Jec2;
-import com.xerox.amazonws.ec2.KeyPairInfo;
-import com.xerox.amazonws.ec2.ReservationDescription.Instance;
-import hudson.model.Describable;
-import hudson.model.Descriptor;
-import hudson.model.Descriptor.FormException;
-import hudson.model.Hudson;
-import hudson.model.TaskListener;
-import hudson.model.Label;
-import hudson.model.Node;
-import hudson.Extension;
-import hudson.Util;
-import hudson.util.FormValidation;
-import org.kohsuke.stapler.DataBoundConstructor;
-import org.kohsuke.stapler.QueryParameter;
-
-import javax.servlet.ServletException;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Template of {@link EC2Slave} to launch.
- *
- * @author Kohsuke Kawaguchi
- */
-public class SlaveTemplate implements Describable<SlaveTemplate> {
- public final String ami;
- public final String description;
- public final String remoteFS;
- public final InstanceType type;
- public final String labels;
- public final String initScript;
- public final String userData;
- public final String numExecutors;
- public final String remoteAdmin;
- public final String rootCommandPrefix;
- public final String jvmopts;
- protected transient EC2Cloud parent;
-
- private transient /*almost final*/ Set<Label> labelSet;
-
- @DataBoundConstructor
- public SlaveTemplate(String ami, String remoteFS, InstanceType type, String labelString, String description, String initScript, String userData, String numExecutors, String remoteAdmin, String rootCommandPrefix, String jvmopts) {
- this.ami = ami;
- this.remoteFS = remoteFS;
- this.type = type;
- this.labels = Util.fixNull(labelString);
- this.description = description;
- this.initScript = initScript;
- this.userData = userData;
- this.numExecutors = Util.fixNull(numExecutors).trim();
- this.remoteAdmin = remoteAdmin;
- this.rootCommandPrefix = rootCommandPrefix;
- this.jvmopts = jvmopts;
- readResolve(); // initialize
- }
-
- public EC2Cloud getParent() {
- return parent;
- }
-
- public String getLabelString() {
- return labels;
- }
-
- public String getDisplayName() {
- return description+" ("+ami+")";
- }
-
- public int getNumExecutors() {
- try {
- return Integer.parseInt(numExecutors);
- } catch (NumberFormatException e) {
- return EC2Slave.toNumExecutors(type);
- }
- }
-
- public String getRemoteAdmin() {
- return remoteAdmin;
- }
-
- public String getRootCommandPrefix() {
- return rootCommandPrefix;
- }
-
- /**
- * Does this contain the given label?
- *
- * @param l
- * can be null to indicate "don't care".
- */
- public boolean containsLabel(Label l) {
- return l==null || labelSet.contains(l);
- }
-
- /**
- * Provisions a new EC2 slave.
- *
- * @return always non-null. This needs to be then added to {@link Hudson#addNode(Node)}.
- */
- public EC2Slave provision(TaskListener listener) throws EC2Exception, IOException {
- PrintStream logger = listener.getLogger();
- Jec2 ec2 = getParent().connect();
-
- try {
- logger.println("Launching "+ami);
- KeyPairInfo keyPair = parent.getPrivateKey().find(ec2);
- if(keyPair==null)
- throw new EC2Exception("No matching keypair found on EC2. Is the EC2 private key a valid one?");
- Instance inst = ec2.runInstances(ami, 1, 1, Collections.<String>emptyList(), userData, keyPair.getKeyName(), type).getInstances().get(0);
- return newSlave(inst);
- } catch (FormException e) {
- throw new AssertionError(); // we should have discovered all configuration issues upfront
- }
- }
-
- private EC2Slave newSlave(Instance inst) throws FormException, IOException {
- return new EC2Slave(inst.getInstanceId(), description, remoteFS, getNumExecutors(), labels, initScript, remoteAdmin, rootCommandPrefix, jvmopts);
- }
-
- /**
- * Provisions a new EC2 slave based on the currently running instance on EC2,
- * instead of starting a new one.
- */
- public EC2Slave attach(String instanceId, TaskListener listener) throws EC2Exception, IOException {
- PrintStream logger = listener.getLogger();
- Jec2 ec2 = getParent().connect();
-
- try {
- logger.println("Attaching to "+instanceId);
- Instance inst = ec2.describeInstances(Collections.singletonList(instanceId)).get(0).getInstances().get(0);
- return newSlave(inst);
- } catch (FormException e) {
- throw new AssertionError(); // we should have discovered all configuration issues upfront
- }
- }
-
- /**
- * Initializes data structure that we don't persist.
- */
- protected Object readResolve() {
- labelSet = Label.parse(labels);
- return this;
- }
-
- public Descriptor<SlaveTemplate> getDescriptor() {
- return Hudson.getInstance().getDescriptor(getClass());
- }
-
- @Extension
- public static final class DescriptorImpl extends Descriptor<SlaveTemplate> {
- public String getDisplayName() {
- return null;
- }
-
- /**
- * Since this shares much of the configuration with {@link EC2Computer}, check its help page, too.
- */
- @Override
- public String getHelpFile(String fieldName) {
- String p = super.getHelpFile(fieldName);
- if (p==null) p = Hudson.getInstance().getDescriptor(EC2Slave.class).getHelpFile(fieldName);
- return p;
- }
-
- /***
- * Check that the AMI requested is available in the cloud and can be used.
- */
- public FormValidation doValidateAmi(
- @QueryParameter String accessId, @QueryParameter String secretKey,
- @QueryParameter String ec2EndpointUrl,
- final @QueryParameter String ami) throws IOException, ServletException {
- Jec2 jec2 = EC2Cloud.connect(accessId, secretKey, EC2Cloud.checkEndPoint(ec2EndpointUrl));
- if(jec2!=null) {
- try {
- List<String> images = new LinkedList<String>();
- images.add(ami);
- List<String> owners = new LinkedList<String>();
- List<String> users = new LinkedList<String>();
- users.add("self"); // if we can't run it its not useful.
- List<ImageDescription> img = jec2.describeImages(
- images, owners, users, null);
- if(img==null || img.isEmpty())
- // de-registered AMI causes an empty list to be returned. so be defensive
- // against other possibilities
- return FormValidation.error("No such AMI, or not usable with this accessId: "+ami);
- return FormValidation.ok(img.get(0).getImageLocation()+" by "+img.get(0).getImageOwnerId());
- } catch (EC2Exception e) {
- return FormValidation.error(e.getMessage());
- }
- } else
- return FormValidation.ok(); // can't test
- }
- }
-}
View
26 src/main/java/hudson/plugins/ec2/ebs/ZPoolExpandNotice.java
@@ -1,26 +0,0 @@
-package hudson.plugins.ec2.ebs;
-
-import hudson.model.AdministrativeMonitor;
-import hudson.Extension;
-
-/**
- * {@link AdministrativeMonitor} that tells the user that ZFS pool is filling up
- * and they need to add more storage.
- *
- * @author Kohsuke Kawaguchi
- */
-@Extension
-public class ZPoolExpandNotice extends AdministrativeMonitor {
- /**
- * Set by {@link ZPoolMonitor}.
- */
- /*package*/ boolean activated = false;
-
- public ZPoolExpandNotice() {
- super("zpool.ebs");
- }
-
- public boolean isActivated() {
- return activated;
- }
-}
View
65 src/main/java/hudson/plugins/ec2/ebs/ZPoolMonitor.java
@@ -1,65 +0,0 @@
-package hudson.plugins.ec2.ebs;
-
-import hudson.model.PeriodicWork;
-import hudson.model.Hudson;
-import hudson.model.AdministrativeMonitor;
-import hudson.triggers.Trigger;
-import hudson.util.TimeUnit2;
-import hudson.Extension;
-import org.jvnet.solaris.libzfs.LibZFS;
-import org.jvnet.solaris.libzfs.ZFSFileSystem;
-import org.jvnet.solaris.libzfs.ZFSPool;
-
-import java.net.URL;
-import java.io.IOException;
-
-/**
- * Once an hour, check if the main zpool is that hosts $HUDSON_HOME has still enough free space.
- *
- * @author Kohsuke Kawaguchi
- */
-@Extension
-public class ZPoolMonitor extends PeriodicWork {
- public long getRecurrencePeriod() {
- return TimeUnit2.HOURS.toMillis(1);
- }
-
- protected void doRun() {
- ZFSFileSystem fs=null;
- try {
- if(isInsideEC2())
- fs = new LibZFS().getFileSystemByMountPoint(Hudson.getInstance().getRootDir());
- } catch (LinkageError e) {
- // probably not running on OpenSolaris
- }
- if(fs==null) {
- cancel();
- return;
- }
- ZFSPool pool = fs.getPool();
- long a = pool.getAvailableSize();
- long t = pool.getSize();
-
- // if the disk is 90% filled up and the available space is less than 1GB,
- // notify the user
- ZPoolExpandNotice zen = AdministrativeMonitor.all().get(ZPoolExpandNotice.class);
- zen.activated = t/a>10 && a<1000L*1000*1000;
- }
-
- private static Boolean isInsideEC2;
-
- /**
- * Returns true if this JVM runs inside EC2.
- */
- public static synchronized boolean isInsideEC2() {
- if(isInsideEC2==null) {
- try {
- new URL("http://169.254.169.254/latest").openStream().close();
- isInsideEC2 = true;
- } catch (IOException e) {
- isInsideEC2 = false;
- }
- }
- return isInsideEC2;
- }
-}
View
9 src/main/java/hudson/plugins/ec2/ebs/package-info.java
@@ -1,9 +0,0 @@
-/**
- * Code that deals with HUDSON_HOME on EBS, which is used in
- * conjunction with our EC2 launch wizard.
- *
- * <p>
- * This should eventually move to its own plugin, but for
- * now I'm putting this here.
- */
-package hudson.plugins.ec2.ebs;
View
208 src/main/java/hudson/plugins/ec2/ssh/EC2UnixLauncher.java
@@ -1,208 +0,0 @@
-package hudson.plugins.ec2.ssh;
-
-import com.trilead.ssh2.Connection;
-import com.trilead.ssh2.SCPClient;
-import com.trilead.ssh2.ServerHostKeyVerifier;
-import com.trilead.ssh2.Session;
-import com.xerox.amazonws.ec2.EC2Exception;
-import com.xerox.amazonws.ec2.KeyPairInfo;
-import com.xerox.amazonws.ec2.ReservationDescription.Instance;
-import hudson.model.Descriptor;
-import hudson.model.Hudson;
-import hudson.plugins.ec2.EC2Cloud;
-import hudson.plugins.ec2.EC2Computer;
-import hudson.plugins.ec2.EC2ComputerLauncher;
-import hudson.remoting.Channel;
-import hudson.remoting.Channel.Listener;
-import hudson.slaves.ComputerLauncher;
-import org.apache.commons.io.IOUtils;
-import org.jets3t.service.S3ServiceException;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.net.URL;
-
-/**
- * {@link ComputerLauncher} that connects to a Unix slave on EC2 by using SSH.
- *
- * @author Kohsuke Kawaguchi
- */
-public class EC2UnixLauncher extends EC2ComputerLauncher {
-
- private final int FAILED=-1;
- private final int SAMEUSER=0;
- private final int RECONNECT=-2;
-
- protected void launch(EC2Computer computer, PrintStream logger, Instance inst) throws IOException, EC2Exception, InterruptedException, S3ServiceException {
- logger.println("Connecting to "+inst.getDnsName());
- final Connection bootstrapConn;
- final Connection conn;
- Connection cleanupConn = null; // java's code path analysis for final doesn't work that well.
- boolean successful = false;
-
- try {
- bootstrapConn = connectToSsh(inst);
- int bootstrapResult = bootstrap(bootstrapConn, computer, logger);
- if (bootstrapResult == FAILED)
- return; // bootstrap closed for us.
- else if (bootstrapResult == SAMEUSER)
- cleanupConn = bootstrapConn; // take over the connection
- else {
- // connect fresh as ROOT
- cleanupConn = connectToSsh(inst);
- KeyPairInfo key = EC2Cloud.get().getKeyPair();
- if (!cleanupConn.authenticateWithPublicKey("root", key.getKeyMaterial().toCharArray(), "")) {
- logger.println("Authentication failed");
- return; // failed to connect as root.
- }
- }
- conn = cleanupConn;
-
- SCPClient scp = conn.createSCPClient();
- String initScript = computer.getNode().initScript;
-
- if(initScript!=null && initScript.trim().length()>0 && conn.exec("test -e /.hudson-run-init", logger) !=0) {
- logger.println("Executing init script");
- scp.put(initScript.getBytes("UTF-8"),"init.sh","/tmp","0700");
- Session sess = conn.openSession();
- sess.requestDumbPTY(); // so that the remote side bundles stdout and stderr
- sess.execCommand(computer.getRootCommandPrefix() + "/tmp/init.sh");
-
- sess.getStdin().close(); // nothing to write here
- sess.getStderr().close(); // we are not supposed to get anything from stderr
- IOUtils.copy(sess.getStdout(),logger);
-
- int exitStatus = waitCompletion(sess);
- if (exitStatus!=0) {
- logger.println("init script failed: exit code="+exitStatus);
- return;
- }
-
- // leave the completion marker
- scp.put(new byte[0],".hudson-run-init","/","0600");
-
- }
-
- // TODO: parse the version number. maven-enforcer-plugin might help
- logger.println("Verifying that java exists");
- if(conn.exec("java -fullversion", logger) !=0) {
- logger.println("Installing Java");
-
- String jdk = "java1.6.0_12";
- String path = "/hudson-ci/jdk/linux-i586/" + jdk + ".tgz";
-
- URL url = EC2Cloud.get().buildPresignedURL(path);
- if(conn.exec("wget -nv -O /usr/" + jdk + ".tgz '" + url + "'", logger) !=0) {
- logger.println("Failed to download Java");
- return;
- }
-
- if(conn.exec("tar xz -C /usr -f /usr/" + jdk + ".tgz", logger) !=0) {
- logger.println("Failed to install Java");
- return;
- }
-
- if(conn.exec("ln -s /usr/" + jdk + "/bin/java /bin/java", logger) !=0) {
- logger.println("Failed to symlink Java");
- return;
- }
- }
-
- // TODO: on Windows with ec2-sshd, this scp command ends up just putting slave.jar as c:\tmp
- // bug in ec2-sshd?
-
- logger.println("Copying slave.jar");
- scp.put(Hudson.getInstance().getJnlpJars("slave.jar").readFully(),
- "slave.jar","/tmp");
-
- logger.println("Launching slave agent");
- final Session sess = conn.openSession();
- sess.execCommand("java " + computer.getNode().jvmopts + " -jar /tmp/slave.jar");
- computer.setChannel(sess.getStdout(),sess.getStdin(),logger,new Listener() {
- public void onClosed(Channel channel, IOException cause) {
- sess.close();
- conn.close();
- }
- });
- successful = true;
- } finally {
- if(cleanupConn != null && !successful)
- cleanupConn.close();
- }
- }
-
- private int bootstrap(Connection bootstrapConn, EC2Computer computer, PrintStream logger) throws IOException, InterruptedException, EC2Exception {
- boolean closeBootstrap = true;
- try {
- int tries = 20;
- boolean isAuthenticated = false;
- KeyPairInfo key = EC2Cloud.get().getKeyPair();
- while (tries-- > 0) {
- isAuthenticated = bootstrapConn.authenticateWithPublicKey(computer.getRemoteAdmin(), key.getKeyMaterial().toCharArray(), "");
- if (isAuthenticated) {
- break;
- }
- logger.println("Authentication failed. Trying again...");
- Thread.currentThread().sleep(10000);
- }
- if (!isAuthenticated) {
- logger.println("Authentication failed");
- return FAILED;
- }
- if (!computer.getRemoteAdmin().equals("root")) {
- // Get root working, so we can scp in etc.
- Session sess = bootstrapConn.openSession();
- sess.requestDumbPTY(); // so that the remote side bundles stdout and stderr
- sess.execCommand(computer.getRootCommandPrefix() + "cp ~/.ssh/authorized_keys /root/.ssh/");
- sess.getStdin().close(); // nothing to write here
- sess.getStderr().close(); // we are not supposed to get anything from stderr
- IOUtils.copy(sess.getStdout(), logger);
- int exitStatus = waitCompletion(sess);