Example #1
0
 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)
Example #2
0
    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,
            ),
        )
Example #3
0
    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,
            ),
        )
Example #4
0
    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,
            ),
        )
Example #5
0
    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)
Example #6
0
    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,
            ))
Example #7
0
 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])
Example #8
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()),
         )
Example #9
0
    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())
Example #10
0
    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,
        )
Example #11
0
    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,
            ))
Example #12
0
    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,
            ))
Example #13
0
    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,
            ))
Example #14
0
    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,
            ),
        )
Example #15
0
    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,
            ),
        )
Example #16
0
    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),
            ))
Example #17
0
    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])
Example #18
0
    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,
            ),
        )
Example #19
0
    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,
        ))
Example #20
0
    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))
Example #22
0
 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)
Example #23
0
 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'))
Example #24
0
 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))
Example #25
0
 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()),
         )
Example #26
0
 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")
Example #27
0
 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),
         ),
     )
Example #29
0
    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,
            ),
        )
Example #30
0
    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,
            ),
        )