Beispiel #1
0
 def test_asks_region_for_monitoring_state(self):
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateInterfaces, region.GetDiscoveryState
     )
     self.addCleanup((yield connecting))
     rpc_service = services.getServiceNamed("rpc")
     reactor = Clock()
     service = RackNetworksMonitoringService(
         rpc_service,
         reactor,
         enable_monitoring=False,
         enable_beaconing=False,
     )
     protocol.GetDiscoveryState.return_value = {"interfaces": {}}
     # Put something in the cache. This tells recordInterfaces that refresh
     # has already run but the interfaces have changed thus they need to be
     # updated.
     service._recorded = {}
     yield service.startService()
     yield maybeDeferred(service.getDiscoveryState)
     yield service.stopService()
     self.assertThat(
         protocol.GetDiscoveryState,
         MockCalledOnceWith(
             protocol, system_id=rpc_service.getClient().localIdent
         ),
     )
Beispiel #2
0
    def test_runs_refresh_first_time(self):
        fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
        protocol, connecting = fixture.makeEventLoop(region.RequestRackRefresh)
        self.addCleanup((yield connecting))

        rpc_service = services.getServiceNamed("rpc")
        service = RackNetworksMonitoringService(
            rpc_service,
            Clock(),
            enable_monitoring=False,
            enable_beaconing=False,
        )

        yield maybeDeferred(service.startService)
        # By stopping the interface_monitor first, we assure that the loop
        # happens at least once before the service stops completely.
        yield maybeDeferred(service.interface_monitor.stopService)
        yield maybeDeferred(service.stopService)

        self.assertThat(
            protocol.RequestRackRefresh,
            MockCalledOnceWith(
                protocol, system_id=rpc_service.getClient().localIdent
            ),
        )
Beispiel #3
0
    def test_reports_interfaces_to_region(self):
        fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
        protocol, connecting = fixture.makeEventLoop(region.UpdateInterfaces)
        self.addCleanup((yield connecting))

        interfaces = {
            "eth0": {
                "type": "physical",
                "mac_address": factory.make_mac_address(),
                "parents": [],
                "links": [],
                "enabled": True,
            }
        }

        rpc_service = services.getServiceNamed('rpc')
        service = RackNetworksMonitoringService(rpc_service,
                                                Clock(),
                                                enable_monitoring=False)
        service.getInterfaces = lambda: succeed(interfaces)
        # Put something in the cache. This tells recordInterfaces that refresh
        # has already run but the interfaces have changed thus they need to be
        # updated.
        service._recorded = {}

        service.startService()
        yield service.stopService()

        self.assertThat(
            protocol.UpdateInterfaces,
            MockCalledOnceWith(protocol,
                               system_id=rpc_service.getClient().localIdent,
                               interfaces=interfaces))
Beispiel #4
0
 def test_reports_mdns_to_region(self):
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateInterfaces, region.ReportMDNSEntries
     )
     self.addCleanup((yield connecting))
     rpc_service = services.getServiceNamed("rpc")
     service = RackNetworksMonitoringService(
         rpc_service,
         Clock(),
         enable_monitoring=False,
         enable_beaconing=False,
     )
     mdns = [
         {
             "interface": "eth0",
             "hostname": "boggle.example.com",
             "address": factory.make_ip_address(),
         }
     ]
     yield service.reportMDNSEntries(mdns)
     self.assertThat(
         protocol.ReportMDNSEntries,
         MockCalledOnceWith(
             protocol,
             system_id=rpc_service.getClient().localIdent,
             mdns=mdns,
         ),
     )
