Search in sources :

Example 1 with PlannedNode

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;
}
Also used : PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) Node(hudson.model.Node) ArrayList(java.util.ArrayList)

Example 2 with PlannedNode

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();
}
Also used : IntStream(java.util.stream.IntStream) StringUtils(org.apache.commons.lang.StringUtils) CredentialsHelper(io.jenkins.plugins.orka.helpers.CredentialsHelper) DataBoundConstructor(org.kohsuke.stapler.DataBoundConstructor) StandardCredentials(com.cloudbees.plugins.credentials.common.StandardCredentials) Label(hudson.model.Label) QueryParameter(org.kohsuke.stapler.QueryParameter) CapacityHandler(io.jenkins.plugins.orka.helpers.CapacityHandler) Callable(java.util.concurrent.Callable) FormValidator(io.jenkins.plugins.orka.helpers.FormValidator) Computer(hudson.model.Computer) Level(java.util.logging.Level) ConfigurationResponse(io.jenkins.plugins.orka.client.ConfigurationResponse) Future(java.util.concurrent.Future) OrkaVM(io.jenkins.plugins.orka.client.OrkaVM) Extension(hudson.Extension) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) OrkaClientProxyFactory(io.jenkins.plugins.orka.helpers.OrkaClientProxyFactory) ListBoxModel(hudson.util.ListBoxModel) DeploymentResponse(io.jenkins.plugins.orka.client.DeploymentResponse) FormValidation(hudson.util.FormValidation) Descriptor(hudson.model.Descriptor) Collection(java.util.Collection) IOException(java.io.IOException) UUID(java.util.UUID) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Node(hudson.model.Node) List(java.util.List) POST(org.kohsuke.stapler.verb.POST) Cloud(hudson.slaves.Cloud) Collections(java.util.Collections) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) Future(java.util.concurrent.Future) Callable(java.util.concurrent.Callable) IOException(java.io.IOException)

Example 3 with PlannedNode

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();
    }
}
Also used : ArrayList(java.util.ArrayList) FormException(hudson.model.Descriptor.FormException) IOException(java.io.IOException) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode)

Example 4 with PlannedNode

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;
}
Also used : SlaveComputer(hudson.slaves.SlaveComputer) TrackedPlannedNode(org.jenkinsci.plugins.cloudstats.TrackedPlannedNode) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) SlaveComputer(hudson.slaves.SlaveComputer) Computer(hudson.model.Computer) ServletException(javax.servlet.ServletException) AzureCloudException(com.microsoft.azure.vmagent.exceptions.AzureCloudException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException)

Example 5 with PlannedNode

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);
            }
        })));
    }
}
Also used : StreamTaskListener(hudson.util.StreamTaskListener) TrackedPlannedNode(org.jenkinsci.plugins.cloudstats.TrackedPlannedNode) Node(hudson.model.Node) TrackedPlannedNode(org.jenkinsci.plugins.cloudstats.TrackedPlannedNode) PlannedNode(hudson.slaves.NodeProvisioner.PlannedNode) AzureCloudException(com.microsoft.azure.vmagent.exceptions.AzureCloudException) IOException(java.io.IOException) Callable(java.util.concurrent.Callable) ServletException(javax.servlet.ServletException) AzureCloudException(com.microsoft.azure.vmagent.exceptions.AzureCloudException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ProvisioningActivity(org.jenkinsci.plugins.cloudstats.ProvisioningActivity) SlaveComputer(hudson.slaves.SlaveComputer) Computer(hudson.model.Computer) FailureStage(com.microsoft.azure.vmagent.util.FailureStage)

Aggregations

PlannedNode (hudson.slaves.NodeProvisioner.PlannedNode)5 IOException (java.io.IOException)4 Computer (hudson.model.Computer)3 Node (hudson.model.Node)3 ArrayList (java.util.ArrayList)3 AzureCloudException (com.microsoft.azure.vmagent.exceptions.AzureCloudException)2 SlaveComputer (hudson.slaves.SlaveComputer)2 Callable (java.util.concurrent.Callable)2 ExecutionException (java.util.concurrent.ExecutionException)2 ServletException (javax.servlet.ServletException)2 TrackedPlannedNode (org.jenkinsci.plugins.cloudstats.TrackedPlannedNode)2 StandardCredentials (com.cloudbees.plugins.credentials.common.StandardCredentials)1 FailureStage (com.microsoft.azure.vmagent.util.FailureStage)1 Extension (hudson.Extension)1 Descriptor (hudson.model.Descriptor)1 FormException (hudson.model.Descriptor.FormException)1 Label (hudson.model.Label)1 Cloud (hudson.slaves.Cloud)1 FormValidation (hudson.util.FormValidation)1 ListBoxModel (hudson.util.ListBoxModel)1