示例#1
0
    def make_IPCMasterService(self, workers=None):
        master = IPCMasterService(reactor,
                                  workers=workers,
                                  socket_path=self.ipc_path)

        dv_connected = DeferredValue()
        original_registerWorker = master.registerWorker

        def mock_registerWorker(*args, **kwargs):
            original_registerWorker(*args, **kwargs)
            dv_connected.set(None)

        new_registerWorker = self.patch(master, 'registerWorker')
        new_registerWorker.side_effect = mock_registerWorker

        dv_disconnected = DeferredValue()
        original_unregisterWorker = master.unregisterWorker

        def mock_unregisterWorker(*args, **kwargs):
            original_unregisterWorker(*args, **kwargs)
            dv_disconnected.set(None)

        new_unregisterWorker = self.patch(master, 'unregisterWorker')
        new_unregisterWorker.side_effect = mock_unregisterWorker

        return master, dv_connected, dv_disconnected
示例#2
0
文件: events.py 项目: zhangrb/maas
    def registerEventType(self, event_type):
        """Ensure that `event_type` is known to the region.

        This populates the cache used by `ensureEventTypeRegistered` but does
        not consult it; it always attempts to contact the region.

        :return: :class:`Deferred`
        """
        details = EVENT_DETAILS[event_type]

        def register(client):
            return client(RegisterEventType,
                          name=event_type,
                          level=details.level,
                          description=details.description)

        d = maybeDeferred(getRegionClient).addCallback(register)
        # Whatever happens, we are now done registering.
        d.addBoth(callOut, self._types_registering.pop, event_type)
        # On success, record that the event type has been registered. On
        # failure, ensure that the set of registered event types does NOT
        # contain the event type.
        d.addCallbacks(callback=callOut,
                       callbackArgs=(self._types_registered.add, event_type),
                       errback=callOut,
                       errbackArgs=(self._types_registered.discard,
                                    event_type))
        # Capture the result into a DeferredValue.
        result = DeferredValue()
        result.capture(d)
        # Keep track of it so that concurrent requests don't duplicate work.
        self._types_registering[event_type] = result
        return result.get()
示例#3
0
    def test_processNotification_gets_called_multiple_times(self):
        socket_path = self.patch_socket_path()
        service = LeaseSocketService(sentinel.service, reactor)
        dvs = [
            DeferredValue(),
            DeferredValue(),
        ]

        # Mock processNotifcation to catch the call.
        def mock_processNotification(*args, **kwargs):
            for dv in dvs:
                if not dv.isSet:
                    dv.set(args)
                    break

        self.patch(service, "processNotification", mock_processNotification)

        # Start the service and stop it at the end of the test.
        service.startService()
        self.addCleanup(service.stopService)

        # Create test payload to send.
        packet1 = {"test1": factory.make_name("test1")}
        packet2 = {"test2": factory.make_name("test2")}

        # Send notifications to the socket and wait for notifications.
        yield deferToThread(self.send_notification, socket_path, packet1)
        yield deferToThread(self.send_notification, socket_path, packet2)
        yield dvs[0].get(timeout=10)
        yield dvs[1].get(timeout=10)

        # Packet should be the argument passed to processNotification in
        # order.
        self.assertEquals((packet1, ), dvs[0].value)
        self.assertEquals((packet2, ), dvs[1].value)
示例#4
0
    def test_killWorker_spawns_another(self):
        service = WorkersService(reactor, worker_count=1, worker_cmd="cat")

        dv = DeferredValue()
        original_unregisterWorker = service.unregisterWorker

        def mock_unregisterWorker(*args, **kwargs):
            original_unregisterWorker(*args, **kwargs)
            dv.set(None)

        self.patch(
            service, "unregisterWorker"
        ).side_effect = mock_unregisterWorker

        try:
            service.startService()

            self.assertEquals(1, len(service.workers))
            pid = list(service.workers.keys())[0]
            service.killWorker(pid)
            yield dv.get(timeout=2)
            self.assertNotIn(pid, service.workers)
            self.assertEquals(1, len(service.workers))
        finally:
            service.stopService()
示例#5
0
 def stopService(self):
     """Disconnect from UNIX socket."""
     self.starting.cancel()
     if self._protocol:
         self.protocol = DeferredValue()
         self.processId = DeferredValue()
         self._protocol, protocol = None, self._protocol
         if protocol.transport:
             protocol.transport.loseConnection()
     return super(IPCWorkerService, self).stopService()
