/** Choose which datapoint to use. */ public enum TimeScale { SEC10(TimeUnit2.SECONDS.toMillis(10)), MIN(TimeUnit2.MINUTES.toMillis(1)), HOUR(TimeUnit2.HOURS.toMillis(1)); /** Number of milliseconds (10 secs, 1 min, and 1 hour) that this constant represents. */ public final long tick; TimeScale(long tick) { this.tick = tick; } /** Creates a new {@link DateFormat} suitable for processing this {@link TimeScale}. */ public DateFormat createDateFormat() { switch (this) { case HOUR: return new SimpleDateFormat("MMM/dd HH"); case MIN: return new SimpleDateFormat("HH:mm"); case SEC10: return new SimpleDateFormat("HH:mm:ss"); default: throw new AssertionError(); } } /** Parses the {@link TimeScale} from the query parameter. */ public static TimeScale parse(String type) { if (type == null) return TimeScale.MIN; return Enum.valueOf(TimeScale.class, type.toUpperCase(Locale.ENGLISH)); } }
/** * Turns an interval into milliseconds./ * * @param interval the interval. * @return the milliseconds. */ private static long toIntervalMillis(String interval) { TimeUnit2 units = TimeUnit2.MINUTES; interval = interval.toLowerCase(); if (interval.endsWith("h")) { units = TimeUnit2.HOURS; interval = StringUtils.removeEnd(interval, "h"); } if (interval.endsWith("m")) { interval = StringUtils.removeEnd(interval, "m"); } else if (interval.endsWith("d")) { units = TimeUnit2.DAYS; interval = StringUtils.removeEnd(interval, "d"); } else if (interval.endsWith("ms")) { units = TimeUnit2.SECONDS; interval = StringUtils.removeEnd(interval, "ms"); } else if (interval.endsWith("s")) { units = TimeUnit2.SECONDS; interval = StringUtils.removeEnd(interval, "s"); } long value = 0; try { value = Long.parseLong(interval); } catch (NumberFormatException e) { value = 1; } return Math.min( TimeUnit2.DAYS.toMillis(30), Math.max(TimeUnit2.MINUTES.toMillis(1), units.toMillis(value))); }
/** * Turns an interval into a suitable crontab. * * @param interval the interval. * @return the crontab. */ private static String toCrontab(String interval) { long millis = toIntervalMillis(interval); if (millis < TimeUnit2.MINUTES.toMillis(5)) { return "* * * * *"; } if (millis < TimeUnit2.MINUTES.toMillis(10)) { return "*/12 * * * *"; } if (millis < TimeUnit2.MINUTES.toMillis(30)) { return "*/6 * * * *"; } if (millis < TimeUnit2.HOURS.toMillis(1)) { return "*/2 * * * *"; } if (millis < TimeUnit2.HOURS.toMillis(8)) { return "H * * * *"; } return "H H * * *"; }
@Override public synchronized long check(VMLabMgrComputer computer) { if (computer.isIdle()) { final long idleTime = System.currentTimeMillis() - computer.getIdleStartMilliseconds(); if (idleTime > TimeUnit2.MINUTES.toMillis(1)) { LOGGER.info(MessageFormat.format("Disconnecting from {0}", computer.getName())); computer.getNode().terminate(); } } return 1l; }
/** * Default convenience implementation of {@link RetentionStrategy} for slaves provisioned from * {@link Cloud}. * * <p>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 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 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()); }
private Connection connectToSsh(Computer computer, PrintStream logger) throws RequestUnsuccessfulException, DigitalOceanException { final long timeout = TimeUnit2.MINUTES.toMillis(computer.getCloud().getTimeoutMinutes()); final long startTime = System.currentTimeMillis(); final int sleepTime = 10; long waitTime; while ((waitTime = System.currentTimeMillis() - startTime) < timeout) { // Hack to fetch this each time through the loop to get the latest information. final Droplet droplet = DigitalOcean.getDroplet( computer.getCloud().getAuthToken(), computer.getNode().getDropletId()); if (isDropletStarting(droplet)) { logger.println( "Waiting for droplet to enter ACTIVE state. Sleeping " + sleepTime + " seconds."); } else { try { final String host = getIpAddress(computer); if (Strings.isNullOrEmpty(host) || "0.0.0.0".equals(host)) { logger.println( "No ip address yet, your host is most likely waiting for an ip address."); } else { int port = computer.getSshPort(); Connection conn = getDropletConnection(host, port, logger); if (conn != null) { return conn; } } } catch (IOException e) { // Ignore, we'll retry. } logger.println("Waiting for SSH to come up. Sleeping " + sleepTime + " seconds."); } sleep(sleepTime); } throw new RuntimeException( format( "Timed out after %d seconds of waiting for ssh to become available (max timeout configured is %s)", waitTime / 1000, timeout / 1000)); }
/** * Returns the interval between indexing. * * @return the interval between indexing. */ @SuppressWarnings("unused") // used by Jelly EL public String getInterval() { if (interval < TimeUnit2.SECONDS.toMillis(1)) { return Long.toString(interval) + "ms"; } if (interval < TimeUnit2.MINUTES.toMillis(1)) { return Long.toString(TimeUnit2.MILLISECONDS.toSeconds(interval)) + "s"; } if (interval < TimeUnit2.HOURS.toMillis(1)) { return Long.toString(TimeUnit2.MILLISECONDS.toMinutes(interval)) + "m"; } if (interval < TimeUnit2.DAYS.toMillis(1)) { return Long.toString(TimeUnit2.MILLISECONDS.toHours(interval)) + "h"; } return Long.toString(TimeUnit2.MILLISECONDS.toDays(interval)) + "d"; }
@Override public synchronized long check(JCloudsComputer c) { if (c.isIdle() && !c.getNode().isPendingDelete() && !disabled) { // Get the retention time, in minutes, from the JCloudsCloud this JCloudsComputer belongs to. final int retentionTime = JCloudsCloud.getByName(c.getCloudName()).getRetentionTime(); if (retentionTime > -1) { final long idleMilliseconds = System.currentTimeMillis() - c.getIdleStartMilliseconds(); if (idleMilliseconds > TimeUnit2.MINUTES.toMillis(retentionTime)) { LOGGER.info("Setting " + c.getName() + " to be deleted."); if (!c.isOffline()) { c.setTemporarilyOffline(true, OfflineCause.create(Messages._DeletedCause())); } c.getNode().setPendingDelete(true); } } } return 1; }