package hudson.slaves;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.util.TimeUnit2;
import jenkins.model.Jenkins;
import javax.annotation.concurrent.GuardedBy;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.util.SystemProperties;
/**
* Default convenience implementation of {@link RetentionStrategy} for agents provisioned from {@link Cloud}.
*
* If an agent is idle for 10 mins, this retention strategy will remove the agent. This can be used as-is for
* a {@link Node} provisioned by cloud to implement the auto-scaling semantics, it can be subtyped to tweak
* the behavior, or it can be used as an example.
* <p>TODO {@link CloudRetentionStrategy} seems to be a better implementation.
* @author Kohsuke Kawaguchi
* @since 1.510
*/
public class CloudSlaveRetentionStrategy<T extends Computer> extends RetentionStrategy<T> {
@Override
@GuardedBy("hudson.model.Queue.lock")
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 agent.
*/
protected long getIdleMaxTime() {
return TIMEOUT;
}
// for debugging, it's convenient to be able to reduce this time
public static long TIMEOUT = SystemProperties.getLong(CloudSlaveRetentionStrategy.class.getName()+".timeout", TimeUnit2.MINUTES.toMillis(10));
private static final Logger LOGGER = Logger.getLogger(CloudSlaveRetentionStrategy.class.getName());
}