def test_removeProcessFromGroup_raises_still_running_when_process_has_pid(
            self):
        pconfig = DummyPConfig(None, "foo", "/bin/foo")
        process = DummyProcess(pconfig)
        process.pid = 42

        gconfig = DummyPGroupConfig(None, pconfigs=[pconfig])
        pgroup = DummyProcessGroup(gconfig)
        pgroup.processes = {"process_with_pid": process}

        supervisord = DummySupervisor(process_groups={"group_name": pgroup})
        interface = self.makeOne(supervisord)

        self.assertRPCError(
            SupervisorFaults.STILL_RUNNING,
            interface.removeProcessFromGroup,
            "group_name",
            "process_with_pid",
        )
Example #2
0
    def test_remove_process_group_event(self):
        from supervisor import events
        L = []
        def callback(event):
            L.append(1)
        events.subscribe(events.ProcessGroupRemovedEvent, callback)
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(options,'foo', pconfigs=[pconfig])
        options.process_group_configs = [gconfig]
        supervisord = self._makeOne(options)

        supervisord.add_process_group(gconfig)
        supervisord.process_groups['foo'].stopped_processes = [DummyProcess(None)]
        supervisord.remove_process_group('foo')
        options.test = True
        supervisord.runforever()

        self.assertEqual(L, [1])
Example #3
0
 def test_handle_request(self):
     with tempfile.NamedTemporaryFile() as f:
         t = f.name
         options = DummyOptions()
         pconfig = DummyPConfig(options, 'foo', 'foo', stdout_logfile=t)
         supervisord = PopulatedDummySupervisor(options, 'foo', pconfig)
         handler = self._makeOne(supervisord)
         request = DummyRequest('/logtail/foo', None, None, None)
         handler.handle_request(request)
         self.assertEqual(request._error, None)
         from supervisor.medusa import http_date
         self.assertEqual(
             request.headers['Last-Modified'],
             http_date.build_http_date(os.stat(t)[stat.ST_MTIME]))
         self.assertEqual(request.headers['Content-Type'],
                          'text/plain;charset=utf-8')
         self.assertEqual(request.headers['X-Accel-Buffering'], 'no')
         self.assertEqual(len(request.producers), 1)
         self.assertEqual(request._done, True)
Example #4
0
    def test_addProgramToGroup_adds_new_process_config_to_group(self):
        pconfig = DummyPConfig(None, 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(None, pconfigs=[pconfig])
        pgroup = DummyProcessGroup(gconfig)
        pgroup.processes = {}

        supervisord = DummySupervisor(process_groups={'group_name': pgroup})
        supervisord.options = supervisor.options.ServerOptions()

        interface = self.makeOne(supervisord)

        poptions = {'command': '/usr/bin/find /'}
        self.assertTrue(
            interface.addProgramToGroup('group_name', 'new_process', poptions))
        self.assertEqual('addProgramToGroup', interface.update_text)

        config = pgroup.config.process_configs[1]
        self.assertEqual('new_process', config.name)
        self.assertTrue(isinstance(config, supervisor.options.ProcessConfig))
Example #5
0
    def test_stdout_capturemode_single_buffer(self):
        # mike reported that comm events that took place within a single
        # output buffer were broken 8/20/2007
        from supervisor.events import ProcessCommunicationEvent
        from supervisor.events import subscribe
        events = []
        def doit(event):
            events.append(event)
        subscribe(ProcessCommunicationEvent, doit)
        BEGIN_TOKEN = ProcessCommunicationEvent.BEGIN_TOKEN
        END_TOKEN = ProcessCommunicationEvent.END_TOKEN
        data = BEGIN_TOKEN + 'hello' + END_TOKEN
        options = DummyOptions()
        from supervisor.loggers import getLogger
        options.getLogger = getLogger # actually use real logger
        logfile = '/tmp/log'
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stdout_logfile=logfile,
                              stdout_capture_maxbytes=1000)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process)

        try:
            dispatcher.output_buffer = data
            dispatcher.record_output()
            self.assertEqual(open(logfile, 'r').read(), '')
            self.assertEqual(dispatcher.output_buffer, '')
            self.assertEqual(len(events), 1)

            event = events[0]
            from supervisor.events import ProcessCommunicationStdoutEvent
            self.assertEqual(event.__class__, ProcessCommunicationStdoutEvent)
            self.assertEqual(event.process, process)
            self.assertEqual(event.channel, 'stdout')
            self.assertEqual(event.data, 'hello')

        finally:
            try:
                dispatcher.capturelog.close()
                dispatcher.childlog.close()
                os.remove(logfile)
            except (OSError, IOError):
                pass
Example #6
0
    def test_record_output_emits_stderr_event_when_enabled(self):
        options = DummyOptions()
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stderr_events_enabled=True)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process, 'stderr')
        dispatcher.output_buffer = 'hello from stderr'

        L = []
        def doit(event):
            L.append(event)
        from supervisor import events
        events.subscribe(events.EventTypes.PROCESS_LOG_STDERR, doit)
        dispatcher.record_output()

        self.assertEqual(len(L), 1)
        event = L[0]
        self.assertEqual(event.process, process)
        self.assertEqual(event.data, 'hello from stderr')
Example #7
0
 def test_runforever_select_dispatchers(self):
     options = DummyOptions()
     supervisord = self._makeOne(options)
     pconfig = DummyPConfig(options, 'foo', '/bin/foo',)
     process = DummyProcess(pconfig)
     gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
     pgroup = DummyProcessGroup(gconfig)
     readable = DummyDispatcher(readable=True)
     writable = DummyDispatcher(writable=True)
     error = DummyDispatcher(writable=True, error=OSError)
     pgroup.dispatchers = {6:readable, 7:writable, 8:error}
     supervisord.process_groups = {'foo': pgroup}
     options.select_result = [6], [7, 8], []
     options.test = True
     supervisord.runforever()
     self.assertEqual(pgroup.transitioned, True)
     self.assertEqual(readable.read_event_handled, True)
     self.assertEqual(writable.write_event_handled, True)
     self.assertEqual(error.error_handled, True)
Example #8
0
    def test_remove_process_group(self):
        from supervisor.states import ProcessStates
        options = DummyOptions()
        pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
        gconfig = DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])
        supervisord = self._makeOne(options)

        self.assertRaises(KeyError, supervisord.remove_process_group, 'asdf')

        supervisord.add_process_group(gconfig)
        result = supervisord.remove_process_group('foo')
        self.assertEqual(supervisord.process_groups, {})
        self.assertTrue(result)

        supervisord.add_process_group(gconfig)
        supervisord.process_groups['foo'].unstopped_processes = [DummyProcess(None)]
        result = supervisord.remove_process_group('foo')
        self.assertEqual(list(supervisord.process_groups.keys()), ['foo'])
        self.assertTrue(not result)
    def test_addProgramToGroup_adds_new_process_to_supervisord_processes(self):
        pconfig = DummyPConfig(None, "foo", "/bin/foo")
        gconfig = DummyPGroupConfig(None, pconfigs=[pconfig])
        pgroup = DummyProcessGroup(gconfig)
        pgroup.processes = {}

        supervisord = DummySupervisor(process_groups={"group_name": pgroup})
        supervisord.options = supervisor.options.ServerOptions()
        interface = self.makeOne(supervisord)
        poptions = {"command": "/usr/bin/find /"}

        self.assertTrue(
            interface.addProgramToGroup("new_process", poptions, "group_name"))
        self.assertEqual("addProgramToGroup", interface.update_text)

        process = pgroup.processes["new_process"]

        self.assertTrue(isinstance(process, supervisor.process.Subprocess))
        self.assertEqual("/usr/bin/find /", process.config.command)
Example #10
0
    def test_record_output_does_not_emit_stdout_event_when_disabled(self):
        options = DummyOptions()
        config = DummyPConfig(options,
                              'process1',
                              '/bin/process1',
                              stdout_events_enabled=False)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process, 'stdout')
        dispatcher.output_buffer = 'hello from stdout'

        L = []

        def doit(event):
            L.append(event)

        from supervisor import events
        events.subscribe(events.EventTypes.PROCESS_LOG_STDOUT, doit)
        dispatcher.record_output()

        self.assertEqual(len(L), 0)
Example #11
0
 def test_handle_listener_state_change_busy_to_acknowledged_rejected(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.BUSY
     class Dummy:
         pass
     process.group = Dummy()
     process.group.config = Dummy()
     from supervisor.dispatchers import default_handler
     process.group.config.result_handler = default_handler
     dispatcher.state_buffer = 'RESULT 4\nFAILabc'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, 'abc')
     self.assertEqual(options.logger.data[0],
                      'process1: BUSY -> ACKNOWLEDGED (rejected)')
     self.assertEqual(process.listener_state,
                      EventListenerStates.ACKNOWLEDGED)
Example #12
0
    def test_strip_ansi(self):
        options = DummyOptions()
        options.strip_ansi = True
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stdout_logfile=os.path.join(tempfile.gettempdir(), 'foo.txt'))
        process = DummyProcess(config)
        dispatcher = self._makeOne(process)
        ansi = '\x1b[34mHello world... this is longer than a token!\x1b[0m'
        noansi = 'Hello world... this is longer than a token!'

        dispatcher.output_buffer = ansi
        dispatcher.record_output()
        self.assertEqual(len(dispatcher.childlog.data), 1)
        self.assertEqual(dispatcher.childlog.data[0], noansi)

        options.strip_ansi = False

        dispatcher.output_buffer = ansi
        dispatcher.record_output()
        self.assertEqual(len(dispatcher.childlog.data), 2)
        self.assertEqual(dispatcher.childlog.data[1], ansi)
Example #13
0
 def test_toggle_capturemode_sends_event(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1',
                           stdout_logfile='/tmp/foo',
                           stdout_capture_maxbytes=500)
     process = DummyProcess(config)
     process.pid = 4000
     dispatcher = self._makeOne(process)
     dispatcher.capturemode = True
     dispatcher.capturelog.data = ['hallooo']
     L = []
     def doit(event):
         L.append(event)
     from supervisor import events
     events.subscribe(events.EventTypes.PROCESS_COMMUNICATION, doit)
     dispatcher.toggle_capturemode()
     self.assertEqual(len(L), 1)
     event = L[0]
     self.assertEqual(event.process, process)
     self.assertEqual(event.pid, 4000)
     self.assertEqual(event.data, 'hallooo')
Example #14
0
    def test_strip_ansi(self):
        options = DummyOptions()
        options.strip_ansi = True
        config = DummyPConfig(options, 'process1', '/bin/process1',
                              stdout_logfile='/tmp/foo')
        process = DummyProcess(config)
        dispatcher = self._makeOne(process)
        ansi = '\x1b[34mHello world... this is longer than a token!\x1b[0m'
        noansi = 'Hello world... this is longer than a token!'

        options.readfd_result = ansi
        dispatcher.handle_read_event()
        self.assertEqual(len(dispatcher.childlog.data), 1)
        self.assertEqual(dispatcher.childlog.data[0], noansi)

        options.strip_ansi = False

        options.readfd_result = ansi
        dispatcher.handle_read_event()
        self.assertEqual(len(dispatcher.childlog.data), 2)
        self.assertEqual(dispatcher.childlog.data[1], ansi)
