提交 b7e8854d 编写于 作者: K Kohsuke Kawaguchi

adding an example retention strategy and clarified doc.

In particular, explain how to free an external resource when a slave is
gone.
上级 c3a19670
......@@ -26,6 +26,8 @@ package hudson.slaves;
import hudson.ExtensionPoint;
import hudson.Extension;
import hudson.DescriptorExtensionList;
import hudson.model.Computer;
import hudson.model.Slave;
import hudson.slaves.NodeProvisioner.PlannedNode;
import hudson.model.Describable;
import jenkins.model.Jenkins;
......@@ -37,6 +39,7 @@ import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.util.DescriptorList;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Collection;
......@@ -47,6 +50,33 @@ import java.util.Collection;
* Put another way, this class encapsulates different communication protocols
* needed to start a new slave programmatically.
*
* <h2>Notes for implementers</h2>
* <h4>Automatically delete idle slaves</h4>
* <p>
* Nodes provisioned from a cloud do not automatically get released just because it's created from {@link Cloud}.
* Doing so requires a use of {@link RetentionStrategy}. Instantiate your {@link Slave} subtype with something
* like {@link CloudSlaveRetentionstrategy} so that it gets automatically deleted after some idle time.
*
* <h4>Freeing an external resource when a slave is removed</h4>
* <p>
* Whether you do auto scale-down or not, you often want to release an external resource tied to a cloud-allocated
* slave when it is removed.
*
* <p>
* To do this, have your {@link Slave} subtype remember the necessary handle (such as EC2 instance ID)
* as a field. Such fields need to survive the user-initiated re-configuration of {@link Slave}, so you'll need to
* expose it in your {@link Slave} <tt>configure-entries.jelly</tt> and read it back in through {@link DataBoundConstructor}.
*
* <p>
* You then implement your own {@link Computer} subtype, override {@link Slave#createComputer()}, and instantiate
* your own {@link Computer} subtype with this handle information.
*
* <p>
* Finally, override {@link Computer#onRemoved()} and use the handle to talk to the "cloud" and de-allocate
* the resource (such as shutting down a virtual machine.) {@link Computer} needs to own this handle information
* because by the time this happens, a {@link Slave} object is already long gone.
*
*
* @author Kohsuke Kawaguchi
* @see NodeProvisioner
* @see AbstractCloudImpl
......
package hudson.slaves;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.util.TimeUnit2;
import jenkins.model.Jenkins;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Default convenience implementation of {@link RetentionStrategy} for slaves provisioned from {@link Cloud}.
*
* If a slave is idle for 10 mins, this retention strategy will remove the slave. This can be used as-is for
* a {@link Node} provisioned by cloud to implement the auto-scaling semantics, it can be subtyped to twaeak
* the behaviour, or it can be used as an example.
*
* @author Kohsuke Kawaguchi
* @since 1.510
*/
public class CloudSlaveRetentionstrategy<T extends Computer> extends RetentionStrategy<T> {
@Override
public long check(T c) {
if (!c.isConnecting() && c.isAcceptingTasks()) {
if (isIdleForTooLong(c)) {
try {
Node n = c.getNode();
if (n!=null) // rare, but n==null if the node is deleted and being checked roughly at the same time
kill(n);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to remove "+c.getDisplayName(),e);
}
}
}
return checkCycle();
}
/**
* Remove the node.
*
* <p>
* To actually deallocate the resource tied to this {@link Node}, implement {@link Computer#onRemoved()}.
*/
protected void kill(Node n) throws IOException {
Jenkins.getInstance().removeNode(n);
}
/**
* When do we check again next time?
*/
protected long checkCycle() {
return getIdleMaxTime()/10;
}
/**
* Has this computer been idle for too long?
*/
protected boolean isIdleForTooLong(T c) {
return System.currentTimeMillis()-c.getIdleStartMilliseconds() > getIdleMaxTime();
}
/**
* If the computer has been idle longer than this time, we'll kill the slave.
*/
protected long getIdleMaxTime() {
return TIMEOUT;
}
// for debugging, it's convenient to be able to reduce this time
public static long TIMEOUT = Long.getLong(CloudSlaveRetentionstrategy.class.getName()+".timeout", TimeUnit2.MINUTES.toMillis(10));
private static final Logger LOGGER = Logger.getLogger(CloudSlaveRetentionstrategy.class.getName());
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册