示例#1
0
    def test_get_boot_method_render_substitutes_armhf_in_params(self):
        # get_config_reader() should substitute "arm" for "armhf" in the
        # arch field of the parameters (mapping from pxe to maas
        # namespace).
        config_path = b"pxelinux.cfg/default-arm"
        backend = TFTPBackend(self.make_dir(), "http://example.com/")
        # python-tx-tftp sets up call context so that backends can discover
        # more about the environment in which they're running.
        call_context = {
            "local": (factory.make_ipv4_address(), factory.pick_port()),
            "remote": (factory.make_ipv4_address(), factory.pick_port()),
        }

        @partial(self.patch, backend, "get_boot_method_reader")
        def get_boot_method_reader(boot_method, params):
            params_json = json.dumps(params).encode("ascii")
            params_json_reader = BytesReader(params_json)
            return succeed(params_json_reader)

        reader = yield context.call(
            call_context, backend.get_reader, config_path
        )
        output = reader.read(10000).decode("ascii")
        observed_params = json.loads(output)
        # XXX: GavinPanella 2015-11-25 bug=1519804: get_by_pxealias() on
        # ArchitectureRegistry is not stable, so we permit either here.
        self.assertIn(observed_params["arch"], ["armhf", "arm64"])
示例#2
0
    def test_make_parsed_url_asserts_with_conflicting_port_numbers(self):
        with ExpectedException(AssertionError):
            netloc = "%s:%d" % (factory.make_hostname(), factory.pick_port())
            factory.make_parsed_url(netloc=netloc, port=factory.pick_port())

        with ExpectedException(AssertionError):
            netloc = "%s:%d" % (factory.make_hostname(), factory.pick_port())
            factory.make_parsed_url(netloc=netloc, port=True)
示例#3
0
 def test_get_render_file_with_ipv4_hosts(self):
     return self._test_get_render_file(
         local=(
             factory.make_ipv4_address(),
             factory.pick_port()),
         remote=(
             factory.make_ipv4_address(),
             factory.pick_port()),
     )
示例#4
0
 def test_get_render_file_with_ipv6_hosts(self):
     # Some versions of Twisted have the scope and flow info in the remote
     # address tuple. See https://twistedmatrix.com/trac/ticket/6826 (the
     # address is captured by tftp.protocol.TFTP.dataReceived).
     return self._test_get_render_file(
         local=(factory.make_ipv6_address(), factory.pick_port(),
                random.randint(1, 1000), random.randint(1, 1000)),
         remote=(factory.make_ipv6_address(), factory.pick_port(),
                 random.randint(1, 1000), random.randint(1, 1000)),
     )
示例#5
0
    def test_get_remote_mac(self):
        remote_host = factory.make_ipv4_address()
        call_context = {
            "local": (factory.make_ipv4_address(), factory.pick_port()),
            "remote": (remote_host, factory.pick_port()),
        }

        mock_find = self.patch(boot, "find_mac_via_arp")
        yield context.call(call_context, get_remote_mac)
        self.assertThat(mock_find, MockCalledOnceWith(remote_host))
示例#6
0
 def test_set_and_get_tftp_port(self):
     config = ClusterConfiguration({})
     example_port = factory.pick_port()
     config.tftp_port = example_port
     self.assertEqual(example_port, config.tftp_port)
     # It's also stored in the configuration database.
     self.assertEqual({"tftp_port": example_port}, config.store)
示例#7
0
    def test_getConfiguration_returns_configuration_object(self):
        port = factory.pick_port()
        is_region, is_rack = factory.pick_bool(), factory.pick_bool()
        rpc_service, protocol = yield prepareRegion(
            self, is_region=is_region, is_rack=is_rack, syslog_port=port
        )
        forwarders = self.extract_regions(rpc_service)
        service, syslog = self.make_RackSyslog_ExternalService(
            rpc_service, reactor
        )
        yield service.startService()
        self.addCleanup((yield service.stopService))

        config = yield service._getConfiguration()
        observed = syslog._getConfiguration(
            config.controller_type,
            config.syslog_configuration,
            config.connections,
        )

        self.assertThat(observed, IsInstance(external._SyslogConfiguration))
        self.assertThat(
            observed,
            MatchesStructure.byEquality(
                port=port,
                forwarders=forwarders,
                is_region=is_region,
                is_rack=is_rack,
            ),
        )
