To remove all offline nodes, adjust the script below and run doDelete () only on slaves, where isOffline () is true or isOnline () is false. If you want to delete all nodes (be careful), do not use the following if statement :
if ( aSlave.name.indexOf(slaveStartsWith) == 0) {
I also ignore the slave (if you want ALWAYS ignore the slave for deletion). It can be expanded to use a list of slaves to ignore.
In any case, the script will gracefully remove any Jenkins node slaves that start with the given name (so that you have more control), and it will be marked as offline (asap), but delete it only after all the tasks on this slave (s) will be / completed. I think I should share here.
Using the Jenkins Scriptler Plugin, you can import / upload / run this script: https://github.com/gigaaks/jenkins-scripts/blob/7eaf41348e886db108bad9a72f876c3827085418/scriptler/disableSlaveNodeStartsWith.groovy
/*** BEGIN META { "name" : "Disable Jenkins Hudson slaves nodes gracefully for all slaves starting with a given value", "comment" : "Disables Jenkins Hudson slave nodes gracefully - waits until running jobs are complete.", "parameters" : [ 'slaveStartsWith'], "core": "1.350", "authors" : [ { name : "GigaAKS" }, { name : "Arun Sangal" } ] } END META**/ // This scriptler script will mark Jenkins slave nodes offline for all slaves which starts with a given value. // It will wait for any slave nodes which are running any job(s) and then delete them. // It requires only one parameter named: slaveStartsWith and value can be passed as: "swarm-". import java.util.* import jenkins.model.* import hudson.model.* import hudson.slaves.* def atleastOneSlaveRunnning = true; def time = new Date().format("HH:mm MM/dd/yy z",TimeZone.getTimeZone("EST")) while (atleastOneSlaveRunnning) { //First thing - set the flag to false. atleastOneSlaveRunnning = false; time = new Date().format("HH:mm MM/dd/yy z",TimeZone.getTimeZone("EST")) for (aSlave in hudson.model.Hudson.instance.slaves) { println "-- Time: " + time; println "" //Dont do anything if the slave name is "ansible01" if ( aSlave.name == "ansible01" ) { continue; } if ( aSlave.name.indexOf(slaveStartsWith) == 0) { println "Active slave: " + aSlave.name; println('\tcomputer.isOnline: ' + aSlave.getComputer().isOnline()); println('\tcomputer.countBusy: ' + aSlave.getComputer().countBusy()); println "" if ( aSlave.getComputer().isOnline()) { aSlave.getComputer().setTemporarilyOffline(true,null); println('\tcomputer.isOnline: ' + aSlave.getComputer().isOnline()); println "" } if ( aSlave.getComputer().countBusy() == 0 ) { time = new Date().format("HH:mm MM/dd/yy z",TimeZone.getTimeZone("EST")) println("-- Shutting down node: " + aSlave.name + " at " + time); aSlave.getComputer().doDoDelete(); } else { atleastOneSlaveRunnning = true; } } } //Sleep 60 seconds if(atleastOneSlaveRunnning) { println "" println "------------------ sleeping 60 seconds -----------------" sleep(60*1000); println "" } }
Now I can create a free-style jenkins work, use the Scriptler script in the build action and use the script above to gracefully remove the slaves starting with the given name (the job parameter is passed to the script script).
If you are fast enough to receive the following error message, it means that you ran or called the Scriptler script (as shown above) in the task and the limited task to run on a non-master aka node / slave machine. Scriptler SYSTEM scripts Groovy scripts , that is, they must be run on the Jenkins master JVM in order to access / configure all Jenkins resources. To fix the following problem, you can create a task ( limit its execution on the main server , i.e. JVM Jenkins), which will simply take one parameter for the script scripter and call this task from the first (how to start a project / task and block until the task is completed ):
21:42:43 Execution of script [disableSlaveNodesWithPattern.groovy] failed - java.lang.NullPointerException: Cannot get property 'slaves' on null objectorg.jenkinsci.plugins.scriptler.util.GroovyScript$ScriptlerExecutionException: java.lang.NullPointerException: Cannot get property 'slaves' on null object 21:42:43 at org.jenkinsci.plugins.scriptler.util.GroovyScript.call(GroovyScript.java:131) 21:42:43 at hudson.remoting.UserRequest.perform(UserRequest.java:118) 21:42:43 at hudson.remoting.UserRequest.perform(UserRequest.java:48) 21:42:43 at hudson.remoting.Request$2.run(Request.java:328) 21:42:43 at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72) 21:42:43 at java.util.concurrent.FutureTask.run(FutureTask.java:266) 21:42:43 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 21:42:43 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 21:42:43 at java.lang.Thread.run(Thread.java:745) 21:42:43 Caused by: java.lang.NullPointerException: Cannot get property 'slaves' on null object
i.e. If you have a Scriptler script running in the task (which is not running on the MASTER Jenkins / JVM machine), then an error will come, and to solve it, create the task "disableSlaveNodesStartsWith" and limit its work to the wizard (the safer side) and calling the Scriptler script and pass the parameter to the / script job.
Now, from another task, call this task:
