def test_get_loop(self): """ Test the get_loop method. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) self.assertFalse(main_loop.get_loop()) main_loop.loop = True self.assertTrue(main_loop.get_loop())
def test_stopping(self): """ Test the get_loop method. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) self.assertFalse(main_loop.stopping()) main_loop.stop_event.set() self.assertTrue(main_loop.stopping())
def on_running(self, event): """ Called when Supervisor is RUNNING. This method start the Supvisors main loop. """ self.logger.info('local supervisord is RUNNING') # replace the default handler for web ui self.info_source.replace_default_handler() # create zmq sockets self.supvisors.zmq = SupvisorsZmq(self.supvisors) # keep a reference to the internal events publisher self.publisher = self.supvisors.zmq.internal_publisher # start the main loop self.main_loop = SupvisorsMainLoop(self.supvisors) self.main_loop.start()
def test_check_events(self, mocked_send, mocked_stderr): """ Test the processing of the events received. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # test with empty socks mocked_subscriber = Mock(socket='zmq socket') socks = {} main_loop.check_events(mocked_subscriber, socks) self.assertEqual(0, mocked_subscriber.call_count) self.assertEqual(0, mocked_send.call_count) # test with appropriate socks but with exception mocked_subscriber = Mock(socket='zmq socket', **{'receive.side_effect': Exception}) socks = {'zmq socket': 1} main_loop.check_events(mocked_subscriber, socks) self.assertEqual(1, mocked_subscriber.receive.call_count) self.assertEqual(0, mocked_send.call_count) mocked_subscriber.receive.reset_mock() # test with appropriate socks and without exception mocked_subscriber = Mock(socket='zmq socket', **{'receive.return_value': 'a zmq message'}) main_loop.check_events(mocked_subscriber, socks) self.assertEqual(1, mocked_subscriber.receive.call_count) self.assertEqual([call('event', '"a zmq message"')], mocked_send.call_args_list)
def test_send_request(self): """ Test the execution of a deferred Supervisor request. """ from supvisors.mainloop import SupvisorsMainLoop from supvisors.utils import DeferredRequestHeaders main_loop = SupvisorsMainLoop(self.supvisors) # patch main loop subscriber with patch.multiple(main_loop, check_address=DEFAULT, start_process=DEFAULT, stop_process=DEFAULT, restart=DEFAULT, shutdown=DEFAULT) as mocked_loop: # test check address self.check_call(main_loop, mocked_loop, 'check_address', DeferredRequestHeaders.CHECK_ADDRESS, ('10.0.0.2', )) # test isolate addresses self.check_call(main_loop, mocked_loop, '', DeferredRequestHeaders.ISOLATE_ADDRESSES, ('10.0.0.2', '10.0.0.3')) # test start process self.check_call(main_loop, mocked_loop, 'start_process', DeferredRequestHeaders.START_PROCESS, ('10.0.0.2', 'dummy_process', 'extra args')) # test stop process self.check_call(main_loop, mocked_loop, 'stop_process', DeferredRequestHeaders.STOP_PROCESS, ('10.0.0.2', 'dummy_process')) # test restart self.check_call(main_loop, mocked_loop, 'restart', DeferredRequestHeaders.RESTART, ('10.0.0.2', )) # test shutdown self.check_call(main_loop, mocked_loop, 'shutdown', DeferredRequestHeaders.SHUTDOWN, ('10.0.0.2', ))
def test_run(self, check_evt, check_rqt, register, unregister, poll): """ Test the running of the main loop thread. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # patch one loops with patch.object(main_loop, 'stopping', side_effect=[False, False, True]): main_loop.run() # test that register was called twice self.assertEqual(2, register.call_count) # test that poll was called once self.assertEqual([call(500)], poll.call_args_list) # test that check_events was called once self.assertEqual(1, check_evt.call_count) # test that check_requests was called once self.assertEqual(1, check_rqt.call_count) # test that unregister was called twice self.assertEqual(2, unregister.call_count)
def test_run(self, register, unregister, poll): """ Test the running of the main loop thread. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # configure patches main_loop.subscriber.receive.side_effect = [Exception, 'subscription'] main_loop.puller.receive.side_effect = [Exception, ('pull', 'data')] # patch 4 loops with patch.object(main_loop, 'get_loop', side_effect=[True] * 4 + [False]): # patch zmq calls: 2 loops for subscriber, 2 loops for puller effects = [{ main_loop.subscriber.socket: 1 }] * 2 + [{ main_loop.puller.socket: 1 }] * 2 poll.side_effect = effects with patch.multiple(main_loop, send_remote_comm_event=DEFAULT, send_request=DEFAULT) as mocked_loop: main_loop.run() # test that poll was called 4 times self.assertEqual([call(500)] * 4, poll.call_args_list) # test that register was called twice self.assertEqual([ call(main_loop.subscriber.socket, 1), call(main_loop.puller.socket, 1) ], register.call_args_list) # test that unregister was called twice self.assertEqual([ call(main_loop.puller.socket), call(main_loop.subscriber.socket) ], unregister.call_args_list) # test that send_remote_comm_event was called once self.assertEqual( [call(u'event', '"subscription"')], mocked_loop['send_remote_comm_event'].call_args_list) # test that send_request was called once self.assertEqual([call('pull', 'data')], mocked_loop['send_request'].call_args_list)
def test_check_requests(self, mocked_send, mocked_stderr): """ Test the processing of the requests received. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # mock parameters mocked_sockets = Mock( puller=Mock(socket='zmq socket', **{'receive.side_effect': Exception}), internal_subscriber=Mock(**{'disconnect.return_value': None})) mocked_receive = mocked_sockets.puller.receive mocked_disconnect = mocked_sockets.internal_subscriber.disconnect # test with empty socks socks = {} main_loop.check_requests(mocked_sockets, socks) self.assertEqual(0, mocked_receive.call_count) self.assertEqual(0, mocked_send.call_count) self.assertEqual(0, mocked_disconnect.call_count) # test with appropriate socks but with exception socks = {'zmq socket': 1} main_loop.check_requests(mocked_sockets, socks) self.assertEqual(1, mocked_receive.call_count) self.assertEqual(0, mocked_send.call_count) self.assertEqual(0, mocked_disconnect.call_count) mocked_receive.reset_mock() # test with appropriate socks and without exception mocked_receive.side_effect = None mocked_receive.return_value = ('a zmq header', 'a zmq message') main_loop.check_requests(mocked_sockets, socks) self.assertEqual([call('a zmq header', 'a zmq message')], mocked_send.call_args_list) self.assertEqual(0, mocked_disconnect.call_count) mocked_receive.reset_mock() mocked_send.reset_mock() # test disconnection request mocked_receive.return_value = (1, 'an address') main_loop.check_requests(mocked_sockets, socks) self.assertEqual(1, mocked_receive.call_count) self.assertEqual([call('an address')], mocked_disconnect.call_args_list) self.assertEqual(0, mocked_send.call_count)
def on_running(self, event): """ Called when Supervisor is RUNNING. This method start the Supvisors main loop. """ self.logger.info('local supervisord is RUNNING') # replace the default handler for web ui self.info_source.replace_default_handler() # create zmq sockets self.supvisors.zmq = SupervisorZmq(self.supvisors) # keep a reference to the internal events publisher self.publisher = self.supvisors.zmq.internal_publisher # start the main loop # env is needed to create XML-RPC proxy self.main_loop = SupvisorsMainLoop(self.supvisors) self.main_loop.start()
def test_stop(self): """ Test the stopping of the main loop thread. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # try to stop main loop before it is started with self.assertRaises(RuntimeError): main_loop.stop() # stop main loop after it is started main_loop.loop = True with patch.object(main_loop, 'join') as mocked_join: main_loop.stop() self.assertFalse(main_loop.loop) self.assertEqual(1, mocked_join.call_count)
def test_creation(self): """ Test the values set at construction. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) self.assertIsInstance(main_loop, Thread) self.assertIs(self.supvisors, main_loop.supvisors) self.assertFalse(main_loop.stop_event.is_set()) self.assertDictEqual( { 'SUPERVISOR_SERVER_URL': 'http://127.0.0.1:65000', 'SUPERVISOR_USERNAME': '', 'SUPERVISOR_PASSWORD': '' }, main_loop.env) self.assertEqual(1, self.mocked_rpc.call_count) self.assertEqual(call('localhost', main_loop.env), self.mocked_rpc.call_args)
def test_stop(self): """ Test the stopping of the main loop thread. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) with patch.object(main_loop, 'join') as mocked_join: # try to stop main loop before it is started main_loop.stop() self.assertFalse(main_loop.stop_event.is_set()) self.assertEqual(0, mocked_join.call_count) # stop main loop when alive with patch.object(main_loop, 'is_alive', return_value=True): main_loop.stop() self.assertTrue(main_loop.stop_event.is_set()) self.assertEqual(1, mocked_join.call_count)
def test_comm_event(self): """ Test the protocol to send a comm event to the local Supervisor. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # test rpc error with patch.object(main_loop.proxy.supervisor, 'sendRemoteCommEvent', side_effect=Exception): main_loop.send_remote_comm_event('event type', 'event data') # test with a mocked rpc interface with patch.object(main_loop.proxy.supervisor, 'sendRemoteCommEvent') as mocked_supervisor: main_loop.send_remote_comm_event('event type', 'event data') self.assertEqual(1, mocked_supervisor.call_count) self.assertEqual(call('event type', 'event data'), mocked_supervisor.call_args)
def test_shutdown(self): """ Test the protocol to shutdown a remote Supervisor. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # test rpc error self.mocked_rpc.side_effect = Exception main_loop.shutdown('10.0.0.1') self.assertEqual(2, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) # test with a mocked rpc interface rpc_intf = DummyRpcInterface() self.mocked_rpc.side_effect = None self.mocked_rpc.return_value = rpc_intf with patch.object(rpc_intf.supervisor, 'shutdown') as mocked_shutdown: main_loop.shutdown('10.0.0.1') self.assertEqual(3, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) self.assertEqual(1, mocked_shutdown.call_count) self.assertEqual(call(), mocked_shutdown.call_args)
def test_stop_process(self): """ Test the protocol to stop a process handled by a remote Supervisor. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) # test rpc error self.mocked_rpc.side_effect = Exception main_loop.stop_process('10.0.0.1', 'dummy_process') self.assertEqual(2, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) # test with a mocked rpc interface rpc_intf = DummyRpcInterface() self.mocked_rpc.side_effect = None self.mocked_rpc.return_value = rpc_intf with patch.object(rpc_intf.supervisor, 'stopProcess') as mocked_supervisor: main_loop.stop_process('10.0.0.1', 'dummy_process') self.assertEqual(3, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) self.assertEqual(1, mocked_supervisor.call_count) self.assertEqual(call('dummy_process', False), mocked_supervisor.call_args)
def test_check_address(self): """ Test the protocol to get the processes handled by a remote Supervisor. """ from supvisors.mainloop import SupvisorsMainLoop from supvisors.ttypes import AddressStates main_loop = SupvisorsMainLoop(self.supvisors) # patch the main loop send_remote_comm_event # test the check_address behaviour through the calls to internal events with patch.object(main_loop, 'send_remote_comm_event') as mocked_evt: # test rpc error: no event is sent to local Supervisor self.mocked_rpc.side_effect = Exception main_loop.check_address('10.0.0.1') self.assertEqual(2, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) self.assertEqual(0, mocked_evt.call_count) # test with a mocked rpc interface rpc_intf = DummyRpcInterface() self.mocked_rpc.side_effect = None self.mocked_rpc.return_value = rpc_intf self.mocked_rpc.reset_mock() # test with address in isolation with patch.object(rpc_intf.supervisor, 'getAllProcessInfo') as mocked_supervisor: for state in [AddressStates.ISOLATING, AddressStates.ISOLATED]: with patch.object(rpc_intf.supvisors, 'get_address_info', return_value={'statecode': state}): main_loop.check_address('10.0.0.1') self.assertEqual(1, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) self.assertEqual(1, mocked_evt.call_count) self.assertEqual( call('auth', 'address_name:10.0.0.1 authorized:False'), mocked_evt.call_args) self.assertEqual(0, mocked_supervisor.call_count) # reset counters mocked_evt.reset_mock() self.mocked_rpc.reset_mock() # test with address not in isolation with patch.object(rpc_intf.supervisor, 'getAllProcessInfo', return_value=['dummy_list' ]) as mocked_supervisor: for state in [ AddressStates.UNKNOWN, AddressStates.CHECKING, AddressStates.RUNNING, AddressStates.SILENT ]: with patch.object(rpc_intf.supvisors, 'get_address_info', return_value={'statecode': state}): main_loop.check_address('10.0.0.1') self.assertEqual(1, self.mocked_rpc.call_count) self.assertEqual(call('10.0.0.1', main_loop.env), self.mocked_rpc.call_args) self.assertEqual(2, mocked_evt.call_count) self.assertEqual([ call('info', '["10.0.0.1", ["dummy_list"]]'), call('auth', 'address_name:10.0.0.1 authorized:True') ], mocked_evt.call_args_list) self.assertEqual(1, mocked_supervisor.call_count) # reset counters mocked_evt.reset_mock() mocked_supervisor.reset_mock() self.mocked_rpc.reset_mock()
def test_TODO(self): """ Test the values set at construction. """ from supvisors.mainloop import SupvisorsMainLoop main_loop = SupvisorsMainLoop(self.supvisors) self.assertIsNotNone(main_loop)
class SupervisorListener(object): """ This class subscribes directly to the internal Supervisor events. These events are published to all Supvisors instances. Attributes are: - supvisors: a reference to the Supvisors context, - address: the address name where this process is running, - main_loop: the Supvisors' event thread, - publisher: the ZeroMQ socket used to publish Supervisor events to all Supvisors threads. """ def __init__(self, supvisors): """ Initialization of the attributes. """ self.supvisors = supvisors # shortcuts for source code readability supvisors_short_cuts(self, ['fsm', 'info_source', 'logger', 'statistician']) # test if statistics collector can be created for local host try: from supvisors.statscollector import instant_statistics self.collector = instant_statistics except ImportError: self.logger.warn('psutil not installed') self.logger.warn('this Supvisors will not publish statistics') self.collector = None # other attributes self.address = self.supvisors.address_mapper.local_address self.publisher = None self.main_loop = None # subscribe to internal events events.subscribe(events.SupervisorRunningEvent, self.on_running) events.subscribe(events.SupervisorStoppingEvent, self.on_stopping) events.subscribe(events.ProcessStateEvent, self.on_process) events.subscribe(events.Tick5Event, self.on_tick) events.subscribe(events.RemoteCommunicationEvent, self.on_remote_event) def on_running(self, event): """ Called when Supervisor is RUNNING. This method start the Supvisors main loop. """ self.logger.info('local supervisord is RUNNING') # replace the default handler for web ui self.info_source.replace_default_handler() # create zmq sockets self.supvisors.zmq = SupervisorZmq(self.supvisors) # keep a reference to the internal events publisher self.publisher = self.supvisors.zmq.internal_publisher # start the main loop # env is needed to create XML-RPC proxy self.main_loop = SupvisorsMainLoop(self.supvisors) self.main_loop.start() def on_stopping(self, event): """ Called when Supervisor is STOPPING. This method stops the Supvisors main loop. """ self.logger.warn('local supervisord is STOPPING') # force Supervisor to close HTTP servers # this will prevent any pending XML-RPC request to block the main loop self.info_source.close_httpservers() # stop the main loop self.logger.info('request to stop main loop') self.main_loop.stop() self.logger.info('end of main loop') # close zmq sockets self.supvisors.zmq.close() # unsubscribe from events events.clear() # finally, close logger self.logger.close() def on_process(self, event): """ Called when a ProcessEvent is sent by the local Supervisor. The event is published to all Supvisors instances. """ event_name = events.getEventNameByType(event.__class__) self.logger.debug('got Process event from supervisord: {} {}'.format( event_name, event)) # create payload from event payload = { 'name': event.process.config.name, 'group': event.process.group.config.name, 'state': ProcessStates._from_string(event_name.split('_')[-1]), 'now': int(time.time()), 'pid': event.process.pid, 'expected': event.expected } self.logger.debug('payload={}'.format(payload)) self.publisher.send_process_event(payload) def on_tick(self, event): """ Called when a TickEvent is notified. The event is published to all Supvisors instances. Then statistics are published and periodic task is triggered. """ self.logger.debug('got Tick event from supervisord: {}'.format(event)) payload = {'when': event.when} self.publisher.send_tick_event(payload) # get and publish statistics at tick time (optional) if self.collector: status = self.supvisors.context.addresses[self.address] self.publisher.send_statistics( self.collector(status.pid_processes())) # periodic task addresses = self.fsm.on_timer_event() # pushes isolated addresses to main loop self.supvisors.zmq.pusher.send_isolate_addresses(addresses) def on_remote_event(self, event): """ Called when a RemoteCommunicationEvent is notified. This is used to sequence the events received from the Supvisors thread with the other events handled by the local Supervisor. """ self.logger.debug( 'got Remote event from supervisord: {}'.format(event)) if event.type == RemoteCommEvents.SUPVISORS_AUTH: self.authorization(event.data) elif event.type == RemoteCommEvents.SUPVISORS_EVENT: self.unstack_event(event.data) elif event.type == RemoteCommEvents.SUPVISORS_INFO: self.unstack_info(event.data) def unstack_event(self, message): """ Unstack and process one event from the event queue. """ event_type, event_address, event_data = json.loads(message) if event_type == InternalEventHeaders.TICK: self.logger.trace('got tick event from {}: {}'.format( event_address, event_data)) self.fsm.on_tick_event(event_address, event_data) elif event_type == InternalEventHeaders.PROCESS: self.logger.trace('got process event from {}: {}'.format( event_address, event_data)) self.fsm.on_process_event(event_address, event_data) elif event_type == InternalEventHeaders.STATISTICS: # this Supvisors could handle statistics # even if psutil is not installed self.logger.trace('got statistics event from {}: {}'.format( event_address, event_data)) self.statistician.push_statistics(event_address, event_data) def unstack_info(self, message): """ Unstack the process info received. """ # unstack the queue for process info address_name, info = json.loads(message) self.logger.trace( 'got process info event from {}'.format(address_name)) self.fsm.on_process_info(address_name, info) def authorization(self, data): """ Extract authorization and address from data and process event. """ self.logger.trace('got authorization event: {}'.format(data)) # split the line received address_name, authorized = tuple(x.split(':')[1] for x in data.split()) self.fsm.on_authorization(address_name, boolean(authorized)) def force_process_fatal(self, namespec): """ Publishes a fake process event showing a FATAL state for the process. """ self.force_process_state(namespec, ProcessStates.FATAL) def force_process_unknown(self, namespec): """ Publishes a fake process event showing an UNKNOWN state for the process. """ self.force_process_state(namespec, ProcessStates.UNKNOWN) def force_process_state(self, namespec, state): """ Publishes a fake process event showing a state for the process. """ application_name, process_name = split_namespec(namespec) # create payload from event payload = { 'processname': process_name, 'groupname': application_name, 'state': state, 'now': int(time.time()), 'pid': 0, 'expected': False } self.logger.debug('payload={}'.format(payload)) self.publisher.send_process_event(payload)
class SupervisorListener(object): """ This class subscribes directly to the internal Supervisor events. These events are published to all Supvisors instances. Attributes are: - supvisors: a reference to the Supvisors context, - address: the address name where this process is running, - main_loop: the Supvisors' event thread, - publisher: the ZeroMQ socket used to publish Supervisor events to all Supvisors threads. """ def __init__(self, supvisors): """ Initialization of the attributes. """ self.supvisors = supvisors # shortcuts for source code readability supvisors_short_cuts(self, ['fsm', 'info_source', 'logger', 'statistician']) # test if statistics collector can be created for local host try: from supvisors.statscollector import instant_statistics self.collector = instant_statistics except ImportError: self.logger.warn('psutil not installed') self.logger.warn('this Supvisors will not publish statistics') self.collector = None # other attributes self.address = self.supvisors.address_mapper.local_address self.publisher = None self.main_loop = None # subscribe to internal events events.subscribe(events.SupervisorRunningEvent, self.on_running) events.subscribe(events.SupervisorStoppingEvent, self.on_stopping) events.subscribe(events.ProcessStateEvent, self.on_process) events.subscribe(events.Tick5Event, self.on_tick) events.subscribe(events.RemoteCommunicationEvent, self.on_remote_event) def on_running(self, event): """ Called when Supervisor is RUNNING. This method start the Supvisors main loop. """ self.logger.info('local supervisord is RUNNING') # replace the default handler for web ui self.info_source.replace_default_handler() # create zmq sockets self.supvisors.zmq = SupervisorZmq(self.supvisors) # keep a reference to the internal events publisher self.publisher = self.supvisors.zmq.internal_publisher # start the main loop # env is needed to create XML-RPC proxy self.main_loop = SupvisorsMainLoop(self.supvisors) self.main_loop.start() def on_stopping(self, event): """ Called when Supervisor is STOPPING. This method stops the Supvisors main loop. """ self.logger.warn('local supervisord is STOPPING') # force Supervisor to close HTTP servers # this will prevent any pending XML-RPC request to block the main loop self.info_source.close_httpservers() # stop the main loop self.logger.info('request to stop main loop') self.main_loop.stop() self.logger.info('end of main loop') # close zmq sockets self.supvisors.zmq.close() # unsubscribe from events events.clear() # finally, close logger self.logger.close() def on_process(self, event): """ Called when a ProcessEvent is sent by the local Supervisor. The event is published to all Supvisors instances. """ event_name = events.getEventNameByType(event.__class__) self.logger.debug('got Process event from supervisord: {} {}'.format( event_name, event)) # create payload from event payload = {'name': event.process.config.name, 'group': event.process.group.config.name, 'state': ProcessStates._from_string(event_name.split('_')[-1]), 'now': int(time.time()), 'pid': event.process.pid, 'expected': event.expected} self.logger.debug('payload={}'.format(payload)) self.publisher.send_process_event(payload) def on_tick(self, event): """ Called when a TickEvent is notified. The event is published to all Supvisors instances. Then statistics are published and periodic task is triggered. """ self.logger.debug('got Tick event from supervisord: {}'.format(event)) payload = {'when': event.when} self.publisher.send_tick_event(payload) # get and publish statistics at tick time (optional) if self.collector: status = self.supvisors.context.addresses[self.address] self.publisher.send_statistics( self.collector(status.pid_processes())) # periodic task addresses = self.fsm.on_timer_event() # pushes isolated addresses to main loop self.supvisors.zmq.pusher.send_isolate_addresses(addresses) def on_remote_event(self, event): """ Called when a RemoteCommunicationEvent is notified. This is used to sequence the events received from the Supvisors thread with the other events handled by the local Supervisor. """ self.logger.debug('got Remote event from supervisord: {}'.format(event)) if event.type == RemoteCommEvents.SUPVISORS_AUTH: self.authorization(event.data) elif event.type == RemoteCommEvents.SUPVISORS_EVENT: self.unstack_event(event.data) elif event.type == RemoteCommEvents.SUPVISORS_INFO: self.unstack_info(event.data) def unstack_event(self, message): """ Unstack and process one event from the event queue. """ event_type, event_address, event_data = json.loads(message) if event_type == InternalEventHeaders.TICK: self.logger.trace('got tick event from {}: {}'.format( event_address, event_data)) self.fsm.on_tick_event(event_address, event_data) elif event_type == InternalEventHeaders.PROCESS: self.logger.trace('got process event from {}: {}'.format( event_address, event_data)) self.fsm.on_process_event(event_address, event_data) elif event_type == InternalEventHeaders.STATISTICS: # this Supvisors could handle statistics # even if psutil is not installed self.logger.trace('got statistics event from {}: {}'.format( event_address, event_data)) self.statistician.push_statistics(event_address, event_data) def unstack_info(self, message): """ Unstack the process info received. """ # unstack the queue for process info address_name, info = json.loads(message) self.logger.trace('got process info event from {}'.format( address_name)) self.fsm.on_process_info(address_name, info) def authorization(self, data): """ Extract authorization and address from data and process event. """ self.logger.trace('got authorization event: {}'.format(data)) # split the line received address_name, authorized = tuple(x.split(':')[1] for x in data.split()) self.fsm.on_authorization(address_name, boolean(authorized)) def force_process_fatal(self, namespec): """ Publishes a fake process event showing a FATAL state for the process. """ self.force_process_state(namespec, ProcessStates.FATAL) def force_process_unknown(self, namespec): """ Publishes a fake process event showing an UNKNOWN state for the process. """ self.force_process_state(namespec, ProcessStates.UNKNOWN) def force_process_state(self, namespec, state): """ Publishes a fake process event showing a state for the process. """ application_name, process_name = split_namespec(namespec) # create payload from event payload = {'processname': process_name, 'groupname': application_name, 'state': state, 'now': int(time.time()), 'pid': 0, 'expected': False} self.logger.debug('payload={}'.format(payload)) self.publisher.send_process_event(payload)