示例#6
0
 def __init__(self, reactor, socket_path=None):
     super(IPCWorkerService, self).__init__()
     self.reactor = reactor
     self.socket_path = socket_path
     if self.socket_path is None:
         self.socket_path = get_ipc_socket_path()
     self.endpoint = UNIXClientEndpoint(reactor, self.socket_path)
     self._protocol = None
     self.protocol = DeferredValue()
     self.processId = DeferredValue()
示例#7
0
 def test__calls_handler_on_notification(self):
     listener = PostgresListenerService()
     dv = DeferredValue()
     listener.register("machine", lambda *args: dv.set(args))
     yield listener.startService()
     try:
         yield deferToDatabase(self.send_notification, "machine_create", 1)
         yield dv.get(timeout=2)
         self.assertEqual(('create', '1'), dv.value)
     finally:
         yield listener.stopService()
示例#8
0
 def test_calls_handler_on_notification(self):
     listener = PostgresListenerService()
     listener.HANDLE_NOTIFY_DELAY = listener.CHANNEL_REGISTRAR_DELAY = 0
     dv = DeferredValue()
     listener.register("machine", lambda *args: dv.set(args))
     yield listener.startService()
     yield listener.channelRegistrarDone
     try:
         yield deferToDatabase(self.send_notification, "machine_create", 1)
         yield dv.get(timeout=2)
         self.assertEqual(("create", "1"), dv.value)
     finally:
         yield listener.stopService()
示例#9
0
 def test__calls_handler_on_notification_with_delayed_registration(self):
     listener = PostgresListenerService()
     dv = DeferredValue()
     yield listener.startService()
     try:
         # Register after the service has been started. The handler should
         # still be called.
         listener.register("machine", lambda *args: dv.set(args))
         yield deferToDatabase(self.send_notification, "machine_create", 1)
         yield dv.get(timeout=2)
         self.assertEqual(('create', '1'), dv.value)
     finally:
         yield listener.stopService()
示例#10
0
 def test__calls_system_handler_on_notification(self):
     listener = PostgresListenerService()
     # Change notifications to a frozenset. This makes sure that
     # the system message does not go into the queue. Instead if should
     # call the handler directly in `doRead`.
     listener.notifications = frozenset()
     dv = DeferredValue()
     listener.register("sys_test", lambda *args: dv.set(args))
     yield listener.startService()
     try:
         yield deferToDatabase(self.send_notification, "sys_test", 1)
         yield dv.get(timeout=2)
         self.assertEqual(("sys_test", "1"), dv.value)
     finally:
         yield listener.stopService()
示例#11
0
    def catch_packet_on_socket(self):
        socket_path = self.patch_socket_path()
        service = LeaseSocketService(sentinel.service, reactor)
        dv = DeferredValue()

        def mock_processNotification(*args, **kwargs):
            dv.set(args)

        self.patch(service, "processNotification", mock_processNotification)

        return socket_path, service, dv
示例#12
0
    def wrap_async_method(self, obj, method_name):
        dv = DeferredValue()
        original_method = getattr(obj, method_name)

        def mock_method(*args, **kwargs):
            d = original_method(*args, **kwargs)
            d.addCallback(callOut, dv.set, None)
            return d

        new_method = self.patch(obj, method_name)
        new_method.side_effect = mock_method
        return dv
示例#13
0
    def test_stopService_doesnt(self):
        service = WorkersService(reactor, worker_count=1, worker_cmd="cat")

        dv = DeferredValue()
        original_unregisterWorker = service.unregisterWorker

        def mock_unregisterWorker(*args, **kwargs):
            original_unregisterWorker(*args, **kwargs)
            dv.set(None)

        self.patch(service,
                   "unregisterWorker").side_effect = mock_unregisterWorker

        try:
            service.startService()
            self.assertEqual(1, len(service.workers))
        finally:
            service.stopService()

        yield dv.get(timeout=2)
        self.assertEqual({}, service.workers)
示例#14
0
    def test_stopService_doesnt(self):
        service = HTTPImageService(reactor, 1, worker_cmd='cat')

        dv = DeferredValue()
        original_unregisterWorker = service.unregisterWorker

        def mock_unregisterWorker(*args, **kwargs):
            original_unregisterWorker(*args, **kwargs)
            dv.set(None)

        self.patch(service,
                   'unregisterWorker').side_effect = (mock_unregisterWorker)

        try:
            service.startService()
            self.assertEquals(1, len(service.workers))
        finally:
            service.stopService()

        yield dv.get(timeout=2)
        self.assertEqual({}, service.workers)