示例#8
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))
示例#9
0
    def test__tryUpdate_updates_syslog_server(self):
        self.useFixture(MAASRootFixture())
        port = factory.pick_port()
        rpc_service, _ = yield prepareRegion(self, syslog_port=port)
        forwarders = self.extract_regions(rpc_service)
        service, _ = self.make_RackSyslog_ExternalService(rpc_service, reactor)

        write_config = self.patch_autospec(external.syslog_config,
                                           "write_config")
        service_monitor = self.patch_autospec(external, "service_monitor")

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

        yield service._orig_tryUpdate()

        expected_forwards = [{
            "name": name,
            "ip": ip
        } for name, ip in forwarders]
        self.assertThat(
            write_config,
            MockCalledOnceWith(False, forwarders=expected_forwards, port=port),
        )
        self.assertThat(service_monitor.restartService,
                        MockCalledOnceWith("syslog_rack"))
        # 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(
            write_config,
            MockCalledOnceWith(False, forwarders=expected_forwards, port=port),
        )
        self.assertThat(service_monitor.restartService,
                        MockCalledOnceWith("syslog_rack"))
示例#10
0
 def test__preserves_port_with_hostname(self):
     hostname = factory.make_name("host")
     port = factory.pick_port()
     self.assertEqual(
         "https://%s:%s/" % (hostname, port),
         compose_URL("https://:%s/" % port, hostname),
     )
示例#11
0
 def test__preserves_port_with_IPv6(self):
     ip = factory.make_ipv6_address()
     port = factory.pick_port()
     self.assertEqual(
         "https://[%s]:%s/" % (ip, port),
         compose_URL("https://:%s/" % port, ip),
     )
示例#12
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))
示例#13
0
    def test_render_GET_produces_from_reader(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)

        content = factory.make_string(size=100).encode('utf-8')
        reader = BytesReader(content)
        self.tftp.backend.get_reader.return_value = succeed(reader)

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

        self.assertEquals(
            [100], request.responseHeaders.getRawHeaders(b'Content-Length'))
        self.assertEquals(content, b''.join(request.written))
示例#14
0
    def test_render_GET_503_when_no_tftp_service(self):
        # Remove the fake 'tftp' service.
        self.tftp.disownServiceParent()
        self.tftp = None

        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)

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

        self.assertEquals(503, request.responseCode)
        self.assertEquals(b'HTTP boot service not ready.',
                          b''.join(request.written))
示例#15
0
 def test__ignores_protocol_starting_on_events(self):
     event = make_event(
         "%s starting on %d" %
         (factory.make_name("protocol"), factory.pick_port()))
     with TwistedLoggerFixture() as logger:
         observe_twisted_internet_unix(event)
     self.assertThat(logger.events, HasLength(0))
示例#16
0
 def test_make_parsed_url_accepts_explicit_port(self):
     port = factory.pick_port()
     url = factory.make_parsed_url(port=port)
     self.assertThat(
         url.netloc, EndsWith(':%d' % port),
         'The generated URL does not contain'
         'a port specification for port %d' % port)
示例#17
0
    def test_render_GET_503_when_no_tftp_service(self):
        # Remove the fake 'tftp' service.
        self.tftp.disownServiceParent()
        self.tftp = None

        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)

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

        self.assertEqual(503, request.responseCode)
        self.assertEqual(b"HTTP boot service not ready.",
                         b"".join(request.written))
示例#18
0
 def test__ignores_port_closed_events(self):
     event = make_event(
         "(%s Port %d Closed)" %
         (factory.make_name("port-name"), factory.pick_port()))
     with TwistedLoggerFixture() as logger:
         observe_twisted_internet_udp(event)
     self.assertThat(logger.events, HasLength(0))
示例#19
0
    def test_render_GET_produces_from_reader(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)

        content = factory.make_string(size=100).encode("utf-8")
        reader = BytesReader(content)
        self.tftp.backend.get_reader.return_value = succeed(reader)

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

        self.assertEqual(
            [100], request.responseHeaders.getRawHeaders(b"Content-Length"))
        self.assertEqual(content, b"".join(request.written))
