def test_run_script_uses_timeout_from_parameter(self): scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) script['parameters'] = { 'runtime': { 'type': 'runtime', 'value': random.randint(0, 1000), } } run_script(script, scripts_dir) self.assertThat(self.mock_output_and_send, MockCallsMatch( call('Starting %s' % script['msg_name'], **self.args), call( 'Finished %s: None' % script['msg_name'], exit_status=None, files={ script['combined_name']: script['combined'].encode(), script['stdout_name']: script['stdout'].encode(), script['stderr_name']: script['stderr'].encode(), script['result_name']: script['result'].encode(), }, **self.args), )) self.assertThat(self.mock_capture_script_output, MockCalledOnceWith( ANY, script['combined_path'], script['stdout_path'], script['stderr_path'], script['parameters']['runtime']['value']))
def test_run_script_timed_out_script(self): scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) self.mock_capture_script_output.side_effect = TimeoutExpired( [factory.make_name('arg') for _ in range(3)], script['timeout_seconds']) self.args.pop('status') self.assertFalse(run_script(script, scripts_dir)) self.assertThat(self.mock_output_and_send, MockCallsMatch( call( 'Starting %s' % script['msg_name'], status='WORKING', **self.args), call( 'Timeout(%s) expired on %s' % ( str(timedelta(seconds=script['timeout_seconds'])), script['msg_name']), files={ script['combined_name']: script['combined'].encode(), script['stdout_name']: script['stdout'].encode(), script['stderr_name']: script['stderr'].encode(), script['result_name']: script['result'].encode(), }, status='TIMEDOUT', **self.args), ))
def test_run_script_sets_env(self): scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) mock_popen = self.patch(maas_run_remote_scripts, 'Popen') run_script(script, scripts_dir) env = mock_popen.call_args[1]['env'] self.assertEquals(script['combined_path'], env['OUTPUT_COMBINED_PATH']) self.assertEquals(script['stdout_path'], env['OUTPUT_STDOUT_PATH']) self.assertEquals(script['stderr_path'], env['OUTPUT_STDERR_PATH']) self.assertEquals(script['result_path'], env['RESULT_PATH']) self.assertEquals(script['download_path'], env['DOWNLOAD_PATH']) self.assertEquals(str(script['timeout_seconds']), env['RUNTIME']) self.assertEquals(str(script['has_started']), env['HAS_STARTED']) self.assertIn('PATH', env)
def test_run_script_only_sends_result_when_avail(self): scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) os.remove(script['result_path']) run_script(script, scripts_dir) self.assertThat(self.mock_output_and_send, MockCallsMatch( call('Starting %s' % script['msg_name'], **self.args), call( 'Finished %s: None' % script['msg_name'], exit_status=None, files={ script['combined_name']: script['combined'].encode(), script['stdout_name']: script['stdout'].encode(), script['stderr_name']: script['stderr'].encode(), }, **self.args), )) self.assertThat(self.mock_capture_script_output, MockCalledOnceWith( ANY, script['combined_path'], script['stdout_path'], script['stderr_path'], script['timeout_seconds']))
def test_run_script_errors_with_bad_param(self): fake_block_devices = [{ 'MODEL': factory.make_name('model'), 'SERIAL': factory.make_name('serial'), } for _ in range(3) ] mock_get_block_devices = self.patch( maas_run_remote_scripts, 'get_block_devices') mock_get_block_devices.return_value = fake_block_devices testing_block_device_model = factory.make_name('model') testing_block_device_serial = factory.make_name('serial') scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) script['parameters'] = {'storage': { 'type': 'storage', 'argument_format': '{bad}', 'value': { 'model': testing_block_device_model, 'serial': testing_block_device_serial, }, }} self.assertFalse(run_script(script, scripts_dir)) expected_output = ( "Unable to run '%s': Storage device '%s' with serial '%s' not " 'found!\n\n' "This indicates the storage device has been removed or " "the OS is unable to find it due to a hardware failure. " "Please re-commission this node to re-discover the " "storage devices, or delete this device manually.\n\n" 'Given parameters:\n%s\n\n' 'Discovered storage devices:\n%s\n' % ( script['name'], testing_block_device_model, testing_block_device_serial, str(script['parameters']), str(fake_block_devices)) ) expected_output = expected_output.encode() self.assertThat(self.mock_output_and_send, MockCallsMatch( call('Starting %s' % script['msg_name'], **self.args), call( 'Failed to execute %s: 2' % script['msg_name'], exit_status=2, files={ script['combined_name']: expected_output, script['stderr_name']: expected_output, }, **self.args), ))
def test_run_script_errors_bad_params_on_unexecutable_script_no_errno( self): # Regression test for LP:1669246 scripts_dir = self.useFixture(TempDirectory()).path script = make_script(scripts_dir=scripts_dir) self.mock_capture_script_output.side_effect = OSError() self.assertFalse(run_script(script, scripts_dir)) self.assertThat(self.mock_output_and_send, MockCallsMatch( call('Starting %s' % script['msg_name'], **self.args), call( 'Failed to execute %s: 2' % script['msg_name'], exit_status=2, files={ script['combined_name']: b'Unable to execute script', script['stderr_name']: b'Unable to execute script', }, **self.args), ))