示例#15
0
    def test_stopping_cancels_start(self):
        listener = PostgresListenerService()

        # Start then stop immediately, without waiting for start to complete.
        starting = listener.startService()
        starting_spy = DeferredValue()
        starting_spy.observe(starting)
        stopping = listener.stopService()

        # Both `starting` and `stopping` have callbacks yet to fire.
        self.assertThat(starting.callbacks, Not(Equals([])))
        self.assertThat(stopping.callbacks, Not(Equals([])))

        # Wait for the listener to stop.
        yield stopping

        # Neither `starting` nor `stopping` have callbacks. This is because
        # `stopping` chained itself onto the end of `starting`.
        self.assertThat(starting.callbacks, Equals([]))
        self.assertThat(stopping.callbacks, Equals([]))

        # Confirmation that `starting` was cancelled.
        with ExpectedException(CancelledError):
            yield starting_spy.get()
示例#16
0
    def test_processNotification_gets_called_with_notification(self):
        socket_path = self.patch_socket_path()
        service = LeaseSocketService(sentinel.service, reactor)
        dv = DeferredValue()

        # Mock processNotifcation to catch the call.
        def mock_processNotification(*args, **kwargs):
            dv.set(args)

        self.patch(service, "processNotification", mock_processNotification)

        # Start the service and stop it at the end of the test.
        service.startService()
        self.addCleanup(service.stopService)

        # Create test payload to send.
        packet = {"test": factory.make_name("test")}

        # Send notification to the socket and wait for notification.
        yield deferToThread(self.send_notification, socket_path, packet)
        yield dv.get(timeout=10)

        # Packet should be the argument passed to processNotifcation
        self.assertEquals((packet, ), dv.value)
示例#17
0
class IPCWorkerService(service.Service, object):
    """
    IPC worker service.

    Provides the worker side of the IPC communication to the master.
    """

    def __init__(self, reactor, socket_path=None):
        super(IPCWorkerService, self).__init__()
        self.reactor = reactor
        self.socket_path = socket_path
        if self.socket_path is None:
            self.socket_path = get_ipc_socket_path()
        self.endpoint = UNIXClientEndpoint(reactor, self.socket_path)
        self._protocol = None
        self.protocol = DeferredValue()
        self.processId = DeferredValue()

    @asynchronous
    def startService(self):
        """Connect to UNIX socket."""
        super(IPCWorkerService, self).startService()
        protocol = IPCWorker()
        protocol.service = self
        self.starting = connectProtocol(self.endpoint, protocol)

        def save_protocol(protocol):
            self._protocol = protocol

        def log_failure(failure):
            if failure.check(CancelledError):
                log.msg("IPCWorkerService start-up has been cancelled.")
            else:
                log.err(failure, "IPCWorkerService start-up failed.")

        self.starting.addCallback(save_protocol)
        self.starting.addErrback(log_failure)

        # Twisted's service framework does not track start-up progress, i.e.
        # it does not check for Deferreds returned by startService(). Here we
        # return a Deferred anyway so that direct callers (esp. those from
        # tests) can easily wait for start-up.
        return self.starting

    @asynchronous
    def stopService(self):
        """Disconnect from UNIX socket."""
        self.starting.cancel()
        if self._protocol:
            self.protocol = DeferredValue()
            self.processId = DeferredValue()
            self._protocol, protocol = None, self._protocol
            if protocol.transport:
                protocol.transport.loseConnection()
        return super(IPCWorkerService, self).stopService()

    @asynchronous
    def rpcPublish(self, port):
        """Publish the RPC port to the region."""
        d = self.protocol.get()
        d.addCallback(
            lambda protocol: protocol.callRemote(
                RPCEndpointPublish, pid=os.getpid(), port=port))
        return d

    @asynchronous
    def rpcRegisterConnection(self, connid, ident, host, port):
        """Register RPC connection on master."""
        d = self.protocol.get()
        d.addCallback(
            lambda protocol: protocol.callRemote(
                RPCRegisterConnection, pid=os.getpid(),
                connid=connid, ident=ident, host=host, port=port))
        return d

    @asynchronous
    def rpcUnregisterConnection(self, connid):
        """Unregister RPC connection on master."""
        d = self.protocol.get()
        d.addCallback(
            lambda protocol: protocol.callRemote(
                RPCUnregisterConnection, pid=os.getpid(), connid=connid))
        return d