Exemple #1
0
 def test__returns_None_when_node_not_found(self):
     logger = self.useFixture(FakeLogger("maas", logging.DEBUG))
     client = self.patch(windows_module, "getRegionClient").return_value
     client.side_effect = always_fail_with(NoSuchNode())
     mac = factory.make_mac_address()
     d = windows_module.request_node_info_by_mac_address(mac)
     self.assertThat(extract_result(d), Is(None))
     self.assertDocTestMatches(
         "Node doesn't exist for MAC address: %s" % mac,
         logger.output)
Exemple #2
0
    def test_unhandled_errors_do_not_cause_disconnection(self):
        self.patch(common.log, "debug")
        protocol = common.RPCProtocol()
        protocol.makeConnection(StringTransport())
        # Ensure that the superclass dispatchCommand() will fail.
        dispatchCommand = self.patch(amp.AMP, "dispatchCommand")
        dispatchCommand.side_effect = always_fail_with(ZeroDivisionError())
        # Push a command box into the protocol.
        seq = b"%d" % random.randrange(0, 2**32)
        cmd = factory.make_string().encode("ascii")
        box = amp.AmpBox(_ask=seq, _command=cmd)
        with TwistedLoggerFixture() as logger:
            protocol.ampBoxReceived(box)
        # The transport is still connected.
        self.expectThat(protocol.transport.disconnecting, Is(False))
        # The error has been logged on the originating side of the AMP
        # session, along with an explanatory message. The message includes a
        # command reference.
        cmd_ref = common.make_command_ref(box)
        self.assertDocTestMatches(
            """\
            Unhandled failure dispatching AMP command. This is probably a bug.
            Please ensure that this error is handled within application code
            or declared in the signature of the %s command. [%s]
            Traceback (most recent call last):
            ...

            """ % (cmd, cmd_ref),
            logger.output,
        )
        # A simpler error message has been transmitted over the wire. It
        # includes the same command reference as logged locally.
        protocol.transport.io.seek(0)
        observed_boxes_sent = amp.parse(protocol.transport.io)
        expected_boxes_sent = [
            amp.AmpBox(
                _error=seq,
                _error_code=amp.UNHANDLED_ERROR_CODE,
                _error_description=(b"Unknown Error [%s]" %
                                    cmd_ref.encode("ascii")),
            )
        ]
        self.assertThat(observed_boxes_sent, Equals(expected_boxes_sent))
Exemple #3
0
    def test_logs_failures(self):
        rack_controllers = [factory.make_RackController()]
        clients = self.patch_clients(rack_controllers)
        clients[0].side_effect = always_fail_with(
            ZeroDivisionError("splendid day for a spot of cricket"))

        tag_name = factory.make_name("tag")
        tag_definition = factory.make_name("definition")
        tag_nsmap = {}

        work = []
        for rack, client in zip(rack_controllers, clients):
            work.append({
                "system_id":
                rack.system_id,
                "hostname":
                rack.hostname,
                "client":
                client,
                "tag_name":
                tag_name,
                "tag_definition":
                tag_definition,
                "tag_nsmap":
                tag_nsmap,
                "credentials":
                factory.make_name("creds"),
                "nodes": [{
                    "system_id": factory.make_Node().system_id
                } for _ in range(3)],
            })

        with FakeLogger("maas") as log:
            [d] = _do_populate_tags(work)
            self.assertIsNone(extract_result(d))

        self.assertDocTestMatches(
            "Tag tag-... (definition-...) could not be evaluated ... (...): "
            "splendid day for a spot of cricket",
            log.output,
        )
Exemple #4
0
    def test_report_power_state_reports_all_exceptions(self):
        logger_twisted = self.useFixture(TwistedLoggerFixture())
        logger_maaslog = self.useFixture(FakeLogger("maas"))

        # Avoid threads here.
        self.patch(power, "deferToThread", maybeDeferred)

        exception_type = factory.make_exception_type()
        exception_message = factory.make_string()
        exception = exception_type(exception_message)

        # Pretend the query always fails with `exception`.
        query = self.patch_autospec(power, self.func)
        query.side_effect = always_fail_with(exception)

        # Intercept calls to power_state_update() and send_node_event().
        power_state_update = self.patch_autospec(power, "power_state_update")
        power_state_update.return_value = succeed(None)
        send_node_event = self.patch_autospec(power, "send_node_event")
        send_node_event.return_value = succeed(None)

        self.patch(
            self.power_driver, "detect_missing_packages"
        ).return_value = []

        system_id = factory.make_name("system_id")
        hostname = factory.make_name("hostname")
        context = sentinel.context
        clock = Clock()

        d = power.get_power_state(
            system_id, hostname, self.power_type, context, clock
        )
        d = power.report_power_state(d, system_id, hostname)

        # Crank through some number of retries.
        for wait in self.waits:
            self.assertFalse(d.called)
            clock.advance(wait)
        self.assertTrue(d.called)

        # Finally the exception from the query is raised.
        self.assertRaises(exception_type, extract_result, d)

        # The broken power query function patched earlier was called the same
        # number of times as there are steps in the default waiting policy.
        expected_call = call(system_id, hostname, self.power_type, context)
        expected_calls = [expected_call] * self.calls
        self.assertThat(query, MockCallsMatch(*expected_calls))

        expected_message = "%s: Power state could not be queried: %s" % (
            hostname,
            exception_message,
        )

        # An attempt was made to report the failure to the region.
        self.assertThat(
            power_state_update, MockCalledOnceWith(system_id, "error")
        )
        # An attempt was made to log a node event with details.
        self.assertThat(
            send_node_event,
            MockCalledOnceWith(
                EVENT_TYPES.NODE_POWER_QUERY_FAILED,
                system_id,
                hostname,
                exception_message,
            ),
        )

        # Nothing was logged to the Twisted log.
        self.assertEqual("", logger_twisted.output)
        # A brief message is written to maaslog.
        self.assertEqual(expected_message + "\n", logger_maaslog.output)
 def patch_authenticate_for_error(self, client, exception):
     authenticate = self.patch_autospec(client, "authenticateCluster")
     authenticate.side_effect = always_fail_with(exception)
Exemple #6
0
 def test__returns_None_when_node_not_found(self):
     client = self.patch(windows_module, "getRegionClient").return_value
     client.side_effect = always_fail_with(NoSuchNode())
     mac = factory.make_mac_address()
     d = windows_module.request_node_info_by_mac_address(mac)
     self.assertThat(extract_result(d), Is(None))