示例#20
0
    def test_tftp_service_rebinds_on_HUP(self):
        # Initial set of interfaces to bind to.
        interfaces = {"1.1.1.1", "2.2.2.2"}
        self.patch(
            tftp_module, "get_all_interface_addresses", lambda: interfaces
        )

        tftp_service = TFTPService(
            resource_root=self.make_dir(),
            client_service=Mock(),
            port=factory.pick_port(),
        )
        tftp_service.updateServers()

        # The child services of tftp_services are named after the
        # interface they bind to.
        self.assertEqual(
            interfaces, {server.name for server in tftp_service.getServers()}
        )

        # Update the set of interfaces to bind to.
        interfaces.add("3.3.3.3")
        interfaces.remove("1.1.1.1")

        # Ask the TFTP service to update its set of servers.
        tftp_service.updateServers()

        # We're in the reactor thread but we want to move the reactor
        # forwards, hence we need to get all explicit about it.
        reactor.runUntilCurrent()

        # The interfaces now bound match the updated interfaces set.
        self.assertEqual(
            interfaces, {server.name for server in tftp_service.getServers()}
        )
示例#21
0
    def test_tftp_service_does_not_bind_to_link_local_addresses(self):
        # Initial set of interfaces to bind to.
        ipv4_test_net_3 = IPNetwork("203.0.113.0/24")  # RFC 5737
        normal_addresses = {
            factory.pick_ip_in_network(ipv4_test_net_3),
            factory.make_ipv6_address(),
        }
        link_local_addresses = {
            factory.pick_ip_in_network(IPV4_LINK_LOCAL),
            factory.pick_ip_in_network(IPV6_LINK_LOCAL),
        }
        self.patch(
            tftp_module,
            "get_all_interface_addresses",
            lambda: normal_addresses | link_local_addresses,
        )

        tftp_service = TFTPService(
            resource_root=self.make_dir(),
            client_service=Mock(),
            port=factory.pick_port(),
        )
        tftp_service.updateServers()

        # Only the "normal" addresses have been used.
        self.assertEqual(
            normal_addresses,
            {server.name for server in tftp_service.getServers()},
        )
示例#22
0
 def test_tftp_service(self):
     # A TFTP service is configured and added to the top-level service.
     interfaces = [factory.make_ipv4_address(), factory.make_ipv6_address()]
     self.patch(
         tftp_module, "get_all_interface_addresses", lambda: interfaces
     )
     example_root = self.make_dir()
     example_client_service = Mock()
     example_port = factory.pick_port()
     tftp_service = TFTPService(
         resource_root=example_root,
         client_service=example_client_service,
         port=example_port,
     )
     tftp_service.updateServers()
     # The "tftp" service is a multi-service containing UDP servers for
     # each interface defined by get_all_interface_addresses().
     self.assertIsInstance(tftp_service, MultiService)
     # There's also a TimerService that updates the servers every 45s.
     self.assertThat(
         tftp_service.refresher,
         MatchesStructure.byEquality(
             step=45,
             parent=tftp_service,
             name="refresher",
             call=(tftp_service.updateServers, (), {}),
         ),
     )
     expected_backend = MatchesAll(
         IsInstance(TFTPBackend),
         AfterPreprocessing(
             lambda backend: backend.base.path, Equals(example_root)
         ),
         AfterPreprocessing(
             lambda backend: backend.client_service,
             Equals(example_client_service),
         ),
     )
     expected_protocol = MatchesAll(
         IsInstance(TFTP),
         AfterPreprocessing(
             lambda protocol: protocol.backend, expected_backend
         ),
     )
     expected_server = MatchesAll(
         IsInstance(internet.UDPServer),
         AfterPreprocessing(lambda service: len(service.args), Equals(2)),
         AfterPreprocessing(
             lambda service: service.args[0], Equals(example_port)  # port
         ),
         AfterPreprocessing(
             lambda service: service.args[1], expected_protocol  # protocol
         ),
     )
     self.assertThat(tftp_service.getServers(), AllMatch(expected_server))
     # Only the interface used for each service differs.
     self.assertItemsEqual(
         [svc.kwargs for svc in tftp_service.getServers()],
         [{"interface": interface} for interface in interfaces],
     )