Example #15
0
 def test_process_state_exited_event_unexpected(self):
     from supervisor import events
     from supervisor.states import ProcessStates
     options = DummyOptions()
     pconfig1 = DummyPConfig(options, 'process1', 'process1','/bin/process1')
     process1 = DummyProcess(pconfig1)
     class DummyGroup:
         config = pconfig1
     process1.group = DummyGroup
     process1.pid = 1
     event = events.ProcessStateExitedEvent(process1,
                                            ProcessStates.STARTING,
                                            expected=False)
     headers, payload = self._deserialize(str(event))
     self.assertEqual(len(headers), 5)
     self.assertEqual(headers['processname'], 'process1')
     self.assertEqual(headers['groupname'], 'process1')
     self.assertEqual(headers['pid'], '1')
     self.assertEqual(headers['from_state'], 'STARTING')
     self.assertEqual(headers['expected'], '0')
     self.assertEqual(payload, '')
Example #16
0
 def test_process_state_events_without_extra_values(self):
     from supervisor.states import ProcessStates
     from supervisor import events
     for klass in (
         events.ProcessStateFatalEvent,
         events.ProcessStateUnknownEvent,
         ):
         options = DummyOptions()
         pconfig1 = DummyPConfig(options, 'process1', 'process1',
                                 '/bin/process1')
         class DummyGroup:
             config = pconfig1
         process1 = DummyProcess(pconfig1)
         process1.group = DummyGroup
         event = klass(process1, ProcessStates.STARTING)
         headers, payload = self._deserialize(str(event))
         self.assertEqual(len(headers), 3)
         self.assertEqual(headers['processname'], 'process1')
         self.assertEqual(headers['groupname'], 'process1')
         self.assertEqual(headers['from_state'], 'STARTING')
         self.assertEqual(payload, '')
    def test_exit(self):
        options = DummyOptions()
        supervisord = self._makeOne(options)
        pconfig = DummyPConfig(
            options,
            'foo',
            '/bin/foo',
        )
        gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
        pgroup = DummyProcessGroup(gconfig)
        L = []

        def callback():
            L.append(1)

        supervisord.process_groups = {'foo': pgroup}
        supervisord.options.mood = SupervisorStates.RESTARTING
        supervisord.options.test = True
        from supervisor.medusa import asyncore_25 as asyncore
        self.assertRaises(asyncore.ExitNow, supervisord.runforever)
        self.assertEqual(pgroup.all_stopped, True)
Example #18
0
 def test_record_output_capturemode_string_longer_than_token(self):
     # stdout/stderr goes to the process log and the main log,
     # in capturemode, the length of the data needs to be longer
     # than the capture token to make it out.
     options = DummyOptions()
     from supervisor import loggers
     options.loglevel = loggers.LevelsByName.TRAC
     config = DummyPConfig(options,
                           'process1',
                           '/bin/process1',
                           stdout_logfile='/tmp/foo',
                           stdout_capture_maxbytes=100)
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     dispatcher.output_buffer = 'stdout string longer than a token'
     dispatcher.record_output()
     self.assertEqual(dispatcher.childlog.data,
                      ['stdout string longer than a token'])
     self.assertEqual(
         options.logger.data[0],
         "'process1' stdout output:\nstdout string longer than a token")
