def test_get_ports_archive_url(self): mirrors = { "main": urlparse(factory.make_url("ports")), "ports": urlparse(factory.make_url("ports")), } return_value = succeed(mirrors) protocol, connecting = self.patch_rpc_methods(return_value) self.addCleanup((yield connecting)) value = yield get_ports_archive_url() expected_url = mirrors["ports"].geturl() self.assertEqual(expected_url, value)
def test_refresh_signals_failure(self): signal = self.patch(refresh, "signal") self.patch_scripts_failure() system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "FAILED", "Failed refreshing %s" % system_id, ), )
def test_refresh_signals_failure_on_unexecutable_script_baderrno(self): signal = self.patch(refresh, "signal") script_name = factory.make_name("script_name") self.patch_scripts_failure(script_name) mock_popen = self.patch(refresh, "Popen") mock_popen.side_effect = OSError(0, "Exec format error") system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "WORKING", files={ script_name: b"[Errno 0] Exec format error", "%s.err" % script_name: b"[Errno 0] Exec format error", }, exit_status=2, error="Failed to execute %s [1/1]: 2" % script_name, ), )
def test_refresh_executes_lxd_binary(self): signal = self.patch(refresh, "signal") script_name = LXD_OUTPUT_NAME self.patch_scripts_success(script_name) system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "WORKING", "Starting %s [1/1]" % script_name, ), )
def test__get_boot_sources_v1_sets_os_to_wildcard(self): sources = [{ "path": factory.make_url(), "selections": [ { "release": "trusty", "arches": ["amd64"], "subarches": ["generic"], "labels": ["release"], }, { "release": "precise", "arches": ["amd64"], "subarches": ["generic"], "labels": ["release"], }, ], }] clock = Clock() client_call = Mock() client_call.side_effect = [ defer.fail(UnhandledCommand()), defer.succeed(dict(sources=sources)), ] service = ImageDownloadService(sentinel.rpc, sentinel.tftp_root, clock) sources = yield service._get_boot_sources(client_call) os_selections = [ selection.get("os") for source in sources["sources"] for selection in source["selections"] ] self.assertEqual(["*", "*"], os_selections)
def test_refresh_signals_finished(self): signal = self.patch(refresh, 'signal') script_name = factory.make_name('script_name') self.patch_scripts_success(script_name) system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'OK', "Finished refreshing %s" % system_id, ))
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_sends_results_raises_podactionfail_on_signalexception(self): mock_signal = self.patch(pods, "signal") err_msg = factory.make_name("error_message") mock_signal.side_effect = SignalException(err_msg) name = (factory.make_name("name"),) system_id = factory.make_name("system_id") fake_driver = MagicMock() fake_driver.get_commissioning_data.return_value = succeed( {factory.make_name("filename"): factory.make_name("data")} ) self.patch(PodDriverRegistry, "get_item").return_value = fake_driver with ExpectedException( exceptions.PodActionFail, re.escape( f"Unable to send Pod commissioning information for {name}({system_id}): {err_msg}" ), ): yield pods.send_pod_commissioning_results( pod_type=factory.make_name("type"), context={}, pod_id=random.randint(1, 10), name=name, system_id=system_id, consumer_key=factory.make_name("consumer_key"), token_key=factory.make_name("token_key"), token_secret=factory.make_name("token_secret"), metadata_url=urlparse(factory.make_url()), )
def test_signal_formats_params_with_moonshot_power_params(self): mock_encode_multipart_data = self.patch( maas_api_helper, 'encode_multipart_data') mock_encode_multipart_data.return_value = None, None mock_geturl = self.patch(maas_api_helper, 'geturl') mock_geturl.return_value = b'OK' status = factory.make_name('status') power_type = 'moonshot' power_params = OrderedDict([ ('power_user', factory.make_name('power_user')), ('power_pass', factory.make_name('power_pass')), ('power_address', factory.make_url()), ('power_hwaddress', factory.make_name('power_hwaddress')), ]) # None used for url and creds as we're not actually sending data. maas_api_helper.signal( None, None, status, power_type=power_type, power_params=','.join([value for value in power_params.values()])) # XXX ltrager 2017-01-18 - The power_parameters JSON dump breaks # MockCalledWith. self.assertDictEqual( mock_encode_multipart_data.call_args[0][0], { b'op': b'signal', b'status': status.encode('utf-8'), b'power_type': power_type.encode('utf-8'), b'power_parameters': json.dumps(power_params).encode(), }) self.assertThat(mock_geturl, MockCalledOnce())
def test_refresh_runs_script_sudo_if_no_snap(self): self.mock_running_in_snap.return_value = False mock_popen = self.patch(refresh, "Popen") mock_popen.side_effect = OSError() self.patch(refresh, "signal") script_name = factory.make_name("script_name") script_content = dedent("""\ #!/bin/bash echo 'test script' echo '{status: skipped}' > $RESULT_PATH """) info_scripts = self.create_scripts_success( script_name, script_content=script_content) system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh(system_id, consumer_key, token_key, token_secret, url) script_path = (Path(refresh.__file__) / ".." / script_name).resolve() mock_popen.assert_called_once_with( ["sudo", "-E", str(script_path)], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=ANY, )
def test_refresh_accepts_defined_url(self): signal = self.patch(refresh, 'signal') script_name = factory.make_name('script_name') self.patch_scripts_success(script_name) system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'WORKING', 'Starting %s [1/1]' % script_name, ))
def test_refresh_signals_failure_on_unexecutable_script_baderrno(self): signal = self.patch(refresh, 'signal') script_name = factory.make_name('script_name') self.patch_scripts_failure(script_name) mock_popen = self.patch(refresh, 'Popen') mock_popen.side_effect = OSError(0, 'Exec format error') system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'WORKING', files={ script_name: b'[Errno 0] Exec format error', '%s.err' % script_name: b'[Errno 0] Exec format error', }, exit_status=2, error='Failed to execute %s [1/1]: 2' % script_name, ))
def test_refresh_signals_results(self): signal = self.patch(refresh, 'signal') script_name = factory.make_name('script_name') self.patch_scripts_success(script_name) system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'WORKING', files={ script_name: b'test script\n', '%s.out' % script_name: b'test script\n', '%s.err' % script_name: b'', }, exit_status=0, error='Finished %s [1/1]: 0' % script_name, ))
def test_refresh_signals_failure(self): signal = self.patch(refresh, "signal") info_scripts = self.create_scripts_failure() system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh( system_id, consumer_key, token_key, token_secret, url ) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "FAILED", "Failed refreshing %s" % system_id, ), )
def test_refresh_executes_lxd_binary_in_snap(self): signal = self.patch(refresh, "signal") script_name = LXD_OUTPUT_NAME info_scripts = self.create_scripts_success(script_name) path = factory.make_name() self.patch(os, "environ", {"SNAP": path}) system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh( system_id, consumer_key, token_key, token_secret, url ) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "WORKING", "Starting %s [1/1]" % script_name, ), )
def test_refresh_signals_failure_on_timeout(self): signal = self.patch(refresh, 'signal') script_name = factory.make_name('script_name') timeout = timedelta(seconds=random.randint(1, 500)) self.patch_scripts_failure(script_name, timeout) self.patch(refresh.maas_api_helper, 'timedelta').return_value = (timedelta(microseconds=1)) system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'TIMEDOUT', files={ script_name: b'test failed\n', '%s.out' % script_name: b'test failed\n', '%s.err' % script_name: b'', }, error='Timeout(%s) expired on %s [1/1]' % (str(timeout), script_name), ))
def test_refresh_sets_env_vars(self): self.patch(refresh, "signal") script_name = factory.make_name("script_name") info_scripts = self.create_scripts_failure(script_name) mock_popen = self.patch(refresh, "Popen") mock_popen.side_effect = OSError(8, "Exec format error") system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh( system_id, consumer_key, token_key, token_secret, url ) env = mock_popen.call_args[1]["env"] for name in [ "OUTPUT_COMBINED_PATH", "OUTPUT_STDOUT_PATH", "OUTPUT_STDERR_PATH", "RESULT_PATH", ]: self.assertIn(name, env) self.assertIn(script_name, env[name])
def test_refresh_signals_starting(self): signal = self.patch(refresh, "signal") script_name = factory.make_name("script_name") info_scripts = self.create_scripts_success(script_name) system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh( system_id, consumer_key, token_key, token_secret, url ) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "WORKING", "Starting %s [1/1]" % script_name, ), )
def test_refresh_executes_lxd_binary_in_snap(self): signal = self.patch(refresh, 'signal') script_name = LXD_OUTPUT_NAME self.patch_scripts_success(script_name) path = factory.make_name() self.patch(os, "environ", { "SNAP": path }) system_id = factory.make_name('system_id') consumer_key = factory.make_name('consumer_key') token_key = factory.make_name('token_key') token_secret = factory.make_name('token_secret') url = factory.make_url() refresh.refresh( system_id, consumer_key, token_key, token_secret, url) self.assertThat(signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { 'consumer_secret': '', 'consumer_key': consumer_key, 'token_key': token_key, 'token_secret': token_secret, }, 'WORKING', 'Starting %s [1/1]' % script_name, ))
def test_refresh_signals_failure_on_unexecutable_script_baderrno(self): signal = self.patch(refresh, "signal") script_name = factory.make_name("script_name") info_scripts = self.create_scripts_failure(script_name) mock_popen = self.patch(refresh, "Popen") mock_popen.side_effect = OSError(0, "Exec format error") system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh(system_id, consumer_key, token_key, token_secret, url) self.assertThat( signal, MockAnyCall( ANY, ANY, "WORKING", files={ script_name: b"[Errno 0] Exec format error", "%s.err" % script_name: b"[Errno 0] Exec format error", }, exit_status=2, error="Failed to execute %s [1/1]: 2" % script_name, ), )
def test_doesnt_pass_user_agent_when_not_set(self): mock_UrlMirrorReader = self.patch(download_descriptions, "UrlMirrorReader") self.patch(download_descriptions.RepoDumper, "sync") path = factory.make_url() download_descriptions.download_image_descriptions(path) self.assertThat(mock_UrlMirrorReader, MockCalledOnceWith(ANY, policy=ANY))
def test_dispatch_query_encodes_string_data(self): # urllib, used by MAASDispatcher, requires data encoded into bytes. We # encode into utf-8 in dispatch_query if necessary. request = self.patch(urllib.request.Request, "__init__") self.patch_urllib() self.open_func = lambda *args: MagicMock() url = factory.make_url() data = factory.make_string(300, spaces=True) MAASDispatcher().dispatch_query(url, {}, method="POST", data=data) request.assert_called_once_with(ANY, url, bytes(data, "utf-8"), ANY)
def test_heartbeat(self): mock_signal = self.patch(maas_run_remote_scripts, 'signal') url = factory.make_url() creds = factory.make_name('creds') heart_beat = maas_run_remote_scripts.HeartBeat(url, creds) start_time = time.time() heart_beat.start() heart_beat.stop() self.assertLess(time.time() - start_time, 1) self.assertThat(mock_signal, MockCalledOnceWith(url, creds, 'WORKING'))
def test_passes_user_agent(self): mock_UrlMirrorReader = self.patch(download_descriptions, "UrlMirrorReader") self.patch(download_descriptions.RepoDumper, "sync") path = factory.make_url() user_agent = factory.make_name("agent") download_descriptions.download_image_descriptions( path, user_agent=user_agent) self.assertThat( mock_UrlMirrorReader, MockCalledOnceWith(ANY, policy=ANY, user_agent=user_agent))
def test_unknown_pod_raises_UnknownPodType(self): with ExpectedException(exceptions.UnknownPodType): yield pods.send_pod_commissioning_results( pod_type=factory.make_name("type"), context={}, pod_id=random.randint(1, 10), name=factory.make_name("name"), system_id=factory.make_name("system_id"), consumer_key=factory.make_name("consumer_key"), token_key=factory.make_name("token_key"), token_secret=factory.make_name("token_secret"), metadata_url=urlparse(factory.make_url()), )
def test_no_autodetects_proxies(self): self.open_func = lambda *args: MagicMock() url = factory.make_url() proxy_variables = { "http_proxy": "http://proxy.example.com", "https_proxy": "https://proxy.example.com", "no_proxy": "noproxy.example.com", } with patch.dict(os.environ, proxy_variables): dispatcher = MAASDispatcher(autodetect_proxies=False) dispatcher.dispatch_query(url, {}, method="GET") for handler in self.opener.handle_open["http"]: if isinstance(handler, urllib.request.ProxyHandler): raise AssertionError("ProxyHandler shouldn't be there")
def test_heartbeat_with_long_sleep(self): mock_signal = self.patch(maas_run_remote_scripts, 'signal') self.patch(maas_run_remote_scripts.time, 'monotonic').side_effect = [ time.monotonic(), time.monotonic(), time.monotonic() + 500, ] url = factory.make_url() creds = factory.make_name('creds') heart_beat = maas_run_remote_scripts.HeartBeat(url, creds) start_time = time.time() heart_beat.start() heart_beat.stop() self.assertLess(time.time() - start_time, 1) self.assertThat(mock_signal, MockCalledOnceWith(url, creds, 'WORKING'))
def test_doesnt_pass_user_agenton_fallback(self): mock_UrlMirrorReader = self.patch(download_descriptions, "UrlMirrorReader") mock_UrlMirrorReader.side_effect = [TypeError(), Mock()] self.patch(download_descriptions.RepoDumper, "sync") path = factory.make_url() user_agent = factory.make_name("agent") download_descriptions.download_image_descriptions( path, user_agent=user_agent) self.assertThat( mock_UrlMirrorReader, MockCallsMatch( call(ANY, policy=ANY, user_agent=user_agent), call(ANY, policy=ANY), ), )
def test_power_off(self): mock_webhook_request = self.patch(self.webhook, "_webhook_request") system_id = factory.make_name("system_id") power_off_uri = factory.make_url() self.webhook.power_off(system_id, {"power_off_uri": power_off_uri}) self.assertThat( mock_webhook_request, MockCalledOnceWith( b"POST", power_off_uri.encode(), self.webhook._make_auth_headers(system_id, {}), False, ), )
def test_refresh_signals_failure_on_timeout(self): signal = self.patch(refresh, "signal") script_name = factory.make_name("script_name") info_scripts = self.create_scripts_failure(script_name) system_id = factory.make_name("system_id") consumer_key = factory.make_name("consumer_key") token_key = factory.make_name("token_key") token_secret = factory.make_name("token_secret") url = factory.make_url() def timeout_run( proc, combined_path, stdout_path, stderr_path, timeout_seconds ): # Contract of capture_script_output is to create these files for path in (stdout_path, stderr_path, combined_path): open(path, "w").close() raise TimeoutExpired(proc.args, timeout_seconds) mock_capture_script_output = self.patch( refresh, "capture_script_output" ) mock_capture_script_output.side_effect = timeout_run with patch.dict(refresh.NODE_INFO_SCRIPTS, info_scripts, clear=True): refresh.refresh( system_id, consumer_key, token_key, token_secret, url ) self.assertThat( signal, MockAnyCall( "%s/metadata/%s/" % (url, MD_VERSION), { "consumer_secret": "", "consumer_key": consumer_key, "token_key": token_key, "token_secret": token_secret, }, "TIMEDOUT", files={ script_name: b"", "%s.out" % script_name: b"", "%s.err" % script_name: b"", }, error="Timeout(60) expired on %s [1/1]" % script_name, ), )