Exemple #1
0
    def test_tryUpdate_writes_nginx_config_reloads_nginx(self):
        self.useFixture(MAASRootFixture())
        rpc_service, _ = yield prepareRegion(self)
        region_ips = self.extract_regions(rpc_service)
        resource_root = self.make_dir() + "/"
        service = self.make_startable_RackHTTPService(resource_root,
                                                      rpc_service, reactor)

        # Mock service_monitor to catch reloadService.
        mock_reloadService = self.patch(http.service_monitor, "reloadService")
        mock_reloadService.return_value = always_succeed_with(None)

        yield service.startService()
        self.addCleanup((yield service.stopService))
        yield service._orig_tryUpdate()

        # Verify the contents of the written config.
        target_path = http.compose_http_config_path("rackd.nginx.conf")
        self.assertThat(
            target_path,
            FileContains(matcher=Contains("alias %s;" % resource_root)),
        )
        for region_ip in region_ips:
            self.assertThat(
                target_path,
                FileContains(matcher=Contains("server %s:5240;" % region_ip)),
            )
        self.assertThat(
            target_path,
            FileContains(
                matcher=Contains("proxy_pass http://maas-regions/MAAS/;")),
        )
        self.assertThat(mock_reloadService, MockCalledOnceWith("http"))

        # If the configuration has not changed then a second call to
        # `_tryUpdate` does not result in another call to `_configure`.
        yield service._orig_tryUpdate()
        self.assertThat(mock_reloadService, MockCalledOnceWith("http"))
Exemple #2
0
    def test__calls_are_made_to_all_clusters(self):
        rpc_fixture = self.prepare_live_rpc()
        rack_controllers = [factory.make_RackController() for _ in range(3)]
        protocols = []
        rack_creds = []
        for rack in rack_controllers:
            tokens = list(get_auth_tokens(rack.owner))
            if len(tokens) > 0:
                # Use the latest token.
                token = tokens[-1]
            else:
                token = create_auth_token(rack.owner)
            creds = convert_tuple_to_string(get_creds_tuple(token))
            rack_creds.append(creds)

            protocol = rpc_fixture.makeCluster(rack, EvaluateTag)
            protocol.EvaluateTag.side_effect = always_succeed_with({})
            protocols.append(protocol)
        tag = factory.make_Tag(populate=False)

        [d] = populate_tags(tag)

        # `d` is a testing-only convenience. We must wait for it to fire, and
        # we must do that from the reactor thread.
        wait_for_populate = asynchronous(lambda: d)
        wait_for_populate().wait(10)

        for rack, protocol, creds in zip(rack_controllers, protocols,
                                         rack_creds):
            self.expectThat(
                protocol.EvaluateTag,
                MockCalledOnceWith(protocol,
                                   tag_name=tag.name,
                                   tag_definition=tag.definition,
                                   system_id=rack.system_id,
                                   tag_nsmap=ANY,
                                   credentials=creds,
                                   nodes=ANY))
Exemple #3
0
    def test_render_GET_500_server_error(self):
        path = factory.make_name("path")
        ip = factory.make_ip_address()
        request = DummyRequest([path.encode("utf-8")])
        request.requestHeaders = Headers({
            "X-Server-Addr": ["192.168.1.1"],
            "X-Server-Port": ["5248"],
            "X-Forwarded-For": [ip],
            "X-Forwarded-Port": ["%s" % factory.pick_port()],
        })

        self.patch(http.log, "info")
        mock_deferLater = self.patch(http, "deferLater")
        mock_deferLater.side_effect = always_succeed_with(None)

        exc = factory.make_exception("internal error")
        self.tftp.backend.get_reader.return_value = fail(exc)

        resource = http.HTTPBootResource()
        yield self.render_GET(resource, request)

        self.assertEqual(500, request.responseCode)
        self.assertEqual(str(exc).encode("utf-8"), b"".join(request.written))
