From e16b747b66c1827ddb35292f50fd0538ddaec2f9 Mon Sep 17 00:00:00 2001 From: kohsuke Date: Mon, 23 Mar 2009 22:52:08 +0000 Subject: [PATCH] Hudson now monitors the temporary directory to forestall disk out of space problems. git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@16496 71c3de6d-444a-0410-be80-ed276b4c234a --- .../node_monitors/DiskSpaceMonitor.java | 72 +++-------- .../DiskSpaceMonitorDescriptor.java | 113 ++++++++++++++++++ .../node_monitors/TemporarySpaceMonitor.java | 98 +++++++++++++++ .../DiskSpaceMonitor/column.jelly | 2 +- .../TemporarySpaceMonitor/column.jelly | 34 ++++++ 5 files changed, 260 insertions(+), 59 deletions(-) create mode 100644 core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java create mode 100644 core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java create mode 100644 core/src/main/resources/hudson/node_monitors/TemporarySpaceMonitor/column.jelly diff --git a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java index 342fad802f..c81d1cbff1 100644 --- a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java +++ b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java @@ -23,72 +23,36 @@ */ package hudson.node_monitors; +import hudson.Extension; import hudson.FilePath; -import hudson.FilePath.FileCallable; -import hudson.Util; import hudson.Functions; -import hudson.Extension; import hudson.model.Computer; import hudson.model.Hudson; -import hudson.remoting.VirtualChannel; +import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; -import org.jvnet.animal_sniffer.IgnoreJRERequirement; -import java.io.File; import java.io.IOException; -import java.math.BigDecimal; -import java.util.logging.Logger; /** - * Checks available disk space of the node. - * Requres Mustang. + * Checks available disk space of the remote FS root. + * Requires Mustang. * * @author Kohsuke Kawaguchi * @since 1.123 */ public class DiskSpaceMonitor extends NodeMonitor { - public Long getFreeSpace(Computer c) { + public DiskSpace getFreeSpace(Computer c) { return DESCRIPTOR.get(c); } - /** - * Returns the HTML representation of the space. - */ - public String toHtml(long space) { - space/=1024L; // convert to KB - space/=1024L; // convert to MB - if(space<1024) { - // less than a GB - return Util.wrapToErrorSpan(new BigDecimal(space).scaleByPowerOfTen(-3).toPlainString()+"GB"); - } - - return space/1024+"GB"; - } - @Override public String getColumnCaption() { // Hide this column from non-admins return Hudson.getInstance().hasPermission(Hudson.ADMINISTER) ? super.getColumnCaption() : null; } - public static final AbstractNodeMonitorDescriptor DESCRIPTOR = new AbstractNodeMonitorDescriptor() { - protected Long monitor(Computer c) throws IOException, InterruptedException { - FilePath p = c.getNode().getRootPath(); - if(p==null) return null; - - Long size = p.act(new GetUsableSpace()); - if(size!=null && size!=0 && size/(1024*1024*1024)==0) { - // TODO: this scheme should be generalized, so that Hudson can remember why it's marking the node - // as offline, as well as allowing the user to force Hudson to use it. - if(!c.isTemporarilyOffline()) { - LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getName())); - c.setTemporarilyOffline(true); - } - } - return size; - } - + public static final DiskSpaceMonitorDescriptor DESCRIPTOR = new DiskSpaceMonitorDescriptor() { public String getDisplayName() { return Messages.DiskSpaceMonitor_displayName(); } @@ -97,26 +61,18 @@ public class DiskSpaceMonitor extends NodeMonitor { public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws FormException { return new DiskSpaceMonitor(); } + + protected DiskSpace getFreeSpace(Computer c) throws IOException, InterruptedException { + FilePath p = c.getNode().getRootPath(); + if(p==null) return null; + + return p.act(new GetUsableSpace()); + } }; @Extension - public static AbstractNodeMonitorDescriptor install() { + public static DiskSpaceMonitorDescriptor install() { if(Functions.isMustangOrAbove()) return DESCRIPTOR; return null; } - - private static final class GetUsableSpace implements FileCallable { - @IgnoreJRERequirement - public Long invoke(File f, VirtualChannel channel) throws IOException { - try { - return f.getUsableSpace(); - } catch (LinkageError e) { - // pre-mustang - return null; - } - } - private static final long serialVersionUID = 1L; - } - - private static final Logger LOGGER = Logger.getLogger(DiskSpaceMonitor.class.getName()); } diff --git a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java new file mode 100644 index 0000000000..bb0cc78ed7 --- /dev/null +++ b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java @@ -0,0 +1,113 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.node_monitors; + +import hudson.FilePath.FileCallable; +import hudson.model.Computer; +import hudson.remoting.VirtualChannel; +import hudson.Util; +import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace; +import org.jvnet.animal_sniffer.IgnoreJRERequirement; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; +import java.math.BigDecimal; + +/** + * {@link AbstractNodeMonitorDescriptor} for {@link NodeMonitor} that checks a free disk space of some directory. + * + * @author Kohsuke Kawaguchi +*/ +/*package*/ abstract class DiskSpaceMonitorDescriptor extends AbstractNodeMonitorDescriptor { + /** + * Value object that represents the disk space. + */ + public static final class DiskSpace { + public final long size; + + public DiskSpace(long size) { + this.size = size; + } + + @Override + public String toString() { + return String.valueOf(size); + } + + /** + * Returns the HTML representation of the space. + */ + public String toHtml() { + long space = size; + space/=1024L; // convert to KB + space/=1024L; // convert to MB + if(space<1024) { + // less than a GB + return Util.wrapToErrorSpan(new BigDecimal(space).scaleByPowerOfTen(-3).toPlainString()+"GB"); + } + + return space/1024+"GB"; + } + + public boolean moreThanGB() { + return size>1024L*1024*1024; + } + } + + protected DiskSpace monitor(Computer c) throws IOException, InterruptedException { + DiskSpace size = getFreeSpace(c); + if(size!=null && !size.moreThanGB()) { + // TODO: this scheme should be generalized, so that Hudson can remember why it's marking the node + // as offline, as well as allowing the user to force Hudson to use it. + if(!c.isTemporarilyOffline()) { + LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getName())); + c.setTemporarilyOffline(true); + } + } + return size; + } + + /** + * Computes the free size. + */ + protected abstract DiskSpace getFreeSpace(Computer c) throws IOException, InterruptedException; + + protected static final class GetUsableSpace implements FileCallable { + @IgnoreJRERequirement + public DiskSpace invoke(File f, VirtualChannel channel) throws IOException { + try { + long s = f.getUsableSpace(); + if(s<=0) return null; + return new DiskSpace(s); + } catch (LinkageError e) { + // pre-mustang + return null; + } + } + private static final long serialVersionUID = 1L; + } + + private static final Logger LOGGER = Logger.getLogger(DiskSpaceMonitor.class.getName()); +} diff --git a/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java b/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java new file mode 100644 index 0000000000..fe8b4d60ca --- /dev/null +++ b/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java @@ -0,0 +1,98 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.node_monitors; + +import hudson.node_monitors.DiskSpaceMonitorDescriptor.DiskSpace; +import hudson.model.Computer; +import hudson.model.Hudson; +import hudson.FilePath; +import hudson.Extension; +import hudson.Functions; +import hudson.remoting.VirtualChannel; +import hudson.FilePath.FileCallable; +import org.kohsuke.stapler.StaplerRequest; +import org.jvnet.animal_sniffer.IgnoreJRERequirement; +import net.sf.json.JSONObject; + +import java.io.IOException; +import java.io.File; + +/** + * Monitors the disk space of "/tmp". + * + * @author Kohsuke Kawaguchi + */ +public class TemporarySpaceMonitor extends NodeMonitor { + public DiskSpace getFreeSpace(Computer c) { + return DESCRIPTOR.get(c); + } + + @Override + public String getColumnCaption() { + // Hide this column from non-admins + return Hudson.getInstance().hasPermission(Hudson.ADMINISTER) ? super.getColumnCaption() : null; + } + + public static final DiskSpaceMonitorDescriptor DESCRIPTOR = new DiskSpaceMonitorDescriptor() { + public String getDisplayName() { + return "Free Temp Space"; + } + + @Override + public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws FormException { + return new TemporarySpaceMonitor(); + } + + protected DiskSpace getFreeSpace(Computer c) throws IOException, InterruptedException { + FilePath p = c.getNode().getRootPath(); + if(p==null) return null; + + return p.act(new GetTempSpace()); + } + }; + + @Extension + public static DiskSpaceMonitorDescriptor install() { + if(Functions.isMustangOrAbove()) return DESCRIPTOR; + return null; + } + + protected static final class GetTempSpace implements FileCallable { + @IgnoreJRERequirement + public DiskSpace invoke(File f, VirtualChannel channel) throws IOException { + try { + f = File.createTempFile("tmp-space","monitor"); + long s = f.getUsableSpace(); + if(s<=0) return null; + return new DiskSpace(s); + } catch (LinkageError e) { + // pre-mustang + return null; + } finally { + f.delete(); + } + } + private static final long serialVersionUID = 1L; + } +} diff --git a/core/src/main/resources/hudson/node_monitors/DiskSpaceMonitor/column.jelly b/core/src/main/resources/hudson/node_monitors/DiskSpaceMonitor/column.jelly index bfe9506e39..7e23e72f97 100644 --- a/core/src/main/resources/hudson/node_monitors/DiskSpaceMonitor/column.jelly +++ b/core/src/main/resources/hudson/node_monitors/DiskSpaceMonitor/column.jelly @@ -28,7 +28,7 @@ THE SOFTWARE. N/A - ${from.toHtml(data)} + ${data.toHtml()} \ No newline at end of file diff --git a/core/src/main/resources/hudson/node_monitors/TemporarySpaceMonitor/column.jelly b/core/src/main/resources/hudson/node_monitors/TemporarySpaceMonitor/column.jelly new file mode 100644 index 0000000000..2512af7df8 --- /dev/null +++ b/core/src/main/resources/hudson/node_monitors/TemporarySpaceMonitor/column.jelly @@ -0,0 +1,34 @@ + + + + + + N/A + + + ${data.toHtml()} + + + \ No newline at end of file -- GitLab