private boolean shouldReboot(Node node) {
        if (node.status().reboot().pending()) return false;

        var rebootEvents = EnumSet.of(History.Event.Type.provisioned, History.Event.Type.rebooted, History.Event.Type.osUpgraded);
        var rebootInterval = Duration.ofDays(rebootIntervalInDays.value());

        Optional<Duration> overdue = node.history().events().stream()
                .filter(event -> rebootEvents.contains(event.type()))
                .map(History.Event::at)
                .max(Comparator.naturalOrder())
                .map(lastReboot -> Duration.between(lastReboot, clock().instant()).minus(rebootInterval));

        if (overdue.isEmpty()) // should never happen as all hosts should have provisioned timestamp
            return random.nextDouble() < interval().getSeconds() / (double) rebootInterval.getSeconds();

        if (overdue.get().isNegative()) return false;

        // Use a probability such that each maintain() schedules the same number of reboots,
        // as long as 0 <= overdue <= rebootInterval, with the last maintain() in that interval
        // naturally scheduling the remaining with probability 1.
        int configServers = nodeRepository().database().cluster().size();
        long secondsRemaining = Math.max(0, rebootInterval.getSeconds() - overdue.get().getSeconds());
        double runsRemaining = configServers * secondsRemaining / (double) interval().getSeconds();
        double probability = 1 / (1 + runsRemaining);
        return random.nextDouble() < probability;
    }
This schedules periodic reboot of all nodes.
We reboot nodes periodically to surface problems at reboot with a smooth frequency rather than
potentially in burst when many nodes need to be rebooted for external reasons.

@author bratseth
node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/NodeRebooter.java