Example #19
0
 def test_handle_listener_state_busy_gobbles(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.BUSY
     class Dummy:
         pass
     process.group = Dummy()
     process.group.config = Dummy()
     from supervisor.dispatchers import default_handler
     process.group.config.result_handler = default_handler
     dispatcher.state_buffer = 'RESULT 2\nOKbogus data\n'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, '')
     self.assertEqual(options.logger.data[0],
                      'process1: BUSY -> ACKNOWLEDGED (processed)')
     self.assertEqual(options.logger.data[1],
                      'process1: ACKNOWLEDGED -> UNKNOWN')
     self.assertEqual(process.listener_state,
                      EventListenerStates.UNKNOWN)
    def test_exit_delayed(self):
        options = DummyOptions()
        supervisord = self._makeOne(options)
        pconfig = DummyPConfig(
            options,
            'foo',
            '/bin/foo',
        )
        process = DummyProcess(pconfig)
        gconfig = DummyPGroupConfig(options, pconfigs=[pconfig])
        pgroup = DummyProcessGroup(gconfig)
        pgroup.unstopped_processes = [process]
        L = []

        def callback():
            L.append(1)

        supervisord.process_groups = {'foo': pgroup}
        supervisord.options.mood = SupervisorStates.RESTARTING
        supervisord.options.test = True
        supervisord.runforever()
        self.assertNotEqual(supervisord.lastshutdownreport, 0)
 def test_main_notfirst(self):
     options = DummyOptions()
     pconfig = DummyPConfig(options, 'foo', '/bin/foo', '/tmp')
     gconfigs = [DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])]
     options.process_group_configs = gconfigs
     options.test = True
     options.first = False
     supervisord = self._makeOne(options)
     supervisord.main()
     self.assertEqual(options.fds_cleaned_up, True)
     self.assertFalse(hasattr(options, 'rlimits_set'))
     self.assertEqual(options.parse_criticals, ['setuid_called'])
     self.assertEqual(options.parse_warnings, [])
     self.assertEqual(options.parse_infos, [])
     self.assertEqual(options.autochildlogdir_cleared, True)
     self.assertEqual(len(supervisord.process_groups), 1)
     self.assertEqual(supervisord.process_groups['foo'].config.options,
                      options)
     self.assertEqual(options.httpservers_opened, True)
     self.assertEqual(options.signals_set, True)
     self.assertEqual(options.daemonized, False)
     self.assertEqual(options.pidfile_written, True)
     self.assertEqual(options.cleaned_up, True)
Example #22
0
 def test_process_state_events_with_pid(self):
     from supervisor.states import ProcessStates
     from supervisor import events
     for klass in (
         events.ProcessStateRunningEvent,
         events.ProcessStateStoppedEvent,
         events.ProcessStateStoppingEvent,
         ):
         options = DummyOptions()
         pconfig1 = DummyPConfig(options, 'process1', 'process1',
                                 '/bin/process1')
         class DummyGroup:
             config = pconfig1
         process1 = DummyProcess(pconfig1)
         process1.group = DummyGroup
         process1.pid = 1
         event = klass(process1, ProcessStates.STARTING)
         headers, payload = self._deserialize(str(event))
         self.assertEqual(len(headers), 4)
         self.assertEqual(headers['processname'], 'process1')
         self.assertEqual(headers['groupname'], 'process1')
         self.assertEqual(headers['from_state'], 'STARTING')
         self.assertEqual(headers['pid'], '1')
         self.assertEqual(payload, '')
Example #23
0
 def test_handle_listener_state_change_busy_to_unknown(self):
     from supervisor.events import EventRejectedEvent
     from supervisor.events import subscribe
     events = []
     def doit(event):
         events.append(event)
     subscribe(EventRejectedEvent, doit)
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     from supervisor.dispatchers import EventListenerStates
     dispatcher = self._makeOne(process)
     process.listener_state = EventListenerStates.BUSY
     current_event = DummyEvent()
     process.event = current_event
     dispatcher.state_buffer = 'bogus data\n'
     self.assertEqual(dispatcher.handle_listener_state_change(), None)
     self.assertEqual(dispatcher.state_buffer, '')
     self.assertEqual(options.logger.data[0],
             'process1: BUSY -> UNKNOWN (bad result line \'bogus data\')')
     self.assertEqual(process.listener_state,
                      EventListenerStates.UNKNOWN)
     self.assertEqual(events[0].process, process)
     self.assertEqual(events[0].event, current_event)
