7454: Add 'size' to arvados_create_kwargs so that it can be included in CustomData.
[arvados.git] / services / nodemanager / arvnodeman / computenode / __init__.py
index 30fe516a1c7b72f81ea57a5f3d97d04d55bf0d24..6e46bc0f4c6283ab0d73da212529299bdec4ba10 100644 (file)
@@ -2,10 +2,13 @@
 
 from __future__ import absolute_import, print_function
 
+import calendar
 import itertools
+import re
 import time
 
 ARVADOS_TIMEFMT = '%Y-%m-%dT%H:%M:%SZ'
+ARVADOS_TIMESUBSEC_RE = re.compile(r'(\.\d+)Z$')
 
 def arvados_node_fqdn(arvados_node, default_hostname='dynamic.compute'):
     hostname = arvados_node.get('hostname') or default_hostname
@@ -15,12 +18,31 @@ def arvados_node_mtime(node):
     return arvados_timestamp(node['modified_at'])
 
 def arvados_timestamp(timestr):
-    return time.mktime(time.strptime(timestr + 'UTC',
-                                     ARVADOS_TIMEFMT + '%Z')) - time.timezone
+    subsec_match = ARVADOS_TIMESUBSEC_RE.search(timestr)
+    if subsec_match is None:
+        subsecs = .0
+    else:
+        subsecs = float(subsec_match.group(1))
+        timestr = timestr[:subsec_match.start()] + 'Z'
+    return calendar.timegm(time.strptime(timestr + 'UTC',
+                                         ARVADOS_TIMEFMT + '%Z'))
 
 def timestamp_fresh(timestamp, fresh_time):
     return (time.time() - timestamp) < fresh_time
 
+def arvados_node_missing(arvados_node, fresh_time):
+    """Indicate if cloud node corresponding to the arvados
+    node is "missing".
+
+    If True, this means the node has not pinged the API server within the timeout
+    period.  If False, the ping is up to date.  If the node has never pinged,
+    returns None.
+    """
+    if arvados_node["last_ping_at"] is None:
+        return None
+    else:
+        return not timestamp_fresh(arvados_timestamp(arvados_node["last_ping_at"]), fresh_time)
+
 class ShutdownTimer(object):
     """Keep track of a cloud node's shutdown windows.