use of hudson.slaves.NodeProvisioner.PlannedNode in project jenkins-test-harness by jenkinsci.
the class DummyCloudImpl method provision.
@Override
public Collection<PlannedNode> provision(Label label, int excessWorkload) {
List<PlannedNode> r = new ArrayList<>();
// provisioning impossible
if (label != this.label)
return r;
while (excessWorkload > 0) {
System.out.println("Provisioning");
numProvisioned++;
Future<Node> f = Computer.threadPoolForRemoting.submit(new Launcher(delay));
r.add(new PlannedNode(name + " #" + numProvisioned, f, 1));
excessWorkload -= 1;
}
return r;
}
use of hudson.slaves.NodeProvisioner.PlannedNode in project macstadium-orka-plugin by jenkinsci.
the class OrkaCloud method provision.
@Override
public Collection<PlannedNode> provision(final Label label, int excessWorkload) {
String provisionIdString = "[provisionId=" + UUID.randomUUID().toString() + "] ";
try {
String labelName = label != null ? label.getName() : "";
logger.info(provisionIdString + "Provisioning for label " + labelName + ". Workload: " + excessWorkload);
AgentTemplate template = this.getTemplate(label);
if (template == null) {
logger.fine(provisionIdString + "Couldn't find template for label " + labelName + ". Stopping provisioning.");
return Collections.emptyList();
}
int vmsToProvision = Math.max(excessWorkload / template.getNumExecutors(), 1);
int possibleVMsToProvision = this.capacityHandler.reserveCapacity(vmsToProvision, provisionIdString);
logger.fine(String.format("%s. Asked for %s VMs and got %s", provisionIdString, vmsToProvision, possibleVMsToProvision));
return IntStream.range(0, possibleVMsToProvision).mapToObj(i -> {
String nodeName = UUID.randomUUID().toString();
Callable<Node> provisionNodeCallable = this.provisionNode(template, provisionIdString, this.capacityHandler);
Future<Node> provisionNodeTask = Computer.threadPoolForRemoting.submit(provisionNodeCallable);
return new PlannedNode(nodeName, provisionNodeTask, template.getNumExecutors());
}).collect(Collectors.toList());
} catch (Exception e) {
logger.log(Level.WARNING, provisionIdString + "Exception during provisioning", e);
}
return Collections.emptyList();
}
use of hudson.slaves.NodeProvisioner.PlannedNode in project vsphere-cloud-plugin by jenkinsci.
the class vSphereCloud method provision.
@Override
public Collection<PlannedNode> provision(final Label label, int excessWorkload) {
final String methodCallDescription = "provision(" + label + "," + excessWorkload + ")";
try {
int excessWorkloadSoFar = excessWorkload;
// First we see what our static slaves can do for us.
int numberOfvSphereCloudSlaves = 0;
int numberOfvSphereCloudSlaveExecutors = 0;
for (vSphereCloudSlave n : NodeIterator.nodes(vSphereCloudSlave.class)) {
if (n instanceof vSphereCloudProvisionedSlave) {
// ignore cloud slaves
continue;
}
if (n.getComputer().isOffline() && label.matches(n.getAssignedLabels())) {
n.getComputer().tryReconnect();
numberOfvSphereCloudSlaves++;
numberOfvSphereCloudSlaveExecutors += n.getNumExecutors();
}
}
excessWorkloadSoFar -= numberOfvSphereCloudSlaveExecutors;
if (excessWorkloadSoFar <= 0) {
VSLOG.log(Level.INFO, methodCallDescription + ": " + numberOfvSphereCloudSlaves + " existing slaves (=" + numberOfvSphereCloudSlaveExecutors + " executors): Workload is satisfied by bringing those online.");
return Collections.emptySet();
}
// demand and we should consider creating new slaves.
synchronized (this) {
ensureLists();
}
retryVMdeletionIfNecessary(Math.max(excessWorkload, 2));
final List<PlannedNode> plannedNodes = new ArrayList<PlannedNode>();
synchronized (templateState) {
templateState.pruneUnwantedRecords();
Integer maxSlavesToProvisionBeforeCloudCapHit = calculateMaxAdditionalSlavesPermitted();
if (maxSlavesToProvisionBeforeCloudCapHit != null && maxSlavesToProvisionBeforeCloudCapHit <= 0) {
// no capacity due to cloud instance cap
return Collections.emptySet();
}
final List<vSphereCloudSlaveTemplate> templates = getTemplates(label);
final List<CloudProvisioningRecord> whatWeCouldUse = templateState.calculateProvisionableTemplates(templates);
VSLOG.log(Level.INFO, methodCallDescription + ": " + numberOfvSphereCloudSlaves + " existing slaves (=" + numberOfvSphereCloudSlaveExecutors + " executors), templates available are " + whatWeCouldUse);
while (excessWorkloadSoFar > 0) {
if (maxSlavesToProvisionBeforeCloudCapHit != null) {
final int intValue = maxSlavesToProvisionBeforeCloudCapHit.intValue();
if (intValue <= 0) {
// out of capacity due to cloud instance cap
break;
}
maxSlavesToProvisionBeforeCloudCapHit = Integer.valueOf(intValue - 1);
}
final CloudProvisioningRecord whatWeShouldSpinUp = CloudProvisioningAlgorithm.findTemplateWithMostFreeCapacity(whatWeCouldUse);
if (whatWeShouldSpinUp == null) {
// out of capacity due to template instance cap
break;
}
final String nodeName = CloudProvisioningAlgorithm.findUnusedName(whatWeShouldSpinUp);
final PlannedNode plannedNode = VSpherePlannedNode.createInstance(templateState, nodeName, whatWeShouldSpinUp);
plannedNodes.add(plannedNode);
excessWorkloadSoFar -= plannedNode.numExecutors;
}
}
VSLOG.log(Level.INFO, methodCallDescription + ": Provisioning " + plannedNodes.size() + " new =" + plannedNodes);
return plannedNodes;
} catch (Exception ex) {
VSLOG.log(Level.WARNING, methodCallDescription + ": Failed.", ex);
return Collections.emptySet();
}
}
use of hudson.slaves.NodeProvisioner.PlannedNode in project azure-vm-agents-plugin by jenkinsci.
the class AzureVMCloud method provision.
@Override
public Collection<PlannedNode> provision(CloudState cloudState, int workLoad) {
LOGGER.log(Level.FINE, "Starting for label {0} workLoad {1}", new Object[] { cloudState.getLabel(), workLoad });
final AzureVMAgentTemplate template = AzureVMCloud.this.getAzureAgentTemplate(cloudState.getLabel());
// round up the number of required machine
int numberOfAgents = (workLoad + template.getNoOfParallelJobs() - 1) / template.getNoOfParallelJobs();
final List<PlannedNode> plannedNodes = new ArrayList<>(numberOfAgents);
if (!template.getTemplateProvisionStrategy().isVerifiedPass()) {
AzureVMCloudVerificationTask.verify(cloudName, template.getTemplateName());
}
if (template.getTemplateProvisionStrategy().isVerifiedFailed()) {
LOGGER.log(Level.INFO, "Template {0} has just verified failed", template.getTemplateName());
if (StringUtils.isNotBlank(template.getTemplateStatusDetails())) {
LOGGER.log(Level.INFO, template.getTemplateStatusDetails());
}
return new ArrayList<>();
}
// reuse existing nodes if available
LOGGER.log(Level.FINE, "Checking for node reuse options");
for (Computer agentComputer : Jenkins.get().getComputers()) {
if (numberOfAgents == 0) {
break;
}
if (agentComputer instanceof AzureVMComputer && agentComputer.isOffline()) {
final AzureVMComputer azureComputer = (AzureVMComputer) agentComputer;
final AzureVMAgent agentNode = azureComputer.getNode();
if (agentNode != null && isNodeEligibleForReuse(agentNode, template)) {
LOGGER.log(Level.FINE, "Agent computer eligible for reuse {0}", agentComputer.getName());
try {
if (AzureVMManagementServiceDelegate.virtualMachineExists(agentNode)) {
numberOfAgents--;
plannedNodes.add(new PlannedNode(agentNode.getNodeName(), Computer.threadPoolForRemoting.submit(() -> {
final Object agentLock = getLockForAgent(agentNode);
try {
synchronized (agentLock) {
SlaveComputer computer = agentNode.getComputer();
if (computer != null && computer.isOnline()) {
return agentNode;
}
LOGGER.log(Level.INFO, "Found existing node, starting VM {0}", agentNode.getNodeName());
try {
getServiceDelegate().startVirtualMachine(agentNode);
// set virtual machine details again
getServiceDelegate().setVirtualMachineDetails(agentNode, template);
Jenkins.get().addNode(agentNode);
if (agentNode.getAgentLaunchMethod().equalsIgnoreCase("SSH")) {
retrySshConnect(azureComputer);
} else {
// Wait until node is online
waitUntilJNLPNodeIsOnline(agentNode);
}
LOGGER.info(String.format("Remove suspended status for node: %s", agentNode.getNodeName()));
azureComputer.setAcceptingTasks(true);
agentNode.clearCleanUpAction();
agentNode.setEligibleForReuse(false);
} catch (Exception e) {
throw AzureCloudException.create(e);
}
template.getTemplateProvisionStrategy().success();
return agentNode;
}
} finally {
releaseLockForAgent(agentNode);
}
}), template.getNoOfParallelJobs()));
}
} catch (Exception e) {
// Couldn't bring the node back online. Mark it as needing deletion
LOGGER.log(Level.WARNING, String.format("Failed to reuse agent computer %s", agentComputer.getName()), e);
azureComputer.setAcceptingTasks(false);
agentNode.setCleanUpAction(CleanUpAction.DEFAULT, Messages._Shutdown_Agent_Failed_To_Revive());
}
}
}
}
// provision new nodes if required
if (numberOfAgents > 0) {
if (template.getMaximumDeploymentSize() > 0 && numberOfAgents > template.getMaximumDeploymentSize()) {
LOGGER.log(Level.FINE, "Setting size of deployment from {0} to {1} nodes, according to template's maximum deployment size", new Object[] { numberOfAgents, template.getMaximumDeploymentSize() });
numberOfAgents = template.getMaximumDeploymentSize();
}
try {
// Determine how many agents we can actually provision from here and
// adjust our count (before deployment to avoid races)
int adjustedNumberOfAgents = adjustVirtualMachineCount(numberOfAgents, template.getMaxVirtualMachinesLimit());
if (adjustedNumberOfAgents == 0) {
LOGGER.log(Level.INFO, "Not able to create {0} nodes, at or above maximum VM count of {1} and already {2} VM(s)", new Object[] { numberOfAgents, determineLimit(template.getMaxVirtualMachinesLimit()), getApproximateVirtualMachineCount() });
return plannedNodes;
} else if (adjustedNumberOfAgents < numberOfAgents) {
LOGGER.log(Level.INFO, "Able to create new nodes, but can only create {0} (desired {1})", new Object[] { adjustedNumberOfAgents, numberOfAgents });
}
doProvision(adjustedNumberOfAgents, plannedNodes, template);
// wait for deployment completion and then check for created nodes
} catch (Exception e) {
LOGGER.log(Level.SEVERE, String.format("Failure provisioning agents about '%s'", template.getLabels()), e);
}
}
LOGGER.log(Level.INFO, "{0} planned node(s)", plannedNodes.size());
return plannedNodes;
}
use of hudson.slaves.NodeProvisioner.PlannedNode in project azure-vm-agents-plugin by jenkinsci.
the class AzureVMCloud method doProvision.
public void doProvision(final int numberOfNewAgents, List<PlannedNode> plannedNodes, final AzureVMAgentTemplate template, final boolean isProvisionOutside) {
Callable<AzureVMDeploymentInfo> callableTask = new Callable<AzureVMDeploymentInfo>() {
@Override
public AzureVMDeploymentInfo call() throws AzureCloudException {
try {
return template.provisionAgents(new StreamTaskListener(System.out, Charset.defaultCharset()), numberOfNewAgents);
} catch (AzureCloudException e) {
throw e;
} catch (Exception e) {
throw AzureCloudException.create(e);
}
}
};
final Future<AzureVMDeploymentInfo> deploymentFuture = getThreadPool().submit(callableTask);
for (int i = 0; i < numberOfNewAgents; i++) {
final int index = i;
final ProvisioningActivity.Id provisioningId = new ProvisioningActivity.Id(this.name, template.getTemplateName());
plannedNodes.add(new TrackedPlannedNode(provisioningId, template.getNoOfParallelJobs(), Computer.threadPoolForRemoting.submit(new Callable<Node>() {
@Override
public Node call() throws AzureCloudException {
// Wait for the future to complete
try {
// Only lock for pool maintaining.
PoolLock.provisionLock(template);
if (isProvisionOutside) {
CloudStatistics.ProvisioningListener.get().onStarted(provisioningId);
}
AzureVMDeploymentInfo info;
try {
info = deploymentFuture.get();
} catch (InterruptedException | ExecutionException e) {
handleFailure(template, null, e, FailureStage.DEPLOYMENT);
throw AzureCloudException.create(e);
}
final String deploymentName = info.getDeploymentName();
final String vmBaseName = info.getVmBaseName();
final String vmName = String.format("%s%d", vmBaseName, index);
AzureVMAgent agent;
try {
agent = createProvisionedAgent(provisioningId, template, vmName, deploymentName);
} catch (AzureCloudException e) {
LOGGER.log(Level.SEVERE, String.format("Failure creating provisioned agent '%s'", vmName), e);
handleFailure(template, vmName, e, FailureStage.PROVISIONING);
throw e;
}
try {
LOGGER.log(Level.INFO, "Adding agent {0} to Jenkins nodes", agent.getNodeName());
// Place the node in blocked state while it starts.
try {
agent.blockCleanUpAction();
Jenkins.get().addNode(agent);
Computer computer = agent.toComputer();
if (agent.getAgentLaunchMethod().equalsIgnoreCase("SSH") && computer != null) {
computer.connect(false).get();
} else if (agent.getAgentLaunchMethod().equalsIgnoreCase("JNLP")) {
// Wait until node is online
waitUntilJNLPNodeIsOnline(agent);
}
} finally {
// Place node in default state, now can be
// dealt with by the cleanup task.
agent.clearCleanUpAction();
}
} catch (Exception e) {
LOGGER.log(Level.SEVERE, String.format("Failure to in post-provisioning for '%s'", vmName), e);
handleFailure(template, vmName, e, FailureStage.POSTPROVISIONING);
// Remove the node from jenkins
try {
Jenkins.get().removeNode(agent);
} catch (IOException nodeRemoveEx) {
LOGGER.log(Level.SEVERE, String.format("Failure removing Jenkins node for '%s'", vmName), nodeRemoveEx);
// Do not throw to avoid it being recorded
}
throw AzureCloudException.create(e);
}
if (isProvisionOutside) {
CloudStatistics.ProvisioningListener.get().onComplete(provisioningId, agent);
}
template.getTemplateProvisionStrategy().success();
return agent;
} catch (AzureCloudException e) {
if (isProvisionOutside) {
CloudStatistics.ProvisioningListener.get().onFailure(provisioningId, e);
}
throw e;
} finally {
PoolLock.provisionUnlock(template);
}
}
private void handleFailure(AzureVMAgentTemplate template, String vmName, Exception e, FailureStage stage) {
// Attempt to terminate whatever was created if any
if (vmName != null) {
try {
getServiceDelegate().terminateVirtualMachine(vmName, template.getResourceGroupName());
} catch (AzureCloudException terminateEx) {
LOGGER.log(Level.SEVERE, String.format("Failure terminating previous failed agent '%s'", vmName), terminateEx);
// Do not throw to avoid it being recorded
}
}
template.retrieveAzureCloudReference().adjustVirtualMachineCount(-1, template.getMaxVirtualMachinesLimit());
// Update the template status given this new issue.
template.handleTemplateProvisioningFailure(e.getMessage(), stage);
}
})));
}
}
Aggregations