Beispiel #5
0
    def test_reports_interfaces_with_hints_if_beaconing_enabled(self):
        fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
        protocol, connecting = fixture.makeEventLoop(region.UpdateInterfaces)
        # Don't actually wait for beaconing to complete.
        pause_mock = self.patch(services_module, "pause")
        queue_mcast_mock = self.patch(
            services_module.BeaconingSocketProtocol, "queueMulticastBeaconing"
        )
        self.addCleanup((yield connecting))

        interfaces = {
            "eth0": {
                "type": "physical",
                "mac_address": factory.make_mac_address(),
                "parents": [],
                "links": [],
                "enabled": True,
            }
        }

        rpc_service = services.getServiceNamed("rpc")
        service = RackNetworksMonitoringService(
            rpc_service,
            Clock(),
            enable_monitoring=False,
            enable_beaconing=True,
        )
        service.getInterfaces = lambda: succeed(interfaces)
        # Put something in the cache. This tells recordInterfaces that refresh
        # has already run but the interfaces have changed thus they need to be
        # updated.
        service._recorded = {}

        service.startService()
        yield service.stopService()

        self.assertThat(
            protocol.UpdateInterfaces,
            MockCalledOnceWith(
                protocol,
                system_id=rpc_service.getClient().localIdent,
                interfaces=interfaces,
                topology_hints=[],
            ),
        )
        # The service should have sent out beacons, waited three seconds,
        # solicited for more beacons, then waited another three seconds before
        # deciding that beaconing is complete.
        self.assertThat(pause_mock, MockCallsMatch(call(3.0), call(3.0)))
        self.assertThat(
            queue_mcast_mock,
            MockCallsMatch(
                # Called when the service starts.
                call(solicitation=True),
                # Called three seconds later.
                call(solicitation=True),
                # Not called again when the service shuts down.
            ),
        )
 def test_get_refresh_details_not_running(self):
     yield self.create_fake_rpc_service()
     rpc_service = services.getServiceNamed("rpc")
     service = RackNetworksMonitoringService(
         rpc_service,
         Clock(),
         enable_monitoring=False,
         enable_beaconing=False,
     )
     service.running = 0
     details = yield service.getRefreshDetails()
     self.assertEqual((None, None, None), details)
 def test_reports_neighbours_to_region(self):
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateInterfaces, region.ReportNeighbours)
     self.addCleanup((yield connecting))
     rpc_service = services.getServiceNamed('rpc')
     service = RackNetworksMonitoringService(
         rpc_service, Clock(), enable_monitoring=False,
         enable_beaconing=False)
     neighbours = [{"ip": factory.make_ip_address()}]
     yield service.reportNeighbours(neighbours)
     self.assertThat(
         protocol.ReportNeighbours, MockCalledOnceWith(
             protocol, system_id=rpc_service.getClient().localIdent,
             neighbours=neighbours))
    def test_reports_interfaces_to_region(self):
        def refresh(
            system_id,
            consumer_key,
            token_key,
            token_secret,
            maas_url=None,
            post_process_hook=None,
        ):
            self.assertEqual("", system_id)
            self.assertEqual(self.metadata_creds["consumer_key"], consumer_key)
            self.assertEqual(self.metadata_creds["token_key"], token_key)
            self.assertEqual(self.metadata_creds["token_secret"], token_secret)
            self.assertEqual("http://localhost/MAAS", maas_url)

        yield self.create_fake_rpc_service()
        self.mock_refresh.side_effect = refresh

        interfaces = {
            "eth0": {
                "type": "physical",
                "mac_address": factory.make_mac_address(),
                "parents": [],
                "links": [],
                "enabled": True,
            }
        }

        update_interfaces_deferred = Deferred()
        rpc_service = services.getServiceNamed("rpc")
        service = RackNetworksMonitoringService(
            rpc_service,
            Clock(),
            enable_monitoring=False,
            enable_beaconing=False,
            update_interfaces_deferred=update_interfaces_deferred,
        )
        service.getInterfaces = lambda: succeed(interfaces)
        # Put something in the cache. This tells recordInterfaces that refresh
        # has already run but the interfaces have changed thus they need to be
        # updated.
        service._recorded = {}

        service.startService()
        yield update_interfaces_deferred
        yield service.stopService()

        self.assertEquals(1, self.mock_refresh.call_count)
    def test_reports_interfaces_with_hints_if_beaconing_enabled(self):
        yield self.create_fake_rpc_service()
        # Don't actually wait for beaconing to complete.
        pause_mock = self.patch(services_module, "pause")
        queue_mcast_mock = self.patch(
            services_module.BeaconingSocketProtocol, "queueMulticastBeaconing"
        )

        interfaces = {
            "eth0": {
                "type": "physical",
                "mac_address": factory.make_mac_address(),
                "parents": [],
                "links": [],
                "enabled": True,
            }
        }

        rpc_service = services.getServiceNamed("rpc")
        service = RackNetworksMonitoringService(
            rpc_service,
            Clock(),
            enable_monitoring=False,
            enable_beaconing=True,
        )
        service.getInterfaces = lambda: succeed(interfaces)

        service.startService()
        # By stopping the interface_monitor first, we assure that the loop
        # happens at least once before the service stops completely.
        yield maybeDeferred(service.interface_monitor.stopService)
        yield service.stopService()

        # The service should have sent out beacons, waited three seconds,
        # solicited for more beacons, then waited another three seconds before
        # deciding that beaconing is complete.
        self.assertThat(pause_mock, MockCallsMatch(call(3.0), call(3.0)))
        self.assertThat(
            queue_mcast_mock,
            MockCallsMatch(
                # Called when the service starts.
                call(solicitation=True),
                # Called three seconds later.
                call(solicitation=True),
                # Not called again when the service shuts down.
            ),
        )
Beispiel #10
0
    def test_runs_refresh_first_time(self):
        fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
        protocol, connecting = fixture.makeEventLoop(region.RequestRackRefresh)
        self.addCleanup((yield connecting))

        rpc_service = services.getServiceNamed('rpc')
        service = RackNetworksMonitoringService(rpc_service,
                                                Clock(),
                                                enable_monitoring=False)

        yield service.startService()
        yield service.stopService()

        self.assertThat(
            protocol.RequestRackRefresh,
            MockCalledOnceWith(protocol,
                               system_id=rpc_service.getClient().localIdent))
