7478: Assign invalid cloud sizes to nodes with stale arvados_node_size tags
authorLucas Di Pentima <ldipentima@veritasgenetics.com>
Mon, 11 Jun 2018 15:10:44 +0000 (12:10 -0300)
committerLucas Di Pentima <ldipentima@veritasgenetics.com>
Mon, 11 Jun 2018 15:10:44 +0000 (12:10 -0300)
When retrieving the node's list from the cloud provider, if the tag
refers to a non existant arvados cloud size, assign an invalid size
and return 'down' state when asked so that it can be properly shut down.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima@veritasgenetics.com>

services/nodemanager/arvnodeman/computenode/dispatch/__init__.py
services/nodemanager/arvnodeman/jobqueue.py

index 9106ea67ccc8ffac7813d64baa5ebc537548fa21..dec8ef1434c5f5ca08290ab71f0ecac765dc6ab9 100644 (file)
@@ -370,6 +370,11 @@ class ComputeNodeMonitorActor(config.actor_class):
     def get_state(self):
         """Get node state, one of ['unpaired', 'busy', 'idle', 'down']."""
 
+        # If this node's size is invalid (because it has a stale arvados_node_size
+        # tag), return 'down' so that it's properly shut down.
+        if self.cloud_node.size.id == 'invalid':
+            return 'down'
+
         # If this node is not associated with an Arvados node, return
         # 'unpaired' if we're in the boot grace period, and 'down' if not,
         # so it isn't counted towards usable nodes.
index f3fdc8ee673c0a104abd9fe07eb03789bc865e16..db578e01fe6cd3fc56cccdb82b603c4215d773d5 100644 (file)
@@ -24,6 +24,26 @@ class ServerCalculator(object):
     that would best satisfy the jobs, choosing the cheapest size that
     satisfies each job, and ignoring jobs that can't be satisfied.
     """
+    class InvalidCloudSize(object):
+        """
+        Dummy CloudSizeWrapper-like class, to be used when a cloud node doesn't
+        have a recognizable arvados_node_size tag.
+        """
+        def __init__(self):
+            self.id = 'invalid'
+            self.name = 'invalid'
+            self.ram = 0
+            self.disk = 0
+            self.scratch = 0
+            self.cores = 0
+            self.bandwidth = 0
+            self.price = 9999999
+            self.preemptable = False
+            self.extra = {}
+
+        def meets_constraints(self, **kwargs):
+            return False
+
 
     class CloudSizeWrapper(object):
         def __init__(self, real_size, node_mem_scaling, **kwargs):
@@ -119,7 +139,7 @@ class ServerCalculator(object):
         for s in self.cloud_sizes:
             if s.id == sizeid:
                 return s
-        return None
+        return InvalidCloudSize()
 
 
 class JobQueueMonitorActor(clientactor.RemotePollLoopActor):