def test_run_scripts_adds_data(self): scripts_dir = factory.make_name('scripts_dir') out_dir = os.path.join(scripts_dir, 'out') self.patch(maas_run_remote_scripts, 'install_dependencies') self.patch(maas_run_remote_scripts, 'run_script') url = factory.make_url() creds = factory.make_name('creds') script = make_script(scripts_dir=scripts_dir) script.pop('result', None) script.pop('combined', None) script.pop('stderr', None) script.pop('stdout', None) script['args'] = { 'url': url, 'creds': creds, 'script_result_id': script['script_result_id'], 'script_version_id': script['script_version_id'], } scripts = [{ 'name': script['name'], 'path': script['path'], 'script_result_id': script['script_result_id'], 'script_version_id': script['script_version_id'], 'timeout_seconds': script['timeout_seconds'], 'parallel': script['parallel'], 'hardware_type': script['hardware_type'], 'has_started': script['has_started'], }] run_scripts(url, creds, scripts_dir, out_dir, scripts) scripts[0].pop('thread', None) self.assertDictEqual(script, scripts[0])
def test_run_scripts(self): mock_install_deps = self.patch( maas_run_remote_scripts, 'install_dependencies') mock_run_script = self.patch(maas_run_remote_scripts, 'run_script') single_thread = make_scripts(instance=False, parallel=0) instance_thread = [ make_scripts(parallel=1) for _ in range(3) ] any_thread = make_scripts(instance=False, parallel=2) scripts = copy.deepcopy(single_thread) for instance_thread_group in instance_thread: scripts += copy.deepcopy(instance_thread_group) scripts += copy.deepcopy(any_thread) url = factory.make_url() creds = factory.make_name('creds') scripts_dir = factory.make_name('scripts_dir') out_dir = os.path.join(scripts_dir, 'out') run_scripts(url, creds, scripts_dir, out_dir, scripts) self.assertEquals( len(single_thread) + len(instance_thread) + len(any_thread), mock_install_deps.call_count) expected_calls = [ call(script=script, scripts_dir=scripts_dir, send_result=True) for script in sorted(scripts, key=lambda i: ( 99 if i['hardware_type'] == 0 else i['hardware_type'], i['name'])) if script['parallel'] != 2 ] expected_calls += [ call(script=script, scripts_dir=scripts_dir, send_result=True) for script in sorted(scripts, key=lambda i: ( len(i.get('packages', {}).keys()), i['name'])) if script['parallel'] == 2 ] self.assertThat(mock_run_script, MockCallsMatch(*expected_calls))
def test_run_scripts_signals_failure(self): scripts_dir = self.useFixture(TempDirectory()).path mock_signal = self.patch(maas_run_remote_scripts, 'signal') self.patch(maas_run_remote_scripts, 'Popen') self.patch(maas_run_remote_scripts, 'capture_script_output') scripts = self.make_scripts() self.make_script_output(scripts, scripts_dir) # Don't need to give the url or creds as we're not running the scripts # and sending the result. The scripts_dir and out_dir are the same as # in the test environment there isn't anything in the scripts_dir. # Returns one due to mock_run.returncode returning a MagicMock which is # detected as a failed script run. self.assertEquals( 1, run_scripts(None, None, scripts_dir, scripts_dir, scripts)) self.assertThat( mock_signal, MockAnyCall(None, None, 'FAILED', '1 scripts failed to run'))
def test_run_scripts_signals_timeout(self): scripts_dir = self.useFixture(TempDirectory()).path mock_signal = self.patch(maas_run_remote_scripts, 'signal') self.patch(maas_run_remote_scripts, 'Popen') scripts = self.make_scripts() self.make_script_output(scripts, scripts_dir) mock_cap = self.patch(maas_run_remote_scripts, 'capture_script_output') mock_cap.side_effect = TimeoutExpired( [factory.make_name('arg') for _ in range(3)], scripts[0]['timeout_seconds']) # Don't need to give the url or creds as we're not running the scripts # and sending the result. The scripts_dir and out_dir are the same as # in the test environment there isn't anything in the scripts_dir. self.assertEquals( 1, run_scripts(None, None, scripts_dir, scripts_dir, scripts)) self.assertThat( mock_signal, MockAnyCall(creds=None, url=None, status='TIMEDOUT', error='Timeout(%s) expired on %s [1/1]' % (str(timedelta(seconds=scripts[0]['timeout_seconds'])), scripts[0]['name']), script_result_id=scripts[0]['script_result_id'], script_version_id=scripts[0]['script_version_id'], files={ scripts[0]['name']: scripts[0]['output'], '%s.out' % scripts[0]['name']: scripts[0]['stdout'], '%s.err' % scripts[0]['name']: scripts[0]['stderr'], })) self.assertThat( mock_signal, MockAnyCall(None, None, 'FAILED', '1 scripts failed to run'))
def test_run_scripts_signals_failure_on_unexecutable_script_baderrno(self): # Regression test for LP:1669246 scripts_dir = self.useFixture(TempDirectory()).path mock_signal = self.patch(maas_run_remote_scripts, 'signal') mock_popen = self.patch(maas_run_remote_scripts, 'Popen') mock_popen.side_effect = OSError(0, 'Exec format error') self.patch(maas_run_remote_scripts, 'capture_script_output') scripts = self.make_scripts() script = scripts[0] self.make_script_output(scripts, scripts_dir) # Don't need to give the url or creds as we're not running the scripts # and sending the result. The scripts_dir and out_dir are the same as # in the test environment there isn't anything in the scripts_dir. # Returns one due to mock_run.returncode returning a MagicMock which is # detected as a failed script run. self.assertEquals( 1, run_scripts(None, None, scripts_dir, scripts_dir, scripts)) self.assertThat( mock_signal, MockAnyCall(creds=None, url=None, status='WORKING', exit_status=2, error='Failed to execute %s [1/1]: 2' % script['name'], script_result_id=script['script_result_id'], script_version_id=script['script_version_id'], files={ script['name']: b'[Errno 0] Exec format error', '%s.err' % script['name']: b'[Errno 0] Exec format error', })) self.assertThat( mock_signal, MockAnyCall(None, None, 'FAILED', '1 scripts failed to run'))
def test_run_scripts(self): scripts_dir = self.useFixture(TempDirectory()).path mock_signal = self.patch(maas_run_remote_scripts, 'signal') mock_popen = self.patch(maas_run_remote_scripts, 'Popen') mock_capture_script_output = self.patch(maas_run_remote_scripts, 'capture_script_output') scripts = self.make_scripts() self.make_script_output(scripts, scripts_dir) # Don't need to give the url or creds as we're not running the scripts # and sending the result. The scripts_dir and out_dir are the same as # in the test environment there isn't anything in the scripts_dir. # Returns one due to mock_run.returncode returning a MagicMock which is # detected as a failed script run. self.assertEquals( 1, run_scripts(None, None, scripts_dir, scripts_dir, scripts)) args = { 'url': None, 'creds': None, 'status': 'WORKING', 'script_result_id': scripts[0]['script_result_id'], 'script_version_id': scripts[0]['script_version_id'], 'error': 'Starting %s [1/1]' % scripts[0]['name'], } self.assertThat(mock_signal, MockAnyCall(**args)) self.assertThat(mock_popen, MockCalledOnce()) self.assertThat(mock_capture_script_output, MockCalledOnce()) # This is a MagicMock args['exit_status'] = ANY args['files'] = { scripts[0]['name']: scripts[0]['output'], '%s.out' % scripts[0]['name']: scripts[0]['stdout'], '%s.err' % scripts[0]['name']: scripts[0]['stderr'], } args['error'] = 'Finished %s [1/1]: 1' % scripts[0]['name'] self.assertThat(mock_signal, MockAnyCall(**args))