Skip to content
Permalink
Browse files
Merge pull request #105 from jenkinsci/feature/windows-slave-support
JENKINS-4995 Support Windows AMIs
  • Loading branch information
francisu committed Jul 29, 2014
2 parents 04cd780 + 859dd4e commit a3bd08def1ed2d2f30c5fa73be707fb702c2a9e5
Showing 41 changed files with 2,176 additions and 72 deletions.
20 pom.xml
@@ -71,6 +71,25 @@ THE SOFTWARE.
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>node-iterator-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
<!-- force version 4.1.1 because of 4.1 bug:
https://issues.apache.org/jira/browse/HTTPCLIENT-1056
that prevents authentication caching, resulting in very
poor performances for WinRM -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3</version>
</dependency>
</dependencies>

@@ -102,6 +121,7 @@ THE SOFTWARE.
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>

<build>
<pluginManagement>
<plugins>
@@ -0,0 +1,9 @@
package hudson.plugins.ec2;

import hudson.model.AbstractDescribableImpl;

public abstract class AMITypeData extends AbstractDescribableImpl<AMITypeData>
{
public abstract boolean isWindows();
public abstract boolean isUnix();
}
@@ -25,6 +25,7 @@

import hudson.Util;
import hudson.model.Computer;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.Descriptor.FormException;
@@ -67,14 +68,16 @@ public abstract class EC2AbstractSlave extends Slave {
*/
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 final boolean stopOnTerminate;
public final String idleTerminationMinutes;
public final boolean usePrivateDnsName;
public final boolean useDedicatedTenancy;
public List<EC2Tag> tags;
public final String cloudName;
public AMITypeData amiType;

// Temporary stuff that is obtained live from EC2
public String publicDNS;
@@ -90,33 +93,37 @@ public abstract class EC2AbstractSlave extends Slave {
protected static final long MIN_FETCH_TIME = 20 * 1000;


/**
* For data read from old Hudson, this is 0, so we use that to indicate 22.
*/
protected final int sshPort;
protected final int launchTimeout;

// Deprecated by the AMITypeData data structure
@Deprecated
protected transient int sshPort;
@Deprecated
public transient String rootCommandPrefix; // e.g. 'sudo'

private transient long createdTime;

public static final String TEST_ZONE = "testZone";


@DataBoundConstructor
public EC2AbstractSlave(String name, String instanceId, String description, String remoteFS, int sshPort, int numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy<EC2Computer> retentionStrategy, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout) throws FormException, IOException {
public EC2AbstractSlave(String name, String instanceId, String description, String remoteFS, int numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy<EC2Computer> retentionStrategy, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout, AMITypeData amiType) throws FormException, IOException {

super(name, "", remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, nodeProperties);

this.instanceId = instanceId;
this.initScript = initScript;
this.remoteAdmin = remoteAdmin;
this.rootCommandPrefix = rootCommandPrefix;
this.jvmopts = jvmopts;
this.sshPort = sshPort;
this.stopOnTerminate = stopOnTerminate;
this.idleTerminationMinutes = idleTerminationMinutes;
this.tags = tags;
this.usePrivateDnsName = usePrivateDnsName;
this.useDedicatedTenancy = useDedicatedTenancy;
this.cloudName = cloudName;
this.launchTimeout = launchTimeout;
this.amiType = amiType;
readResolve();
}

protected Object readResolve() {
@@ -129,6 +136,11 @@ protected Object readResolve() {
if (instanceId == null) {
instanceId = getNodeName();
}

if (amiType == null) {
amiType = new UnixData(rootCommandPrefix, Integer.toString(sshPort));
}

return this;
}

@@ -264,22 +276,32 @@ public long getLaunchTimeoutInMillis() {

String getRemoteAdmin() {
if (remoteAdmin == null || remoteAdmin.length() == 0)
return "root";
return amiType.isWindows() ? "Administrator" : "root";
return remoteAdmin;
}

String getRootCommandPrefix() {
if (rootCommandPrefix == null || rootCommandPrefix.length() == 0)
String commandPrefix = amiType.isUnix() ? ((UnixData)amiType).getRootCommandPrefix() : "";
if (commandPrefix == null || commandPrefix.length() == 0)
return "";
return rootCommandPrefix + " ";
return commandPrefix + " ";
}

String getJvmopts() {
return Util.fixNull(jvmopts);
}

public int getSshPort() {
return sshPort!=0 ? sshPort : 22;
String sshPort = amiType.isUnix() ? ((UnixData)amiType).getSshPort() : "22";
if (sshPort == null || sshPort.length() == 0)
return 22;

int port = 0;
try {
port = Integer.parseInt(sshPort);
} catch (Exception e) {
}
return port!=0 ? port : 22;
}

public boolean getStopOnTerminate() {
@@ -320,6 +342,7 @@ protected void fetchLiveInstanceData( boolean force ) throws AmazonClientExcepti

publicDNS = i.getPublicDnsName();
privateDNS = i.getPrivateIpAddress();
createdTime = i.getLaunchTime().getTime();
tags = new LinkedList<EC2Tag>();

for (Tag t : i.getTags()) {
@@ -380,9 +403,26 @@ public List<EC2Tag> getTags() {
return Collections.unmodifiableList(tags);
}

public long getCreatedTime() {
fetchLiveInstanceData(false);
return createdTime;
}

public boolean getUsePrivateDnsName() {
return usePrivateDnsName;
}

public String getAdminPassword() {
return amiType.isWindows() ? ((WindowsData)amiType).getPassword() : "";
}

public boolean isUseHTTPS() {
return amiType.isWindows() ? ((WindowsData)amiType).isUseHTTPS() : false;
}

public int getBootDelay() {
return amiType.isWindows() ? ((WindowsData)amiType).getBootDelayInMillis() : 0;
}

public static ListBoxModel fillZoneItems(String accessId, String secretKey, String region) throws IOException, ServletException {
ListBoxModel model = new ListBoxModel();
@@ -408,7 +448,7 @@ public static ListBoxModel fillZoneItems(String accessId, String secretKey, Stri
*/
abstract public String getEc2Type();

public static abstract class DescriptorImpl extends SlaveDescriptor {
public static abstract class DescriptorImpl extends SlaveDescriptor {

@Override
public abstract String getDisplayName();
@@ -423,7 +463,13 @@ public ListBoxModel doFillZoneItems(@QueryParameter String accessId,
ServletException {
return fillZoneItems(accessId, secretKey, region);
}

public List<Descriptor<AMITypeData>> getAMITypeDescriptors()
{
return Hudson.getInstance().<AMITypeData,Descriptor<AMITypeData>>getDescriptorList(AMITypeData.class);
}
}

private static final Logger LOGGER = Logger.getLogger(EC2AbstractSlave.class.getName());

}
@@ -5,6 +5,7 @@
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.plugins.ec2.ssh.EC2UnixLauncher;
import hudson.plugins.ec2.win.EC2WindowsLauncher;
import hudson.slaves.NodeProperty;

import java.io.IOException;
@@ -29,18 +30,18 @@
*/
public final class EC2OndemandSlave extends EC2AbstractSlave {

public EC2OndemandSlave(String instanceId, String description, String remoteFS, int sshPort, int numExecutors, String labelString, Mode mode, String initScript, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName,int launchTimeout) throws FormException, IOException {
this(description + " (" + instanceId + ")", instanceId, description, remoteFS, sshPort, numExecutors, labelString, mode, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts, stopOnTerminate, idleTerminationMinutes, publicDNS, privateDNS, tags, cloudName, false, false, launchTimeout);
public EC2OndemandSlave(String instanceId, String description, String remoteFS, int numExecutors, String labelString, Mode mode, String initScript, String remoteAdmin, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName,int launchTimeout, AMITypeData amiType) throws FormException, IOException {
this(description + " (" + instanceId + ")", instanceId, description, remoteFS, numExecutors, labelString, mode, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, jvmopts, stopOnTerminate, idleTerminationMinutes, publicDNS, privateDNS, tags, cloudName, false, false, launchTimeout, amiType);
}

public EC2OndemandSlave(String instanceId, String description, String remoteFS, int sshPort, int numExecutors, String labelString, Mode mode, String initScript, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout) throws FormException, IOException {
this(description + " (" + instanceId + ")", instanceId, description, remoteFS, sshPort, numExecutors, labelString, mode, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts, stopOnTerminate, idleTerminationMinutes, publicDNS, privateDNS, tags, cloudName, usePrivateDnsName, useDedicatedTenancy, launchTimeout);
public EC2OndemandSlave(String instanceId, String description, String remoteFS, int numExecutors, String labelString, Mode mode, String initScript, String remoteAdmin, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout, AMITypeData amiType) throws FormException, IOException {
this(description + " (" + instanceId + ")", instanceId, description, remoteFS, numExecutors, labelString, mode, initScript, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, jvmopts, stopOnTerminate, idleTerminationMinutes, publicDNS, privateDNS, tags, cloudName, usePrivateDnsName, useDedicatedTenancy, launchTimeout, amiType);
}

@DataBoundConstructor
public EC2OndemandSlave(String name, String instanceId, String description, String remoteFS, int sshPort, int numExecutors, String labelString, Mode mode, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout) throws FormException, IOException {
public EC2OndemandSlave(String name, String instanceId, String description, String remoteFS, int numExecutors, String labelString, Mode mode, String initScript, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String jvmopts, boolean stopOnTerminate, String idleTerminationMinutes, String publicDNS, String privateDNS, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, boolean useDedicatedTenancy, int launchTimeout, AMITypeData amiType) throws FormException, IOException {

super(name, instanceId, description, remoteFS, sshPort, numExecutors, mode, labelString, new EC2UnixLauncher(), new EC2RetentionStrategy(idleTerminationMinutes), initScript, nodeProperties, remoteAdmin, rootCommandPrefix, jvmopts, stopOnTerminate, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, useDedicatedTenancy, launchTimeout);
super(name, instanceId, description, remoteFS, numExecutors, mode, labelString, amiType.isWindows() ? new EC2WindowsLauncher() : new EC2UnixLauncher(), new EC2RetentionStrategy(idleTerminationMinutes), initScript, nodeProperties, remoteAdmin, jvmopts, stopOnTerminate, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, useDedicatedTenancy, launchTimeout, amiType);

this.publicDNS = publicDNS;
this.privateDNS = privateDNS;
@@ -50,7 +51,7 @@ public EC2OndemandSlave(String name, String instanceId, String description, Stri
* Constructor for debugging.
*/
public EC2OndemandSlave(String instanceId) throws FormException, IOException {
this(instanceId, instanceId, "debug", "/tmp/hudson", 22, 1, "debug", Mode.NORMAL, "", Collections.<NodeProperty<?>>emptyList(), null, null, null, false, null, "Fake public", "Fake private", null, null, false, false, 0);
this(instanceId, instanceId, "debug", "/tmp/hudson", 1, "debug", Mode.NORMAL, "", Collections.<NodeProperty<?>>emptyList(), null, null, false, null, "Fake public", "Fake private", null, null, false, false, 0, new UnixData(null, null));
}


@@ -26,15 +26,14 @@ public final class EC2SpotSlave extends EC2AbstractSlave {

private final String spotInstanceRequestId;

public EC2SpotSlave(String name, String spotInstanceRequestId, String description, String remoteFS, int sshPort, int numExecutors, Mode mode, String initScript, String labelString, String remoteAdmin, String rootCommandPrefix, String jvmopts, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, int launchTimeout) throws FormException, IOException {
this(name, spotInstanceRequestId, description, remoteFS, sshPort, numExecutors, mode, initScript, labelString, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, rootCommandPrefix, jvmopts, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, launchTimeout);
public EC2SpotSlave(String name, String spotInstanceRequestId, String description, String remoteFS, int numExecutors, Mode mode, String initScript, String labelString, String remoteAdmin, String jvmopts, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, int launchTimeout, AMITypeData amiType) throws FormException, IOException {
this(name, spotInstanceRequestId, description, remoteFS, numExecutors, mode, initScript, labelString, Collections.<NodeProperty<?>>emptyList(), remoteAdmin, jvmopts, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, launchTimeout, amiType);
}

@DataBoundConstructor
public EC2SpotSlave(String name, String spotInstanceRequestId, String description, String remoteFS, int sshPort, int numExecutors, Mode mode, String initScript, String labelString, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String rootCommandPrefix, String jvmopts, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, int launchTimeout) throws FormException, IOException {

super(name, "", description, remoteFS, sshPort, numExecutors, mode, labelString, new EC2SpotComputerLauncher(), new EC2SpotRetentionStrategy(idleTerminationMinutes), initScript, nodeProperties, remoteAdmin, rootCommandPrefix, jvmopts, false, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, false, launchTimeout);
public EC2SpotSlave(String name, String spotInstanceRequestId, String description, String remoteFS, int numExecutors, Mode mode, String initScript, String labelString, List<? extends NodeProperty<?>> nodeProperties, String remoteAdmin, String jvmopts, String idleTerminationMinutes, List<EC2Tag> tags, String cloudName, boolean usePrivateDnsName, int launchTimeout, AMITypeData amiType) throws FormException, IOException {

super(name, "", description, remoteFS, numExecutors, mode, labelString, new EC2SpotComputerLauncher(), new EC2SpotRetentionStrategy(idleTerminationMinutes), initScript, nodeProperties, remoteAdmin, jvmopts, false, idleTerminationMinutes, tags, cloudName, usePrivateDnsName, false, launchTimeout, amiType);
this.name = name;
this.spotInstanceRequestId = spotInstanceRequestId;
}

0 comments on commit a3bd08d

Please sign in to comment.