From 9d4155e6d710d0af814d580cedc213b678988136 Mon Sep 17 00:00:00 2001 From: Frano Stanisic Date: Wed, 2 Dec 2015 12:24:59 +1300 Subject: [PATCH 01/12] First commit, consolidating all changes made offline. Now clears using jenkins API and thersholds. --- .../java/org/jenkinsci/plugin/Diskcheck.java | 92 ++++++++++--------- .../java/org/jenkinsci/plugin/PluginImpl.java | 17 +++- .../jenkinsci/plugin/PluginImpl/config.jelly | 8 +- 3 files changed, 67 insertions(+), 50 deletions(-) mode change 100644 => 100755 src/main/java/org/jenkinsci/plugin/Diskcheck.java diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java old mode 100644 new mode 100755 index 0de2de4..397bc78 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -2,6 +2,7 @@ import hudson.AbortException; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.model.BuildListener; import hudson.model.AbstractBuild; @@ -10,23 +11,20 @@ import hudson.tasks.BuildWrapper; import hudson.node_monitors.*; import hudson.model.Node; -import hudson.model.Result; -import hudson.tasks.BatchFile; -import hudson.tasks.CommandInterpreter; -import hudson.tasks.Shell; import org.kohsuke.stapler.DataBoundConstructor; -import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.net.UnknownHostException; +import java.util.List; /** * Class to allow any build step to be performed before the SCM checkout occurs. * - * @author Manoj Thakkar + * @author Manoj Thakkar edited by Frano Stanisic * */ @@ -35,12 +33,26 @@ public class Diskcheck extends BuildWrapper { public final boolean failOnError; - + + public static FilePath lastFileModified(PrintStream log, FilePath dir) throws UnknownHostException, IOException, InterruptedException { + log.println("lastFileModified call made"); + log.println("dir passed was " + dir); + List files = dir.listDirectories(); + long lastMod = Long.MAX_VALUE; + FilePath choice = null; + for (FilePath file : files) { + if (file.lastModified() < lastMod) { + choice = file; + lastMod = file.lastModified(); + } + } + return choice; + } /** * Constructor taking a list of buildsteps to use. * * @param buildstep - * list of but steps configured in the UI + * list of build steps configured in the UI */ @DataBoundConstructor public Diskcheck(boolean failOnError) { @@ -63,7 +75,7 @@ public Environment setUp(AbstractBuild build, Launcher launcher, } /** - * Overridden precheckout step, this is where wedo all the work. + * Overridden precheckout step, this is where we do all the work. * * Checks to make sure we have some buildsteps set, and then calls the * prebuild and perform on all of them. @@ -79,13 +91,13 @@ public Environment setUp(AbstractBuild build, Launcher launcher, public Descriptor getDescriptor() { return (Descriptor) super.getDescriptor(); } + @Override public void preCheckout(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { PrintStream log = listener.getLogger(); // Default value of disk space check is 1Gb - int SpaceThreshold; - SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); + int SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); log.println("Disk space threshold is set to :" + SpaceThreshold + "Gb"); @@ -121,15 +133,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, System.exit(0); } - long size=0; - try - { - size = DiskSpaceMonitor.DESCRIPTOR.get(Comp).size; - } - catch(NullPointerException e ){ - log.println("Could not get Slave Information , Exiting Disk check for this slave"); - System.exit(0); - } + long size = build.getWorkspace().getParent().getUsableDiskSpace(); int roundedSize = (int) (size / (1024 * 1024 * 1024)); log.println("Total Disk Space Available is: " + roundedSize + "Gb"); @@ -141,31 +145,29 @@ public void preCheckout(AbstractBuild build, Launcher launcher, if (PluginImpl.getInstance().isDiskrecyclerenabled()) { if (roundedSize < SpaceThreshold) { - log.println("Disk Recycler is Enabled so I am going to wipe off the workspace Directory Now "); - String mycommand = "echo $WORKSPACE; rm -rf $WORKSPACE/../; df -k ."; - String mywincommand = "echo Deleting file from %WORKSPACE% && Del /R %WORKSPACE%"; - - /** - * This method will return the command intercepter as per the - * node OS - * - * @param launcher - * @param script - * @return CommandInterpreter - */ - CommandInterpreter runscript; - if (launcher.isUnix()) - runscript = new Shell(mycommand); - else - runscript = new BatchFile(mywincommand); - - Result result = runscript.perform(build, launcher, listener) ? Result.SUCCESS - : Result.FAILURE; - - if (result.toString() == "FAILURE") { - throw new AbortException( - "Something went wrong while deleting Files , Please check the error message above"); - } + int clearUntil = PluginImpl.getInstance().getClearuntil(); + if (clearUntil < SpaceThreshold){ + throw new AbortException( + "Your space clearing thresholds are the wrong way around." + + " Edit them and run this job again."); + } + // Not enough room on slave, start clearing until threshhold met. + while(roundedSize < clearUntil){ + FilePath lastUsedDir = lastFileModified(log, build.getWorkspace().getParent()); + if (lastUsedDir == null){ + throw new AbortException( + "There is nothing left in the workspace, but room still needs to be made." + + " Either the thresholds are wrong, or there is a major issue on the slave."); + } + log.println("Workspace selected was " + lastUsedDir.getRemote() + ". Goodbye!"); + // Use Jenkins internal api to delete files recursively. + // On any errors the exception will bubble up causing the + // build to fail. + lastUsedDir.deleteRecursive(); + size = build.getWorkspace().getParent().getUsableDiskSpace(); + roundedSize = (int) (size / (1024 * 1024 * 1024)); + log.println("New disk space available is: " + roundedSize); + } } } diff --git a/src/main/java/org/jenkinsci/plugin/PluginImpl.java b/src/main/java/org/jenkinsci/plugin/PluginImpl.java index f8c44cd..e071047 100755 --- a/src/main/java/org/jenkinsci/plugin/PluginImpl.java +++ b/src/main/java/org/jenkinsci/plugin/PluginImpl.java @@ -20,6 +20,7 @@ public class PluginImpl extends Plugin{ private boolean diskrecyclerenabled; private int spacecheck; + private int clearuntil; /** * Returns the singleton instance. @@ -46,7 +47,8 @@ public void configure(StaplerRequest req, JSONObject formData) throws IOException, ServletException, FormException { formData=formData.getJSONObject("disk-check"); spacecheck=formData.getInt("spacecheck"); - diskrecyclerenabled=formData.getBoolean("diskrecyclerenabled"); + clearuntil=formData.getInt("clearuntil"); + diskrecyclerenabled=formData.getBoolean("diskrecyclerenabled"); save(); super.configure(req, formData); @@ -64,9 +66,18 @@ public int getSpacecheck() return spacecheck; } - public void setSpacecheck(int spaceheck) + public void setSpacecheck(int spaceCheck) { - this.spacecheck = spacecheck; + this.spacecheck = spaceCheck; +} + public int getClearuntil() + { + return clearuntil; + } + + public void setClearuntil(int clearUntil) + { + this.clearuntil = clearUntil; } public boolean isDiskrecyclerenabled() { diff --git a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly index 50391e0..169b51d 100755 --- a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly +++ b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly @@ -16,9 +16,13 @@ description="Check if you need disk to be checked and recycled if low in space "> - + + + + \ No newline at end of file From 1b20849ac29731bdffd8ca74832337382fd64236 Mon Sep 17 00:00:00 2001 From: franostanisicserato Date: Wed, 2 Dec 2015 12:28:30 +1300 Subject: [PATCH 02/12] First commit, consolidating all changes made offline. Now clears using jenkins API and thresholds. --- .../java/org/jenkinsci/plugin/Diskcheck.java | 92 ++++++++++--------- .../java/org/jenkinsci/plugin/PluginImpl.java | 17 +++- .../jenkinsci/plugin/PluginImpl/config.jelly | 8 +- 3 files changed, 67 insertions(+), 50 deletions(-) mode change 100644 => 100755 src/main/java/org/jenkinsci/plugin/Diskcheck.java diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java old mode 100644 new mode 100755 index 0de2de4..397bc78 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -2,6 +2,7 @@ import hudson.AbortException; import hudson.Extension; +import hudson.FilePath; import hudson.Launcher; import hudson.model.BuildListener; import hudson.model.AbstractBuild; @@ -10,23 +11,20 @@ import hudson.tasks.BuildWrapper; import hudson.node_monitors.*; import hudson.model.Node; -import hudson.model.Result; -import hudson.tasks.BatchFile; -import hudson.tasks.CommandInterpreter; -import hudson.tasks.Shell; import org.kohsuke.stapler.DataBoundConstructor; -import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.net.UnknownHostException; +import java.util.List; /** * Class to allow any build step to be performed before the SCM checkout occurs. * - * @author Manoj Thakkar + * @author Manoj Thakkar edited by Frano Stanisic * */ @@ -35,12 +33,26 @@ public class Diskcheck extends BuildWrapper { public final boolean failOnError; - + + public static FilePath lastFileModified(PrintStream log, FilePath dir) throws UnknownHostException, IOException, InterruptedException { + log.println("lastFileModified call made"); + log.println("dir passed was " + dir); + List files = dir.listDirectories(); + long lastMod = Long.MAX_VALUE; + FilePath choice = null; + for (FilePath file : files) { + if (file.lastModified() < lastMod) { + choice = file; + lastMod = file.lastModified(); + } + } + return choice; + } /** * Constructor taking a list of buildsteps to use. * * @param buildstep - * list of but steps configured in the UI + * list of build steps configured in the UI */ @DataBoundConstructor public Diskcheck(boolean failOnError) { @@ -63,7 +75,7 @@ public Environment setUp(AbstractBuild build, Launcher launcher, } /** - * Overridden precheckout step, this is where wedo all the work. + * Overridden precheckout step, this is where we do all the work. * * Checks to make sure we have some buildsteps set, and then calls the * prebuild and perform on all of them. @@ -79,13 +91,13 @@ public Environment setUp(AbstractBuild build, Launcher launcher, public Descriptor getDescriptor() { return (Descriptor) super.getDescriptor(); } + @Override public void preCheckout(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { PrintStream log = listener.getLogger(); // Default value of disk space check is 1Gb - int SpaceThreshold; - SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); + int SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); log.println("Disk space threshold is set to :" + SpaceThreshold + "Gb"); @@ -121,15 +133,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, System.exit(0); } - long size=0; - try - { - size = DiskSpaceMonitor.DESCRIPTOR.get(Comp).size; - } - catch(NullPointerException e ){ - log.println("Could not get Slave Information , Exiting Disk check for this slave"); - System.exit(0); - } + long size = build.getWorkspace().getParent().getUsableDiskSpace(); int roundedSize = (int) (size / (1024 * 1024 * 1024)); log.println("Total Disk Space Available is: " + roundedSize + "Gb"); @@ -141,31 +145,29 @@ public void preCheckout(AbstractBuild build, Launcher launcher, if (PluginImpl.getInstance().isDiskrecyclerenabled()) { if (roundedSize < SpaceThreshold) { - log.println("Disk Recycler is Enabled so I am going to wipe off the workspace Directory Now "); - String mycommand = "echo $WORKSPACE; rm -rf $WORKSPACE/../; df -k ."; - String mywincommand = "echo Deleting file from %WORKSPACE% && Del /R %WORKSPACE%"; - - /** - * This method will return the command intercepter as per the - * node OS - * - * @param launcher - * @param script - * @return CommandInterpreter - */ - CommandInterpreter runscript; - if (launcher.isUnix()) - runscript = new Shell(mycommand); - else - runscript = new BatchFile(mywincommand); - - Result result = runscript.perform(build, launcher, listener) ? Result.SUCCESS - : Result.FAILURE; - - if (result.toString() == "FAILURE") { - throw new AbortException( - "Something went wrong while deleting Files , Please check the error message above"); - } + int clearUntil = PluginImpl.getInstance().getClearuntil(); + if (clearUntil < SpaceThreshold){ + throw new AbortException( + "Your space clearing thresholds are the wrong way around." + + " Edit them and run this job again."); + } + // Not enough room on slave, start clearing until threshhold met. + while(roundedSize < clearUntil){ + FilePath lastUsedDir = lastFileModified(log, build.getWorkspace().getParent()); + if (lastUsedDir == null){ + throw new AbortException( + "There is nothing left in the workspace, but room still needs to be made." + + " Either the thresholds are wrong, or there is a major issue on the slave."); + } + log.println("Workspace selected was " + lastUsedDir.getRemote() + ". Goodbye!"); + // Use Jenkins internal api to delete files recursively. + // On any errors the exception will bubble up causing the + // build to fail. + lastUsedDir.deleteRecursive(); + size = build.getWorkspace().getParent().getUsableDiskSpace(); + roundedSize = (int) (size / (1024 * 1024 * 1024)); + log.println("New disk space available is: " + roundedSize); + } } } diff --git a/src/main/java/org/jenkinsci/plugin/PluginImpl.java b/src/main/java/org/jenkinsci/plugin/PluginImpl.java index f8c44cd..e071047 100755 --- a/src/main/java/org/jenkinsci/plugin/PluginImpl.java +++ b/src/main/java/org/jenkinsci/plugin/PluginImpl.java @@ -20,6 +20,7 @@ public class PluginImpl extends Plugin{ private boolean diskrecyclerenabled; private int spacecheck; + private int clearuntil; /** * Returns the singleton instance. @@ -46,7 +47,8 @@ public void configure(StaplerRequest req, JSONObject formData) throws IOException, ServletException, FormException { formData=formData.getJSONObject("disk-check"); spacecheck=formData.getInt("spacecheck"); - diskrecyclerenabled=formData.getBoolean("diskrecyclerenabled"); + clearuntil=formData.getInt("clearuntil"); + diskrecyclerenabled=formData.getBoolean("diskrecyclerenabled"); save(); super.configure(req, formData); @@ -64,9 +66,18 @@ public int getSpacecheck() return spacecheck; } - public void setSpacecheck(int spaceheck) + public void setSpacecheck(int spaceCheck) { - this.spacecheck = spacecheck; + this.spacecheck = spaceCheck; +} + public int getClearuntil() + { + return clearuntil; + } + + public void setClearuntil(int clearUntil) + { + this.clearuntil = clearUntil; } public boolean isDiskrecyclerenabled() { diff --git a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly index 50391e0..169b51d 100755 --- a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly +++ b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly @@ -16,9 +16,13 @@ description="Check if you need disk to be checked and recycled if low in space "> - + + + + \ No newline at end of file From 3bc8003da7d6c7cf190d43c4957349ae45a237de Mon Sep 17 00:00:00 2001 From: franostanisicserato Date: Wed, 2 Dec 2015 12:35:26 +1300 Subject: [PATCH 03/12] Forgot to add updated pom. Wwops. --- pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1dd5808..96b8b47 100755 --- a/pom.xml +++ b/pom.xml @@ -3,12 +3,12 @@ org.jenkins-ci.plugins plugin - 1.532 + 1.542 org.jenkins-ci.plugins diskcheck - 0.27 + 0.28 hpi @@ -46,6 +46,8 @@ + + repo.jenkins-ci.org From 629432c64330f11f32e6395c3acbdfa43801450f Mon Sep 17 00:00:00 2001 From: franostanisicserato Date: Wed, 2 Dec 2015 15:20:34 +1300 Subject: [PATCH 04/12] Provided functionality for clear all. --- src/main/java/org/jenkinsci/plugin/Diskcheck.java | 6 ++++++ .../resources/org/jenkinsci/plugin/PluginImpl/config.jelly | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java index 397bc78..8208b3c 100755 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -146,6 +146,11 @@ public void preCheckout(AbstractBuild build, Launcher launcher, if (PluginImpl.getInstance().isDiskrecyclerenabled()) { if (roundedSize < SpaceThreshold) { int clearUntil = PluginImpl.getInstance().getClearuntil(); + if (clearUntil == 0){ + log.println("clearUntil set to 0, clearing everything..."); + build.getWorkspace().getParent().deleteRecursive(); + log.println("aaaaaaaaand it's gone."); + }else{ if (clearUntil < SpaceThreshold){ throw new AbortException( "Your space clearing thresholds are the wrong way around." @@ -169,6 +174,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, log.println("New disk space available is: " + roundedSize); } } + } } log.println("Running Prebuild steps"); diff --git a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly index 169b51d..629fc5e 100755 --- a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly +++ b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly @@ -21,7 +21,7 @@ + description="Enter the disk space(in GB integer only) that should be available on when the above trigger is hit. Default is 2 Gb. If this is set to 0, everything will be deleted."> From 7e13e1099f507d607dc56eeaea77c93b7f66573a Mon Sep 17 00:00:00 2001 From: franostanisicserato Date: Tue, 8 Dec 2015 13:30:22 +1300 Subject: [PATCH 05/12] Code cleanup: indenting, log messages and other cleanups from other pull requests. --- pom.xml | 5 + .../java/org/jenkinsci/plugin/Diskcheck.java | 328 ++++++++---------- .../java/org/jenkinsci/plugin/PluginImpl.java | 117 +++---- 3 files changed, 212 insertions(+), 238 deletions(-) diff --git a/pom.xml b/pom.xml index 96b8b47..d224743 100755 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,11 @@ Manoj Thakkar mthakkar@cloudera.com + + fsta + Frano Stanisic + frano.stanisic@serato.com + diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java index 8208b3c..8fe2779 100755 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -19,194 +19,172 @@ import java.net.UnknownHostException; import java.util.List; - - /** * Class to allow any build step to be performed before the SCM checkout occurs. - * - * @author Manoj Thakkar edited by Frano Stanisic + * + * @author Manoj Thakkar + * @author Frano Stanisic (8th Decemeber 2015, updated deletion to use Jenkins API/only delete files up to a threshhold) * */ +public class Diskcheck extends BuildWrapper { + public final boolean failOnError; + + public static FilePath lastFileModified(PrintStream log, FilePath dir) throws UnknownHostException, IOException, InterruptedException { + log.println("Determining file to delete ..."); + List files = dir.listDirectories(); + long lastMod = Long.MAX_VALUE; + FilePath choice = null; + for (FilePath file : files) { + if (file.lastModified() < lastMod) { + choice = file; + lastMod = file.lastModified(); + } + } + return choice; + } + + /** + * Constructor taking a list of buildsteps to use. + * + * @param buildstep list of build steps configured in the UI + */ + @DataBoundConstructor + public Diskcheck(boolean failOnError) { + this.failOnError = failOnError; + } + + /** + * Overridden setup returns a noop class as we don't want to add anything + * here. + * + * @param build + * @param launcher + * @param listener + * @return noop Environment class + */ + @Override + public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { + return new NoopEnv(); + } + + /** + * Overridden precheckout step, this is where we do all the work. + * + * Checks to make sure we have some buildsteps set, and then calls the + * prebuild and perform on all of them. + * + * @todo handle build steps failure in some sort of reasonable way + * + * @param build + * @param launcher + * @param listener + */ + @Override + public Descriptor getDescriptor() { + return (Descriptor) super.getDescriptor(); + } + + @Override + public void preCheckout(AbstractBuild build, Launcher launcher, + BuildListener listener) throws IOException, InterruptedException { + PrintStream log = listener.getLogger(); + // Default value of disk space check is 1GB + int SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); + + log.println("Disk space upper threshold is set to :" + SpaceThreshold + "GB"); + log.println("Checking disk space now ..."); + + // Touch workspace so that it is created on first time. + if (!build.getWorkspace().exists()) { + build.getWorkspace().mkdirs(); + } -public class Diskcheck extends BuildWrapper { + Node node1 = build.getBuiltOn(); + Computer Comp = node1.toComputer(); + String NodeName = build.getBuiltOnStr(); + + // This new implementation doesn't even touch this, but given I + // am not 100% on what it does I have just left it here. + if (DiskSpaceMonitor.DESCRIPTOR.get(Comp) == null) { + log.println("No slave data available, waiting and retrying ..."); + Thread.sleep(10000); + if (DiskSpaceMonitor.DESCRIPTOR.get(Comp) == null) { + log.println("Could not retrieve slave data, exiting disk check for this slave."); + } + System.exit(0); + } + // End unsure bit. + long size = build.getWorkspace().getParent().getUsableDiskSpace(); + int roundedSize = (int) (size / (1024 * 1024 * 1024)); + log.println("Total disk space available is: " + roundedSize + "GB"); - public final boolean failOnError; - - public static FilePath lastFileModified(PrintStream log, FilePath dir) throws UnknownHostException, IOException, InterruptedException { - log.println("lastFileModified call made"); - log.println("dir passed was " + dir); - List files = dir.listDirectories(); - long lastMod = Long.MAX_VALUE; - FilePath choice = null; - for (FilePath file : files) { - if (file.lastModified() < lastMod) { - choice = file; - lastMod = file.lastModified(); + if ("".equals(NodeName)) { + NodeName = "master"; + } + + log.println("Node Name: " + NodeName); + boolean diskrecyclerenabled = PluginImpl.getInstance().isDiskrecyclerenabled(); + if (diskrecyclerenabled) { + if (roundedSize < SpaceThreshold) { + int clearUntil = PluginImpl.getInstance().getClearuntil(); + if (clearUntil == 0) { + log.println("clearUntil set to 0, clearing everything ..."); + // Jenkins api recursive delete, errors will cause a build failure. + build.getWorkspace().getParent().deleteRecursive(); + log.println("All workspaces deleted successfully."); + } else { + if (clearUntil < SpaceThreshold) { + throw new AbortException( + "Your space clearing thresholds are the wrong way around." + + " Edit them and run this job again."); + } + // Not enough room on slave, start clearing until threshhold met. + while (roundedSize < clearUntil) { + FilePath lastUsedDir = lastFileModified(log, build.getWorkspace().getParent()); + if (lastUsedDir == null) { + throw new AbortException( + "There is nothing left in the workspace, but room still needs to be made." + + " Either the thresholds are wrong, or there is an issue on the slave."); + } + log.println("Deleting workspace " + lastUsedDir.getRemote() + "."); + // Jenkins api recursive delete, errors will cause a build failure. + lastUsedDir.deleteRecursive(); + log.println("Workspace deleted."); + size = build.getWorkspace().getParent().getUsableDiskSpace(); + roundedSize = (int) (size / (1024 * 1024 * 1024)); + log.println("New disk space available is: " + roundedSize + "GB"); + } } } - return choice; - } - /** - * Constructor taking a list of buildsteps to use. - * - * @param buildstep - * list of build steps configured in the UI - */ - @DataBoundConstructor - public Diskcheck(boolean failOnError) { - this.failOnError = failOnError; - } - - /** - * Overridden setup returns a noop class as we don't want to add annything - * here. - * - * @param build - * @param launcher - * @param listener - * @return noop Environment class - */ - @Override - public Environment setUp(AbstractBuild build, Launcher launcher, - BuildListener listener) throws IOException, InterruptedException { - return new NoopEnv(); - } - - /** - * Overridden precheckout step, this is where we do all the work. - * - * Checks to make sure we have some buildsteps set, and then calls the - * prebuild and perform on all of them. - * - * @todo handle build steps failure in some sort of reasonable way - * - * @param build - * @param launcher - * @param listener - */ - - @Override - public Descriptor getDescriptor() { - return (Descriptor) super.getDescriptor(); - } - - @Override - public void preCheckout(AbstractBuild build, Launcher launcher, - BuildListener listener) throws IOException, InterruptedException { - PrintStream log = listener.getLogger(); -// Default value of disk space check is 1Gb - int SpaceThreshold = PluginImpl.getInstance().getSpacecheck(); - - - log.println("Disk space threshold is set to :" + SpaceThreshold + "Gb"); - log.println("Checking disk space Now "); - - /* touch workspace so that it is created on first time */ - if (!build.getWorkspace().exists()) { - build.getWorkspace().mkdirs(); - } - - Node node1 = build.getBuiltOn(); - Computer Comp = node1.toComputer(); - String NodeName = build.getBuiltOnStr(); - /* if (Comp.getChannel()==null) - { - log.println("Can not get slave infomration wait for 10 sec \n"); - Thread.sleep(10000); - if (Comp.getChannel()==null) - { - log.println("Waited long enough to get slave information exiting discheck for now \n"); - System.exit(0); - } - } - */ - - if ( DiskSpaceMonitor.DESCRIPTOR.get(Comp)== null ) - { log.println("No Slave Data available trying to get data from slave"); - Thread.sleep(10000); - if ( DiskSpaceMonitor.DESCRIPTOR.get(Comp)== null ) - - log.println(" Could not get Slave Information , Exiting Disk check for this slave"); - System.exit(0); + + log.println("Running prebuild steps ..."); + if (roundedSize < SpaceThreshold + && !diskrecyclerenabled) { + throw new AbortException( + "Disk space is too low, investigate prior to starting another build."); + } - - long size = build.getWorkspace().getParent().getUsableDiskSpace(); - int roundedSize = (int) (size / (1024 * 1024 * 1024)); - log.println("Total Disk Space Available is: " + roundedSize + "Gb"); - - if (build.getBuiltOnStr() == "") { - NodeName = "master"; - } - - log.println(" Node Name: " + NodeName); - - if (PluginImpl.getInstance().isDiskrecyclerenabled()) { - if (roundedSize < SpaceThreshold) { - int clearUntil = PluginImpl.getInstance().getClearuntil(); - if (clearUntil == 0){ - log.println("clearUntil set to 0, clearing everything..."); - build.getWorkspace().getParent().deleteRecursive(); - log.println("aaaaaaaaand it's gone."); - }else{ - if (clearUntil < SpaceThreshold){ - throw new AbortException( - "Your space clearing thresholds are the wrong way around." - + " Edit them and run this job again."); - } - // Not enough room on slave, start clearing until threshhold met. - while(roundedSize < clearUntil){ - FilePath lastUsedDir = lastFileModified(log, build.getWorkspace().getParent()); - if (lastUsedDir == null){ - throw new AbortException( - "There is nothing left in the workspace, but room still needs to be made." - + " Either the thresholds are wrong, or there is a major issue on the slave."); - } - log.println("Workspace selected was " + lastUsedDir.getRemote() + ". Goodbye!"); - // Use Jenkins internal api to delete files recursively. - // On any errors the exception will bubble up causing the - // build to fail. - lastUsedDir.deleteRecursive(); - size = build.getWorkspace().getParent().getUsableDiskSpace(); - roundedSize = (int) (size / (1024 * 1024 * 1024)); - log.println("New disk space available is: " + roundedSize); - } - } - } - } - - log.println("Running Prebuild steps"); - if (roundedSize < SpaceThreshold - && !(PluginImpl.getInstance().isDiskrecyclerenabled())) { - throw new AbortException( - "Disk Space is too low please look into it before starting a build"); - - } - } - - - @Extension - public static final class DescriptorImpl extends Descriptor { - - /** - * This human readable name is used in the configuration screen. - */ - public String getDisplayName() { - return "Check Disk Space"; - } - - - - public DescriptorImpl() { + } + + @Extension + public static final class DescriptorImpl extends Descriptor { + + /** + * This human readable name is used in the configuration screen. + */ + public String getDisplayName() { + return "Check Disk Space"; + } + + public DescriptorImpl() { load(); } - - } - - - class NoopEnv extends Environment { - } + } + + class NoopEnv extends Environment { + } } diff --git a/src/main/java/org/jenkinsci/plugin/PluginImpl.java b/src/main/java/org/jenkinsci/plugin/PluginImpl.java index e071047..4f1cd42 100755 --- a/src/main/java/org/jenkinsci/plugin/PluginImpl.java +++ b/src/main/java/org/jenkinsci/plugin/PluginImpl.java @@ -1,9 +1,6 @@ package org.jenkinsci.plugin; import hudson.Plugin; -import hudson.model.*; -import hudson.model.AbstractBuild; -import hudson.model.AbstractProject; import hudson.model.Descriptor.FormException; import hudson.model.Hudson; @@ -15,14 +12,13 @@ import org.kohsuke.stapler.StaplerRequest; -//import com.innorium.crystalline.plugins.model.ScannerJobProperty; +public class PluginImpl extends Plugin { -public class PluginImpl extends Plugin{ - private boolean diskrecyclerenabled; - private int spacecheck; - private int clearuntil; - - /** + private boolean diskrecyclerenabled; + private int spacecheck; + private int clearuntil; + + /** * Returns the singleton instance. * * @return the one. @@ -30,57 +26,52 @@ public class PluginImpl extends Plugin{ public static PluginImpl getInstance() { return Hudson.getInstance().getPlugin(PluginImpl.class); } - - @Override - public void start() throws Exception { - super.start(); - load(); - } - - @Override - public void stop() throws Exception { - super.stop(); - } - - @Override - public void configure(StaplerRequest req, JSONObject formData) - throws IOException, ServletException, FormException { - formData=formData.getJSONObject("disk-check"); - spacecheck=formData.getInt("spacecheck"); - clearuntil=formData.getInt("clearuntil"); - diskrecyclerenabled=formData.getBoolean("diskrecyclerenabled"); - - save(); - super.configure(req, formData); - - } - - - - public void setDiskrecyclerenabled(boolean diskrecyclerenabled) { - this.diskrecyclerenabled = diskrecyclerenabled; -} - - public int getSpacecheck() - { - return spacecheck; - } - - public void setSpacecheck(int spaceCheck) - { - this.spacecheck = spaceCheck; -} - public int getClearuntil() - { - return clearuntil; - } - - public void setClearuntil(int clearUntil) - { - this.clearuntil = clearUntil; -} - public boolean isDiskrecyclerenabled() { - return diskrecyclerenabled; - } -} \ No newline at end of file + @Override + public void start() throws Exception { + super.start(); + load(); + } + + @Override + public void stop() throws Exception { + super.stop(); + } + + @Override + public void configure(StaplerRequest req, JSONObject formData) + throws IOException, ServletException, FormException { + formData = formData.getJSONObject("disk-check"); + spacecheck = formData.getInt("spacecheck"); + clearuntil = formData.getInt("clearuntil"); + diskrecyclerenabled = formData.getBoolean("diskrecyclerenabled"); + + save(); + super.configure(req, formData); + + } + + public void setDiskrecyclerenabled(boolean diskrecyclerenabled) { + this.diskrecyclerenabled = diskrecyclerenabled; + } + + public int getSpacecheck() { + return spacecheck; + } + + public void setSpacecheck(int spaceCheck) { + this.spacecheck = spaceCheck; + } + + public int getClearuntil() { + return clearuntil; + } + + public void setClearuntil(int clearUntil) { + this.clearuntil = clearUntil; + } + + public boolean isDiskrecyclerenabled() { + return diskrecyclerenabled; + } +} From bb72a73f07869e7047392fa81400d1b557fc2645 Mon Sep 17 00:00:00 2001 From: Maxime Viargues Date: Thu, 26 Oct 2017 14:41:53 +1300 Subject: [PATCH 06/12] Fixed the plugin shutting down the entire Jenkins!!! This was happening when a slave was connecting and did not have any disk information, then the plugin was doing a system.exit()... --- src/main/java/org/jenkinsci/plugin/Diskcheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java index 8fe2779..fb2dfcc 100755 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -112,7 +112,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, if (DiskSpaceMonitor.DESCRIPTOR.get(Comp) == null) { log.println("Could not retrieve slave data, exiting disk check for this slave."); } - System.exit(0); + return; } // End unsure bit. From 1efb24866ed9f980e16581e8abafff99e0ec2b2e Mon Sep 17 00:00:00 2001 From: Maxime Viargues Date: Mon, 30 Oct 2017 14:06:01 +1300 Subject: [PATCH 07/12] Removed docstring warnings Removed unused and empty parameters. --- src/main/java/org/jenkinsci/plugin/Diskcheck.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java index fb2dfcc..49ce6a8 100755 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -46,8 +46,6 @@ public static FilePath lastFileModified(PrintStream log, FilePath dir) throws Un /** * Constructor taking a list of buildsteps to use. - * - * @param buildstep list of build steps configured in the UI */ @DataBoundConstructor public Diskcheck(boolean failOnError) { @@ -58,9 +56,6 @@ public Diskcheck(boolean failOnError) { * Overridden setup returns a noop class as we don't want to add anything * here. * - * @param build - * @param launcher - * @param listener * @return noop Environment class */ @Override @@ -74,11 +69,8 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener l * Checks to make sure we have some buildsteps set, and then calls the * prebuild and perform on all of them. * - * @todo handle build steps failure in some sort of reasonable way + * TODO handle build steps failure in some sort of reasonable way * - * @param build - * @param launcher - * @param listener */ @Override public Descriptor getDescriptor() { @@ -175,6 +167,7 @@ public static final class DescriptorImpl extends Descriptor { /** * This human readable name is used in the configuration screen. */ + @Override public String getDisplayName() { return "Check Disk Space"; } From 3f15fd225b833d11e43f1ecf5324864a71bf9dc4 Mon Sep 17 00:00:00 2001 From: Maxime Viargues Date: Mon, 30 Oct 2017 14:07:18 +1300 Subject: [PATCH 08/12] Fixed potential null pointers Followed bug/warning from the build to remove the warnings. --- .../java/org/jenkinsci/plugin/Diskcheck.java | 19 +++++++++++++------ .../java/org/jenkinsci/plugin/PluginImpl.java | 15 ++++++++++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugin/Diskcheck.java b/src/main/java/org/jenkinsci/plugin/Diskcheck.java index 49ce6a8..b4d9684 100755 --- a/src/main/java/org/jenkinsci/plugin/Diskcheck.java +++ b/src/main/java/org/jenkinsci/plugin/Diskcheck.java @@ -88,11 +88,18 @@ public void preCheckout(AbstractBuild build, Launcher launcher, log.println("Checking disk space now ..."); // Touch workspace so that it is created on first time. - if (!build.getWorkspace().exists()) { - build.getWorkspace().mkdirs(); + FilePath workspacePath = build.getWorkspace(); + if (workspacePath == null) { + return; + } + if (!workspacePath.exists()) { + workspacePath.mkdirs(); } Node node1 = build.getBuiltOn(); + if (node1 == null) { + return; + } Computer Comp = node1.toComputer(); String NodeName = build.getBuiltOnStr(); @@ -108,7 +115,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, } // End unsure bit. - long size = build.getWorkspace().getParent().getUsableDiskSpace(); + long size = workspacePath.getParent().getUsableDiskSpace(); int roundedSize = (int) (size / (1024 * 1024 * 1024)); log.println("Total disk space available is: " + roundedSize + "GB"); @@ -124,7 +131,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, if (clearUntil == 0) { log.println("clearUntil set to 0, clearing everything ..."); // Jenkins api recursive delete, errors will cause a build failure. - build.getWorkspace().getParent().deleteRecursive(); + workspacePath.getParent().deleteRecursive(); log.println("All workspaces deleted successfully."); } else { if (clearUntil < SpaceThreshold) { @@ -134,7 +141,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, } // Not enough room on slave, start clearing until threshhold met. while (roundedSize < clearUntil) { - FilePath lastUsedDir = lastFileModified(log, build.getWorkspace().getParent()); + FilePath lastUsedDir = lastFileModified(log, workspacePath.getParent()); if (lastUsedDir == null) { throw new AbortException( "There is nothing left in the workspace, but room still needs to be made." @@ -144,7 +151,7 @@ public void preCheckout(AbstractBuild build, Launcher launcher, // Jenkins api recursive delete, errors will cause a build failure. lastUsedDir.deleteRecursive(); log.println("Workspace deleted."); - size = build.getWorkspace().getParent().getUsableDiskSpace(); + size = workspacePath.getParent().getUsableDiskSpace(); roundedSize = (int) (size / (1024 * 1024 * 1024)); log.println("New disk space available is: " + roundedSize + "GB"); } diff --git a/src/main/java/org/jenkinsci/plugin/PluginImpl.java b/src/main/java/org/jenkinsci/plugin/PluginImpl.java index 4f1cd42..51fb6dc 100755 --- a/src/main/java/org/jenkinsci/plugin/PluginImpl.java +++ b/src/main/java/org/jenkinsci/plugin/PluginImpl.java @@ -1,12 +1,13 @@ package org.jenkinsci.plugin; +import hudson.AbortException; import hudson.Plugin; import hudson.model.Descriptor.FormException; -import hudson.model.Hudson; import java.io.IOException; import javax.servlet.ServletException; +import jenkins.model.Jenkins; import net.sf.json.JSONObject; @@ -22,9 +23,17 @@ public class PluginImpl extends Plugin { * Returns the singleton instance. * * @return the one. + * @throws hudson.AbortException + * If Jenkins instance is not ready */ - public static PluginImpl getInstance() { - return Hudson.getInstance().getPlugin(PluginImpl.class); + public static PluginImpl getInstance() throws AbortException { + // To remove warning. I don't think this would ever be null in our case. + Jenkins instance = Jenkins.getInstance(); + if (instance == null) { + throw new AbortException( + "Can't access Jenkins instance, it may not be ready."); + } + return instance.getPlugin(PluginImpl.class); } @Override From 3ec235f3d29b163de156472205c2693616d19d22 Mon Sep 17 00:00:00 2001 From: Maxime Viargues Date: Mon, 30 Oct 2017 14:08:08 +1300 Subject: [PATCH 09/12] Removed Jelly unit test errors. Jelly now needs this line for security reasons. --- src/main/resources/index.jelly | 1 + src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly | 1 + src/main/resources/org/jenkinsci/plugin/diskcheck/config.jelly | 1 + 3 files changed, 3 insertions(+) diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index b620b55..ddee10b 100755 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1,6 +1,7 @@ +
This plugin is to check the disk usage of your node
diff --git a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly index 629fc5e..2b70d78 100755 --- a/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly +++ b/src/main/resources/org/jenkinsci/plugin/PluginImpl/config.jelly @@ -1,3 +1,4 @@ +