3 from __future__ import absolute_import, print_function
9 ComputeNodeSetupActor, ComputeNodeUpdateActor, ComputeNodeMonitorActor
10 from . import ComputeNodeShutdownActor as ShutdownActorBase
12 class ComputeNodeShutdownActor(ShutdownActorBase):
13 SLURM_END_STATES = frozenset(['down\n', 'down*\n',
14 'drain\n', 'drain*\n',
16 SLURM_DRAIN_STATES = frozenset(['drain\n', 'drng\n'])
19 arv_node = self._arvados_node()
22 return super(ComputeNodeShutdownActor, self).on_start()
24 self._nodename = arv_node['hostname']
25 self._logger.info("Draining SLURM node %s", self._nodename)
26 self._later.issue_slurm_drain()
28 def _set_node_state(self, state, *args):
29 cmd = ['scontrol', 'update', 'NodeName=' + self._nodename,
32 subprocess.check_output(cmd)
34 def _get_slurm_state(self):
35 return subprocess.check_output(['sinfo', '--noheader', '-o', '%t', '-n', self._nodename])
37 @ShutdownActorBase._retry((subprocess.CalledProcessError,))
38 def cancel_shutdown(self):
40 if self._get_slurm_state() in self.SLURM_DRAIN_STATES:
41 # Resume from "drng" or "drain"
42 self._set_node_state('RESUME')
44 # Node is in a state such as 'idle' or 'alloc' so don't
45 # try to resume it because that will just raise an error.
47 return super(ComputeNodeShutdownActor, self).cancel_shutdown()
49 @ShutdownActorBase._stop_if_window_closed
50 @ShutdownActorBase._retry((subprocess.CalledProcessError,))
51 def issue_slurm_drain(self):
52 self._set_node_state('DRAIN', 'Reason=Node Manager shutdown')
53 self._logger.info("Waiting for SLURM node %s to drain", self._nodename)
54 self._later.await_slurm_drain()
56 @ShutdownActorBase._stop_if_window_closed
57 @ShutdownActorBase._retry((subprocess.CalledProcessError,))
58 def await_slurm_drain(self):
59 output = self._get_slurm_state()
60 if output in self.SLURM_END_STATES:
61 self._later.shutdown_node()
63 self._timer.schedule(time.time() + 10,
64 self._later.await_slurm_drain)