6520: Apply node size fixup in CloudNodeListMonitorActor
[arvados.git] / services / nodemanager / arvnodeman / nodelist.py
1 #!/usr/bin/env python
2
3 from __future__ import absolute_import, print_function
4
5 import subprocess
6
7 from . import clientactor
8 from . import config
9
10 import arvados.util
11
12 class ArvadosNodeListMonitorActor(clientactor.RemotePollLoopActor):
13     """Actor to poll the Arvados node list.
14
15     This actor regularly polls the list of Arvados node records, and
16     sends it to subscribers.
17     """
18
19     def is_common_error(self, exception):
20         return isinstance(exception, config.ARVADOS_ERRORS)
21
22     def _item_key(self, node):
23         return node['uuid']
24
25     def _send_request(self):
26         nodelist = arvados.util.list_all(self._client.nodes().list)
27
28         # node hostname, state
29         sinfo_out = subprocess.check_output(["sinfo", "--noheader", "--format=%n %t"])
30         nodestates = {}
31         for out in sinfo_out.splitlines():
32             nodename, state = out.split(" ", 2)
33             if state in ('alloc', 'comp'):
34                 nodestates[nodename] = 'busy'
35             elif state == 'idle':
36                 nodestates[nodename] = 'idle'
37             else:
38                 nodestates[nodename] = 'down'
39
40         for n in nodelist:
41             if n["slot_number"] and n["hostname"] and n["hostname"] in nodestates:
42                 n["crunch_worker_state"] = nodestates[n["hostname"]]
43             else:
44                 n["crunch_worker_state"] = 'down'
45
46         return nodelist
47
48 class CloudNodeListMonitorActor(clientactor.RemotePollLoopActor):
49     """Actor to poll the cloud node list.
50
51     This actor regularly polls the cloud to get a list of running compute
52     nodes, and sends it to subscribers.
53     """
54
55     def __init__(self, client, timer_actor, server_calc, *args, **kwargs):
56         super(CloudNodeListMonitorActor, self).__init__(
57             client, timer_actor, *args, **kwargs)
58         self._calculator = server_calc
59
60     def is_common_error(self, exception):
61         return self._client.is_cloud_exception(exception)
62
63     def _item_key(self, node):
64         return node.id
65
66     def _send_request(self):
67         nodes = self._client.list_nodes()
68         for n in nodes:
69             # Replace with libcloud NodeSize object with compatible
70             # CloudSizeWrapper object which merges the size info reported from
71             # the cloud with size information from the configuration file.
72             n.size = self._calculator.find_size(n.size.id)
73         return nodes