Search code examples
jenkinscontinuous-integrationoffline

Check if Jenkins node is online for the job, otherwise send email alert


Having the Jenkins job dedicated to special node I'd like to have a notification if the job can't be run because the node is offline. Is it possible to set up this functionality?

In other words, the default Jenkins behavior is waiting for the node if the job has been started when the node is offline ('pending' job status). I want to fail (or don't start at all) the job in this case and send 'node offline' mail.

This node checking stuff should be inside the job because the job is executed rarely and I don't care if the node is offline when it's not needed for the job. I've tried external node watching plugin, but it doesn't do exactly what I want - it triggers emails every time the node goes offline and it's redundant in my case.


Solution

  • I don't think checking if the node is available can be done inside the job (e.g JobX) you want to run. The act of checking, specifically for your JobX at time of execution, will itself need a job to run - I don't know of a plugin/configuration option that'll do this. JobX can't check if the node is free for JobX.

    I use a lot of flow jobs (in process of converting to pipeline logic) where JobA will trigger the JobB, thus JobA could run on master check the node for JobB, JobX in your case, triggering it if up.

    JobA would need to be a freestyle job and run a 'execute system groovy script > Groovy command' build step. The groovy code below is pulled together from a number of working examples, so untested:

    import hudson.model.*;
    import hudson.AbortException;
    import java.util.concurrent.CancellationException;
    
    
    def allNodes = jenkins.model.Jenkins.instance.nodes
    def triggerJob = false
    for (node in allNodes) {
      if ( node.getComputer().isOnline() && node.nodeName == "special_node" ) {
        println node.nodeName + " " + node.getComputer().countBusy() + " " + node.getComputer().getOneOffExecutors().size
        triggerJob = true
        break
      }
    }
    
    if (triggerJob) {
        println("triggering child build as node available")
        def job = Hudson.instance.getJob('JobB')
        def anotherBuild
        try {
            def params = [
              new StringParameterValue('ParamOne', '123'),
            ]
            def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
            anotherBuild = future.get()
        } catch (CancellationException x) {
            throw new AbortException("${job.fullDisplayName} aborted.")
        }
    
    } else {    
        println("failing parent build as node not available")
        build.getExecutor().interrupt(hudson.model.Result.FAILURE)
        throw new InterruptedException()
    }
    

    To get the node offline email, you could just trigger a post build action to send emails on failure.