Exemple #4
0
    def test_tryUpdate_logs_errors_from_broken_method(self):
        service = ntp.RegionNetworkTimeProtocolService(reactor)
        broken_method = self.patch_autospec(service, self.method)
        broken_method.side_effect = factory.make_exception()

        # Ensure that we never actually execute against systemd or write an
        # actual configuration file.
        self.patch_autospec(
            ntp, "deferToThread").side_effect = always_succeed_with(None)
        self.patch_autospec(service_monitor, "restartService")

        with TwistedLoggerFixture() as logger:
            yield service._tryUpdate()

        self.assertThat(
            logger.output,
            DocTestMatches("""
                Failed to update NTP configuration.
                Traceback (most recent call last):
                ...
                maastesting.factory.TestException#...
                """),
        )
Exemple #5
0
    def test_render_GET_400_when_no_local_addr(self):
        path = factory.make_name("path")
        ip = factory.make_ip_address()
        request = DummyRequest([path.encode("utf-8")])
        request.requestHeaders = Headers(
            {
                "X-Forwarded-For": [ip],
                "X-Forwarded-Port": ["%s" % factory.pick_port()],
            }
        )

        self.patch(http.log, "info")
        mock_deferLater = self.patch(http, "deferLater")
        mock_deferLater.side_effect = always_succeed_with(None)

        resource = http.HTTPBootResource()
        yield self.render_GET(resource, request)

        self.assertEquals(400, request.responseCode)
        self.assertEquals(
            b"Missing X-Server-Addr and X-Forwarded-For HTTP headers.",
            b"".join(request.written),
        )
Exemple #6
0
    def test_render_GET_500_server_error(self):
        path = factory.make_name('path')
        ip = factory.make_ip_address()
        request = DummyRequest([path.encode('utf-8')])
        request.requestHeaders = Headers({
            'X-Server-Addr': ['192.168.1.1'],
            'X-Server-Port': ['5248'],
            'X-Forwarded-For': [ip],
            'X-Forwarded-Port': ['%s' % factory.pick_port()],
        })

        self.patch(http.log, 'info')
        mock_deferLater = self.patch(http, 'deferLater')
        mock_deferLater.side_effect = always_succeed_with(None)

        exc = factory.make_exception("internal error")
        self.tftp.backend.get_reader.return_value = fail(exc)

        resource = http.HTTPBootResource()
        yield self.render_GET(resource, request)

        self.assertEquals(500, request.responseCode)
        self.assertEquals(str(exc).encode('utf-8'), b''.join(request.written))
Exemple #7
0
    def makeEventLoop(self, *commands):
        """Make and add a new stub event-loop for the given `commands`.

        See `make_amp_protocol_factory` for details.
        """
        if region.Identify not in commands:
            commands = commands + (region.Identify,)
        if region.Authenticate not in commands:
            commands = commands + (region.Authenticate,)
        if region.RegisterRackController not in commands:
            commands = commands + (region.RegisterRackController,)
        if amp.StartTLS not in commands:
            commands = commands + (amp.StartTLS,)
        protocol_factory = make_amp_protocol_factory(*commands)
        protocol = protocol_factory()
        eventloop = self.getEventLoopName(protocol)
        protocol.Identify.return_value = {"ident": eventloop}
        protocol.Authenticate.side_effect = self._authenticate_with_cluster_key
        protocol.RegisterRackController.side_effect = always_succeed_with(
            {"system_id": ""}
        )
        protocol.StartTLS.return_value = get_tls_parameters_for_region()
        return protocol, self.addEventLoop(protocol)