示例#23
0
 def test__parses_URL_with_hostname_and_port(self):
     hostname = factory.make_name("host").encode("ascii")
     port = factory.pick_port()
     path = factory.make_name("path").encode("ascii")
     uri = get_patched_URI().fromBytes(b"http://%s:%d/%s" %
                                       (hostname, port, path))
     self.expectThat(uri.host, Equals(hostname))
     self.expectThat(uri.path, Equals(b"/%s" % path))
     self.expectThat(uri.port, Equals(port))
示例#24
0
 def test__parses_URL_with_hostname_and_port(self):
     hostname = factory.make_name('host').encode('ascii')
     port = factory.pick_port()
     path = factory.make_name('path').encode('ascii')
     uri = get_patched_URI().fromBytes(b'http://%s:%d/%s' %
                                       (hostname, port, path))
     self.expectThat(uri.host, Equals(hostname))
     self.expectThat(uri.path, Equals(b'/%s' % path))
     self.expectThat(uri.port, Equals(port))
示例#25
0
 def test__parses_URL_with_IPv6_address_and_port(self):
     ip = factory.make_ipv6_address().encode('ascii')
     port = factory.pick_port()
     path = factory.make_name('path').encode('ascii')
     uri = get_patched_URI().fromBytes(b'http://[%s]:%d/%s' %
                                       (ip, port, path))
     self.expectThat(uri.host, Equals(b'%s' % ip))
     self.expectThat(uri.path, Equals(b'/%s' % path))
     self.expectThat(uri.port, Equals(port))
示例#26
0
 def test_udp_and_tcp_both_use_different_port(self):
     port = factory.pick_port()
     config.write_config(False, port=port)
     matcher_one = Contains('input(type="imtcp" port="%d")' % port)
     matcher_two = Contains('input(type="imudp" port="%d")' % port)
     self.assertThat(
         "%s/%s" % (self.tmpdir, config.MAAS_SYSLOG_CONF_NAME),
         FileContains(matcher=MatchesAll(matcher_one, matcher_two)),
     )
示例#27
0
 def test__parses_URL_with_IPv4_address_and_port(self):
     ip = factory.make_ipv4_address().encode("ascii")
     port = factory.pick_port()
     path = factory.make_name("path").encode("ascii")
     uri = get_patched_URI().fromBytes(b"http://%s:%d/%s" %
                                       (ip, port, path))
     self.expectThat(uri.host, Equals(ip))
     self.expectThat(uri.path, Equals(b"/%s" % path))
     self.expectThat(uri.port, Equals(port))
示例#28
0
 def make_parameters_context(self):
     return {
         "power_address": "".join(
             [
                 factory.make_name("power_address"),
                 ":%s" % factory.pick_port(),
             ]
         ),
         "instance_name": factory.make_name("instance_name"),
         "password": factory.make_name("password"),
     }
示例#29
0
 def make_protocol(self, patch_authenticate=True, transport_uri=""):
     listener = FakePostgresListenerService()
     factory = WebSocketFactory(listener)
     self.patch(factory, "registerRPCEvents")
     self.patch(factory, "unregisterRPCEvents")
     factory.startFactory()
     self.addCleanup(factory.stopFactory)
     protocol = factory.buildProtocol(None)
     protocol.transport = MagicMock()
     protocol.transport.cookies = b""
     protocol.transport.uri = transport_uri
     protocol.transport.host = random.choice([
         maastesting_factory.make_ipv4_address() +
         ":%d" % maastesting_factory.pick_port(),
         "[" + maastesting_factory.make_ipv6_address() +
         "]:%d" % maastesting_factory.pick_port(),
     ])
     protocol.request = HttpRequest()
     if patch_authenticate:
         self.patch(protocol, "authenticate")
     return protocol, factory
示例#30
0
 def test__set_and_get(self):
     config = RegionConfiguration({})
     if isinstance(getattr(config, self.option), str):
         example_value = factory.make_name(self.option)
     else:
         example_value = factory.pick_port()
     # Argument values will most often be passed in from the command-line,
     # so convert to a string before use to reflect that usage.
     setattr(config, self.option, str(example_value))
     self.assertEqual(example_value, getattr(config, self.option))
     # It's also stored in the configuration database.
     self.assertEqual({self.option: example_value}, config.store)