Beispiel #11
0
 def test_get_refresh_details_running(self):
     yield self.create_fake_rpc_service()
     rpc_service = services.getServiceNamed("rpc")
     service = RackNetworksMonitoringService(
         rpc_service,
         Clock(),
         enable_monitoring=False,
         enable_beaconing=False,
     )
     service.running = 1
     self.metadata_creds.update({
         "consumer_key": "my-key",
         "token_key": "my-token",
         "token_secret": "my-secret",
     })
     details = yield service.getRefreshDetails()
     self.assertEqual(("http://localhost/MAAS", "", self.metadata_creds),
                      details)
 def test_requests_beaconing_when_timer_fires(self):
     fixture = self.useFixture(MockLiveClusterToRegionRPCFixture())
     protocol, connecting = fixture.makeEventLoop(
         region.UpdateInterfaces, region.GetDiscoveryState)
     self.addCleanup((yield connecting))
     rpc_service = services.getServiceNamed('rpc')
     reactor = Clock()
     service = RackNetworksMonitoringService(
         rpc_service, reactor, enable_monitoring=False,
         enable_beaconing=True)
     service.beaconing_protocol = Mock()
     service.beaconing_protocol.queueMulticastBeaconing = Mock()
     service.getInterfaces = lambda: succeed({})
     service._recorded = {}
     service.startService()
     yield service.stopService()
     self.assertThat(
         service.beaconing_protocol.queueMulticastBeaconing,
         MockCallsMatch(call()))
Beispiel #13
0
 def connected(teardown):
     test.addCleanup(teardown)
     return services.getServiceNamed("rpc"), protocol
Beispiel #14
0
    def render_GET(self, request):
        # Be sure that the TFTP endpoint is running.
        try:
            tftp = services.getServiceNamed("tftp")
        except KeyError:
            # TFTP service is not installed cannot handle a boot request.
            request.setResponseCode(503)
            return b"HTTP boot service not ready."

        # Extract the local servers IP/port of the request.
        localHost = request.getHeader("X-Server-Addr")
        try:
            localPort = int(request.getHeader("X-Server-Port"))
        except (TypeError, ValueError):
            localPort = 0

        # Extract the original clients IP/port of the request.
        remoteHost = request.getHeader("X-Forwarded-For")
        try:
            remotePort = int(request.getHeader("X-Forwarded-Port"))
        except (TypeError, ValueError):
            remotePort = 0

        # localHost and remoteHost are required headers.
        if not localHost or not remoteHost:
            request.setResponseCode(400)
            return b"Missing X-Server-Addr and X-Forwarded-For HTTP headers."

        def handleFailure(failure):
            if failure.check(AccessViolation):
                request.setResponseCode(403)
                request.write(b"")
            elif failure.check(FileNotFound):
                request.setResponseCode(404)
                request.write(b"")
            else:
                log.err(failure, "Failed to handle boot HTTP request.")
                request.setResponseCode(500)
                request.write(str(failure.value).encode("utf-8"))
            request.finish()

        def writeResponse(reader):
            # Some readers from `tftp` do not provide a way to get the size
            # of the generated content. Only set `Content-Length` when size
            # can be determined for the response.
            if hasattr(reader, "size"):
                request.setHeader(b"Content-Length", reader.size)

            # The readers from `tftp` use `finish` instead of `close`, but
            # `NoRangeStaticProducer` expects `close` instead of `finish`. Map
            # `finish` to `close` so the file handlers are cleaned up.
            reader.close = reader.finish

            # Produce the result without allowing range. This producer will
            # call `close` on the reader and `finish` on the request when done.
            producer = NoRangeStaticProducer(request, reader)
            producer.start()

        path = b"/".join(request.postpath)
        d = context.call(
            {
                "local": (localHost, localPort),
                "remote": (remoteHost, remotePort),
            },
            tftp.backend.get_reader,
            path,
            skip_logging=True,
        )
        d.addCallback(writeResponse)
        d.addErrback(handleFailure)
        d.addErrback(log.err, "Failed to handle boot HTTP request.")

        # Log the HTTP request to rackd.log and push that event to the
        # region controller.
        log_path = path.decode("utf-8")
        log.info(
            "{path} requested by {remoteHost}",
            path=log_path,
            remoteHost=remoteHost,
        )
        d = deferLater(
            reactor,
            0,
            send_node_event_ip_address,
            event_type=EVENT_TYPES.NODE_HTTP_REQUEST,
            ip_address=remoteHost,
            description=log_path,
        )
        d.addErrback(log.err, "Logging HTTP request failed.")

        # Response is handled in the defer.
        return NOT_DONE_YET