Exemple #8
0
    def test_render_GET_logs_node_event_with_original_path_ip(self):
        path = factory.make_name("path")
        ip = factory.make_ip_address()
        request = DummyRequest([path.encode("utf-8")])
        request.requestHeaders = Headers({
            "X-Server-Addr": ["192.168.1.1"],
            "X-Server-Port": ["5248"],
            "X-Forwarded-For": [ip],
            "X-Forwarded-Port": ["%s" % factory.pick_port()],
        })

        log_info = self.patch(http.log, "info")
        mock_deferLater = self.patch(http, "deferLater")
        mock_deferLater.side_effect = always_succeed_with(None)

        self.tftp.backend.get_reader.return_value = fail(AccessViolation())

        resource = http.HTTPBootResource()
        yield self.render_GET(resource, request)

        self.assertThat(
            log_info,
            MockCalledOnceWith("{path} requested by {remoteHost}",
                               path=path,
                               remoteHost=ip),
        )
        self.assertThat(
            mock_deferLater,
            MockCalledOnceWith(
                ANY,
                0,
                http.send_node_event_ip_address,
                event_type=EVENT_TYPES.NODE_HTTP_REQUEST,
                ip_address=ip,
                description=path,
            ),
        )
Exemple #9
0
 def patch_methods_using_rpc(self):
     pcs = self.patch_autospec(power, "power_change_starting")
     pcs.return_value = always_succeed_with(None)
     cps = self.patch_autospec(power, "change_power_state")
     cps.return_value = always_succeed_with(None)
 def patch_authenticate_for_failure(self, client):
     authenticate = self.patch_autospec(client, "authenticateCluster")
     authenticate.side_effect = always_succeed_with(False)
Exemple #11
0
def prepareRegion(
    test,
    *,
    is_region=False,
    is_rack=True,
    servers=None,
    peers=None,
    trusted_networks=None,
    proxy_enabled=True,
    proxy_port=8000,
    proxy_allowed_cidrs=None,
    proxy_prefer_v4_proxy=False,
    syslog_port=5247
):
    """Set up a mock region controller.

    It responds to `GetControllerType`, `GetTimeConfiguration`,
    `GetDNSConfiguration`, `GetProxyConfiguration`, and
    `GetSyslogConfiguration`.

    :return: The running RPC service, and the protocol instance.
    """
    fixture = test.useFixture(MockLiveClusterToRegionRPCFixture())
    protocol, connecting = fixture.makeEventLoop(
        region.GetControllerType,
        region.GetTimeConfiguration,
        region.GetDNSConfiguration,
        region.GetProxyConfiguration,
        region.GetSyslogConfiguration,
    )
    protocol.RegisterRackController.side_effect = always_succeed_with(
        {"system_id": factory.make_name("maas-id")}
    )
    protocol.GetControllerType.side_effect = always_succeed_with(
        {"is_region": is_region, "is_rack": is_rack}
    )
    protocol.GetTimeConfiguration.side_effect = always_succeed_with(
        {
            "servers": [] if servers is None else servers,
            "peers": [] if peers is None else peers,
        }
    )
    protocol.GetDNSConfiguration.side_effect = always_succeed_with(
        {
            "trusted_networks": (
                [] if trusted_networks is None else trusted_networks
            )
        }
    )
    if proxy_allowed_cidrs is None:
        proxy_allowed_cidrs = []
    protocol.GetProxyConfiguration.side_effect = always_succeed_with(
        {
            "enabled": proxy_enabled,
            "port": proxy_port,
            "allowed_cidrs": proxy_allowed_cidrs,
            "prefer_v4_proxy": proxy_prefer_v4_proxy,
        }
    )
    protocol.GetSyslogConfiguration.side_effect = always_succeed_with(
        {"port": syslog_port}
    )

    def connected(teardown):
        test.addCleanup(teardown)
        return services.getServiceNamed("rpc"), protocol

    return connecting.addCallback(connected)
Exemple #12
0
def make_startable_RackExternalService(test, *args, **kwargs):
    service = external.RackExternalService(*args, **kwargs)
    service._orig_tryUpdate = service._tryUpdate
    test.patch(service, "_tryUpdate").return_value = always_succeed_with(None)
    service.call = (service._tryUpdate, tuple(), {})
    return service