Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix JENKINS-8196

Persist a user-requested offline status for a slave across
restarts. Previously slaves would come back online if the server
was restarted while they were marked 'temporarily offline'.

I believe this also addresses JENKINS-7934 and JENKINS-7805
which look like duplicates.
  • Loading branch information...
commit a88920aab7b1e35c24b4adb7a297bd04d35ed9a3 1 parent d990fbb
Nathan Parry nparry authored abayer committed
11 core/src/main/java/hudson/model/Computer.java
View
@@ -509,6 +509,7 @@ public void setTemporarilyOffline(boolean temporarilyOffline) {
public void setTemporarilyOffline(boolean temporarilyOffline, OfflineCause cause) {
offlineCause = temporarilyOffline ? cause : null;
this.temporarilyOffline = temporarilyOffline;
+ getNode().setTemporaryOfflineCause(offlineCause);
Hudson.getInstance().getQueue().scheduleMaintenance();
}
@@ -563,6 +564,16 @@ protected void setNode(Node node) {
this.nodeName = null;
setNumExecutors(node.getNumExecutors());
+ if (this.temporarilyOffline) {
+ // When we get a new node, push our current temp offline
+ // status to it (as the status is not carried across
+ // configuration changes that recreate the node).
+ // Since this is also called the very first time this
+ // Computer is created, avoid pushing an empty status
+ // as that could overwrite any status that the Node
+ // brought along from its persisted config data.
+ node.setTemporaryOfflineCause(this.offlineCause);
+ }
}
/**
42 core/src/main/java/hudson/model/Node.java
View
@@ -25,6 +25,7 @@
package hudson.model;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
+import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.FilePath;
import hudson.FileSystemProvisioner;
@@ -37,9 +38,11 @@
import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.security.Permission;
+import hudson.slaves.ComputerListener;
import hudson.slaves.NodeDescriptor;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
+import hudson.slaves.OfflineCause;
import hudson.util.ClockDifference;
import hudson.util.DescribableList;
import hudson.util.EnumConverter;
@@ -51,6 +54,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.List;
+import java.util.logging.Logger;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.export.ExportedBean;
@@ -68,6 +72,9 @@
*/
@ExportedBean
public abstract class Node extends AbstractModelObject implements Describable<Node>, ExtensionPoint, AccessControlled {
+
+ private static final Logger LOGGER = Logger.getLogger(Node.class.getName());
+
/**
* Newly copied slaves get this flag set, so that Hudson doesn't try to start this node until its configuration
* is saved once.
@@ -166,6 +173,41 @@ public final VirtualChannel getChannel() {
protected abstract Computer createComputer();
/**
+ * Let Nodes be aware of the lifecycle of their own {@link Computer}.
+ */
+ @Extension
+ public static class InternalComputerListener extends ComputerListener {
+ @Override
+ public void onOnline(Computer c, TaskListener listener) {
+ Node node = c.getNode();
+
+ // At startup, we need to restore any previously in-effect temp offline cause.
+ // We wait until the computer is started rather than getting the data to it sooner
+ // so that the normal computer start up processing works as expected.
+ if (node.temporaryOfflineCause != null && node.temporaryOfflineCause != c.getOfflineCause()) {
+ c.setTemporarilyOffline(true, node.temporaryOfflineCause);
+ }
+ }
+ }
+
+ private OfflineCause temporaryOfflineCause;
+
+ /**
+ * Enable a {@link Computer} to inform its node when it is taken
+ * temporarily offline.
+ */
+ void setTemporaryOfflineCause(OfflineCause cause) {
+ try {
+ if (temporaryOfflineCause != cause) {
+ temporaryOfflineCause = cause;
+ Hudson.getInstance().save(); // Gotta be a better way to do this
+ }
+ } catch (java.io.IOException e) {
+ LOGGER.warning("Unable to complete save, temporary offline status will not be persisted: " + e.getMessage());
+ }
+ }
+
+ /**
* Return the possibly empty tag cloud for the labels of this node.
*/
public TagCloud<LabelAtom> getLabelCloud() {
Please sign in to comment.
Something went wrong with that request. Please try again.