3 from __future__ import absolute_import, print_function
10 import arvnodeman.computenode.dispatch.slurm as slurm_dispatch
11 from . import testutil
12 from .test_computenode_dispatch import ComputeNodeShutdownActorMixin
14 @mock.patch('subprocess.check_output')
15 class SLURMComputeNodeShutdownActorTestCase(ComputeNodeShutdownActorMixin,
17 ACTOR_CLASS = slurm_dispatch.ComputeNodeShutdownActor
19 def check_slurm_got_args(self, proc_mock, *args):
20 self.assertTrue(proc_mock.called)
21 slurm_cmd = proc_mock.call_args[0][0]
23 self.assertIn(s, slurm_cmd)
25 def check_success_after_reset(self, proc_mock):
26 self.make_mocks(arvados_node=testutil.arvados_node_mock(63))
28 self.check_success_flag(None, 0)
29 self.check_success_flag(None, 0)
30 # Order is critical here: if the mock gets called when no return value
31 # or side effect is set, we may invoke a real subprocess.
32 proc_mock.return_value = 'drain\n'
33 proc_mock.side_effect = None
34 self.check_success_flag(True, 3)
35 self.check_slurm_got_args(proc_mock, 'compute63')
37 def test_wait_for_drained_state(self, proc_mock):
38 proc_mock.return_value = 'drng\n'
39 self.check_success_after_reset(proc_mock)
41 def test_retry_failed_slurm_calls(self, proc_mock):
42 proc_mock.side_effect = subprocess.CalledProcessError(1, ["mock"])
43 self.check_success_after_reset(proc_mock)
45 def test_slurm_bypassed_when_no_arvados_node(self, proc_mock):
46 # Test we correctly handle a node that failed to bootstrap.
47 proc_mock.return_value = 'idle\n'
49 self.check_success_flag(True)
50 self.assertFalse(proc_mock.called)
52 def test_node_undrained_when_shutdown_window_closes(self, proc_mock):
53 proc_mock.return_value = 'alloc\n'
54 self.make_mocks(arvados_node=testutil.arvados_node_mock(job_uuid=True))
56 self.check_success_flag(False, 2)
57 self.check_slurm_got_args(proc_mock, 'NodeName=compute99',