/** * Determines whether the AMI of the given instance matches the AMI of template and has the * required label (if requiredLabel is non-null) */ private boolean checkInstance( PrintStream logger, Instance existingInstance, Label requiredLabel, EC2AbstractSlave[] returnNode) { logProvision(logger, "checkInstance: " + existingInstance); if (StringUtils.isNotBlank(getIamInstanceProfile())) { if (existingInstance.getIamInstanceProfile() != null) { if (!existingInstance.getIamInstanceProfile().getArn().equals(getIamInstanceProfile())) { logProvision(logger, " false - IAM Instance profile does not match"); return false; } // Match, fall through } else { logProvision(logger, " false - Null IAM Instance profile"); return false; } } if (existingInstance .getState() .getName() .equalsIgnoreCase(InstanceStateName.Terminated.toString()) || existingInstance .getState() .getName() .equalsIgnoreCase(InstanceStateName.ShuttingDown.toString())) { logProvision(logger, " false - Instance is terminated or shutting down"); return false; } // See if we know about this and it has capacity for (EC2AbstractSlave node : NodeIterator.nodes(EC2AbstractSlave.class)) { if (node.getInstanceId().equals(existingInstance.getInstanceId())) { logProvision(logger, "Found existing corresponding Jenkins slave: " + node.getInstanceId()); if (!node.toComputer().isPartiallyIdle()) { logProvision(logger, " false - Node is not partially idle"); return false; } // REMOVEME - this was added to force provision to work, but might not allow // stopped instances to be found - need to investigate further else if (false && node.toComputer().isOffline()) { logProvision(logger, " false - Node is offline"); return false; } else if (requiredLabel != null && !requiredLabel.matches(node.getAssignedLabels())) { logProvision(logger, " false - we need a Node having label " + requiredLabel); return false; } else { logProvision(logger, " true - Node has capacity - can use it"); returnNode[0] = node; return true; } } } logProvision(logger, " true - Instance has no node, but can be used"); return true; }
/** * Counts the number of instances in EC2 currently running that are using the specified image and * a template. * * @param ami If AMI is left null, then all instances are counted and template description is * ignored. * <p>This includes those instances that may be started outside Jenkins. * @param templateDesc */ public int countCurrentEC2Slaves(String ami, String templateDesc) throws AmazonClientException { int n = 0; for (Reservation r : connect().describeInstances().getReservations()) { for (Instance i : r.getInstances()) { if (isEc2ProvisionedAmiSlave(i, ami, templateDesc)) { InstanceStateName stateName = InstanceStateName.fromValue(i.getState().getName()); if (stateName == InstanceStateName.Pending || stateName == InstanceStateName.Running) { EC2AbstractSlave foundSlave = null; for (EC2AbstractSlave ec2Node : NodeIterator.nodes(EC2AbstractSlave.class)) { if (ec2Node.getInstanceId().equals(i.getInstanceId())) { foundSlave = ec2Node; break; } } // Don't count disconnected slaves as being used, we will connected them later is // required if (foundSlave != null && foundSlave.toComputer().isOffline()) continue; n++; } } } } // Count pending spot requests too for (SpotInstanceRequest sir : connect().describeSpotInstanceRequests().getSpotInstanceRequests()) { // Count Spot requests that are open and still have a // chance to be active. if (sir.getState().equals("open")) { n++; } } return n; }