Example #24
0
 def test_main_first(self):
     options = DummyOptions()
     pconfig = DummyPConfig(options, 'foo', 'foo', '/bin/foo')
     gconfigs = [DummyPGroupConfig(options, 'foo', pconfigs=[pconfig])]
     options.process_group_configs = gconfigs
     options.test = True
     options.first = True
     supervisord = self._makeOne(options)
     supervisord.main()
     self.assertEqual(options.environment_processed, True)
     self.assertEqual(options.fds_cleaned_up, False)
     self.assertEqual(options.rlimits_set, True)
     self.assertEqual(options.make_logger_messages,
                      (['setuid_called'], [], ['rlimits_set']))
     self.assertEqual(options.autochildlogdir_cleared, True)
     self.assertEqual(len(supervisord.process_groups), 1)
     self.assertEqual(supervisord.process_groups['foo'].config.options,
                      options)
     self.assertEqual(options.environment_processed, True)
     self.assertEqual(options.httpservers_opened, True)
     self.assertEqual(options.signals_set, True)
     self.assertEqual(options.daemonized, True)
     self.assertEqual(options.pidfile_written, True)
     self.assertEqual(options.cleaned_up, True)
Example #25
0
 def test_handle_write_event(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     self.assertRaises(NotImplementedError, dispatcher.handle_write_event)
Example #26
0
 def test_writable(self):
     options = DummyOptions()
     config = DummyPConfig(options, 'process1', '/bin/process1')
     process = DummyProcess(config)
     dispatcher = self._makeOne(process)
     self.assertEqual(dispatcher.writable(), False)
Example #27
0
    def test_stdout_capturemode_multiple_buffers(self):
        from supervisor.events import ProcessCommunicationEvent
        from supervisor.events import subscribe
        events = []

        def doit(event):
            events.append(event)

        subscribe(ProcessCommunicationEvent, doit)
        import string
        letters = string.letters
        digits = string.digits * 4
        BEGIN_TOKEN = ProcessCommunicationEvent.BEGIN_TOKEN
        END_TOKEN = ProcessCommunicationEvent.END_TOKEN
        data = (letters + BEGIN_TOKEN + digits + END_TOKEN + letters)

        # boundaries that split tokens
        broken = data.split(':')
        first = broken[0] + ':'
        second = broken[1] + ':'
        third = broken[2]

        options = DummyOptions()
        from supervisor.loggers import getLogger
        options.getLogger = getLogger  # actually use real logger
        logfile = '/tmp/log'
        config = DummyPConfig(options,
                              'process1',
                              '/bin/process1',
                              stdout_logfile=logfile,
                              stdout_capture_maxbytes=10000)
        process = DummyProcess(config)
        dispatcher = self._makeOne(process)
        try:
            dispatcher.output_buffer = first
            dispatcher.record_output()
            [x.flush() for x in dispatcher.childlog.handlers]
            self.assertEqual(open(logfile, 'r').read(), letters)
            self.assertEqual(dispatcher.output_buffer, first[len(letters):])
            self.assertEqual(len(events), 0)

            dispatcher.output_buffer += second
            dispatcher.record_output()
            self.assertEqual(len(events), 0)
            [x.flush() for x in dispatcher.childlog.handlers]
            self.assertEqual(open(logfile, 'r').read(), letters)
            self.assertEqual(dispatcher.output_buffer, first[len(letters):])
            self.assertEqual(len(events), 0)

            dispatcher.output_buffer += third
            dispatcher.record_output()
            [x.flush() for x in dispatcher.childlog.handlers]
            self.assertEqual(open(logfile, 'r').read(), letters * 2)
            self.assertEqual(len(events), 1)
            event = events[0]
            from supervisor.events import ProcessCommunicationStdoutEvent
            self.assertEqual(event.__class__, ProcessCommunicationStdoutEvent)
            self.assertEqual(event.process, process)
            self.assertEqual(event.channel, 'stdout')
            self.assertEqual(event.data, digits)

        finally:
            try:
                os.remove(logfile)
            except (OSError, IOError):
                pass