3 from __future__ import absolute_import, print_function
8 ARVADOS_TIMEFMT = '%Y-%m-%dT%H:%M:%SZ'
10 def arvados_node_fqdn(arvados_node, default_hostname='dynamic.compute'):
11 hostname = arvados_node.get('hostname') or default_hostname
12 return '{}.{}'.format(hostname, arvados_node['domain'])
14 def arvados_node_mtime(node):
15 return arvados_timestamp(node['modified_at'])
17 def arvados_timestamp(timestr):
18 return time.mktime(time.strptime(timestr + 'UTC',
19 ARVADOS_TIMEFMT + '%Z')) - time.timezone
21 def timestamp_fresh(timestamp, fresh_time):
22 return (time.time() - timestamp) < fresh_time
24 class ShutdownTimer(object):
25 """Keep track of a cloud node's shutdown windows.
27 Instantiate this class with a timestamp of when a cloud node started,
28 and a list of durations (in minutes) of when the node must not and may
29 be shut down, alternating. The class will tell you when a shutdown
30 window is open, and when the next open window will start.
32 def __init__(self, start_time, shutdown_windows):
33 # The implementation is easiest if we have an even number of windows,
34 # because then windows always alternate between open and closed.
35 # Rig that up: calculate the first shutdown window based on what's
36 # passed in. Then, if we were given an odd number of windows, merge
37 # that first window into the last one, since they both# represent
39 first_window = shutdown_windows[0]
40 shutdown_windows = list(shutdown_windows[1:])
41 self._next_opening = start_time + (60 * first_window)
42 if len(shutdown_windows) % 2:
43 shutdown_windows.append(first_window)
45 shutdown_windows[-1] += first_window
46 self.shutdown_windows = itertools.cycle([60 * n
47 for n in shutdown_windows])
48 self._open_start = self._next_opening
49 self._open_for = next(self.shutdown_windows)
51 def _advance_opening(self):
52 while self._next_opening < time.time():
53 self._open_start = self._next_opening
54 self._next_opening += self._open_for + next(self.shutdown_windows)
55 self._open_for = next(self.shutdown_windows)
57 def next_opening(self):
58 self._advance_opening()
59 return self._next_opening
61 def window_open(self):
62 self._advance_opening()
63 return 0 < (time.time() - self._open_start) < self._open_for