Skip to content
Permalink
Browse files

JENKINS-32690 Make manually provision really work (#195)

* JENKINS-32690 Make manually provision really work

* JENKINS-32690 Make manually provision really work (change to EnumSets)
  • Loading branch information...
Francis Upton IV
Francis Upton IV committed May 9, 2016
1 parent 008e5e4 commit e52a2eae39445157eef79b45da51f435ee5adfaa
Showing with 27 additions and 15 deletions.
  1. +10 −4 src/main/java/hudson/plugins/ec2/EC2Cloud.java
  2. +17 −11 src/main/java/hudson/plugins/ec2/SlaveTemplate.java
@@ -65,6 +65,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -336,7 +337,7 @@ public HttpResponse doProvision(@QueryParameter String template) throws ServletE
}

try {
EC2AbstractSlave node = provisionSlaveIfPossible(t);
EC2AbstractSlave node = provisionSlaveIfPossible(t, true);
if (node == null)
throw HttpResponses.error(SC_BAD_REQUEST, "Cloud or AMI instance cap would be exceeded for: " + template);
Jenkins.getInstance().addNode(node);
@@ -483,7 +484,7 @@ private int getPossibleNewSlavesCount(SlaveTemplate template) throws AmazonClien
return Math.min(availableAmiSlaves, availableTotalSlaves);
}

private synchronized EC2AbstractSlave provisionSlaveIfPossible(SlaveTemplate template) {
private synchronized EC2AbstractSlave provisionSlaveIfPossible(SlaveTemplate template, boolean forceCreateNew) {
/*
* Note this is synchronized between counting the instances and then allocating the node. Once the node is
* allocated, we don't look at that instance as available for provisioning.
@@ -495,7 +496,12 @@ private synchronized EC2AbstractSlave provisionSlaveIfPossible(SlaveTemplate tem
}

try {
return template.provision(StreamTaskListener.fromStdout(), possibleSlavesCount > 0);
EnumSet<SlaveTemplate.ProvisionOptions> provisionOptions = EnumSet.noneOf(SlaveTemplate.ProvisionOptions.class);
if (forceCreateNew)
provisionOptions = EnumSet.of(SlaveTemplate.ProvisionOptions.FORCE_CREATE);
else if (possibleSlavesCount > 0)
provisionOptions = EnumSet.of(SlaveTemplate.ProvisionOptions.ALLOW_CREATE);
return template.provision(StreamTaskListener.fromStdout(), provisionOptions);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Exception during provisioning", e);
return null;
@@ -512,7 +518,7 @@ private synchronized EC2AbstractSlave provisionSlaveIfPossible(SlaveTemplate tem
LOGGER.log(Level.WARNING, String.format("Label is null - can't caculate how many executors slave will have. Using %s number of executors", t.getNumExecutors()));
}
while (excessWorkload > 0) {
final EC2AbstractSlave slave = provisionSlaveIfPossible(t);
final EC2AbstractSlave slave = provisionSlaveIfPossible(t, false);
// Returned null if a new node could not be created
if (slave == null)
break;
@@ -366,18 +366,20 @@ public String getIamInstanceProfile() {
return iamInstanceProfile;
}

enum ProvisionOptions { ALLOW_CREATE, FORCE_CREATE }

/**
* Provisions a new EC2 slave or starts a previously stopped on-demand instance.
*
* @return always non-null. This needs to be then added to {@link Hudson#addNode(Node)}.
*/
public EC2AbstractSlave provision(TaskListener listener, boolean allowCreateNew) throws AmazonClientException, IOException {
public EC2AbstractSlave provision(TaskListener listener, EnumSet<ProvisionOptions> provisionOptions) throws AmazonClientException, IOException {
if (this.spotConfig != null) {
if (allowCreateNew)
if (provisionOptions.contains(ProvisionOptions.ALLOW_CREATE) || provisionOptions.contains(ProvisionOptions.FORCE_CREATE))
return provisionSpot(listener);
return null;
}
return provisionOndemand(listener, allowCreateNew);
return provisionOndemand(listener, provisionOptions);
}

private boolean checkInstance(PrintStream logger, Instance existingInstance, EC2AbstractSlave[] returnNode) {
@@ -438,7 +440,7 @@ private void logProvisionInfo(PrintStream logger, String message) {
/**
* Provisions an On-demand EC2 slave by launching a new instance or starting a previously-stopped instance.
*/
private EC2AbstractSlave provisionOndemand(TaskListener listener, boolean allowCreateNew) throws AmazonClientException, IOException {
private EC2AbstractSlave provisionOndemand(TaskListener listener, EnumSet<ProvisionOptions> provisionOptions) throws AmazonClientException, IOException {
PrintStream logger = listener.getLogger();
AmazonEC2 ec2 = getParent().connect();

@@ -553,18 +555,22 @@ private EC2AbstractSlave provisionOndemand(TaskListener listener, boolean allowC
DescribeInstancesResult diResult = ec2.describeInstances(diRequest);
EC2AbstractSlave[] ec2Node = new EC2AbstractSlave[1];
Instance existingInstance = null;
reservationLoop: for (Reservation reservation : diResult.getReservations()) {
for (Instance instance : reservation.getInstances()) {
if (checkInstance(logger, instance, ec2Node)) {
existingInstance = instance;
logProvision(logger, "Found existing instance: " + existingInstance + ((ec2Node[0] != null) ? (" node: " + ec2Node[0].getInstanceId()) : ""));
break reservationLoop;
if (!provisionOptions.contains(ProvisionOptions.FORCE_CREATE)) {
reservationLoop:
for (Reservation reservation : diResult.getReservations()) {
for (Instance instance : reservation.getInstances()) {
if (checkInstance(logger, instance, ec2Node)) {
existingInstance = instance;
logProvision(logger, "Found existing instance: " + existingInstance + ((ec2Node[0] != null) ? (" node: " + ec2Node[0].getInstanceId()) : ""));
break reservationLoop;
}
}
}
}

if (existingInstance == null) {
if (!allowCreateNew) {
if (!provisionOptions.contains(ProvisionOptions.FORCE_CREATE) &&
!provisionOptions.contains(ProvisionOptions.ALLOW_CREATE)) {
logProvision(logger, "No existing instance found - but cannot create new instance");
return null;
}

0 comments on commit e52a2ea

Please sign in to comment.
You can’t perform that action at this time.