示例#1
0
 def test_namespec(self):
     """ Test of the process namspec. """
     from supvisors.process import ProcessStatus
     # test namespec when group and name are different
     info = process_info_by_name('segv')
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     self.assertEqual('crash:segv', process.namespec())
     # test namespec when group and name are identical
     info = process_info_by_name('firefox')
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     self.assertEqual('firefox', process.namespec())
示例#2
0
 def test_update_sequences(self):
     """ Test the sequencing of the deployment method. """
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     application = ApplicationStatus('ApplicationTest', self.supvisors.logger)
     # add processes to the application
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'], self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         # set random sequence to process
         process.rules.start_sequence = random.randint(0, 2)
         process.rules.stop_sequence = random.randint(0, 2)
         application.add_process(process)
     # call the sequencer
     application.update_sequences()
     # check the sequencing of the starting
     sequences = sorted({process.rules.start_sequence for process in application.processes.values()})
     # as key is an integer, the sequence dictionary should be sorted but pypy doesn't...
     for sequence, processes in sorted(application.start_sequence.items()):
         self.assertEqual(sequence, sequences.pop(0))
         self.assertListEqual(sorted(processes, key=lambda x: x.process_name),
             sorted([proc for proc in application.processes.values() if sequence == proc.rules.start_sequence], key=lambda x: x.process_name))
     # check the sequencing of the stopping
     sequences = sorted({process.rules.stop_sequence for process in application.processes.values()})
     # as key is an integer, the sequence dictionary should be sorted but pypy doesn't...
     for sequence, processes in sorted(application.stop_sequence.items()):
         self.assertEqual(sequence, sequences.pop(0))
         self.assertListEqual(sorted(processes, key=lambda x: x.process_name),
             sorted([proc for proc in application.processes.values() if sequence == proc.rules.stop_sequence], key=lambda x: x.process_name))
示例#3
0
 def test_update_times(self):
     """ Test the update of the time entries for a process info belonging to a ProcessStatus. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # add 2 process infos into a process status
     info = any_process_info_by_state(ProcessStates.STOPPING)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     process.add_info('10.0.0.2',
                      any_process_info_by_state(ProcessStates.STOPPED))
     # get their time values
     now_1 = process.infos['10.0.0.1']['now']
     uptime_1 = process.infos['10.0.0.1']['uptime']
     now_2 = process.infos['10.0.0.2']['now']
     # update times on address 2
     process.update_times('10.0.0.2', now_2 + 10)
     # check that nothing changed for address 1
     self.assertEqual(now_1, process.infos['10.0.0.1']['now'])
     self.assertEqual(uptime_1, process.infos['10.0.0.1']['uptime'])
     # check that times changed for address 2 (uptime excepted)
     self.assertEqual(now_2 + 10, process.infos['10.0.0.2']['now'])
     self.assertEqual(0, process.infos['10.0.0.2']['uptime'])
     # update times on address 1
     process.update_times('10.0.0.1', now_1 + 20)
     # check that times changed for address 1 (including uptime)
     self.assertEqual(now_1 + 20, process.infos['10.0.0.1']['now'])
     self.assertEqual(uptime_1 + 20, process.infos['10.0.0.1']['uptime'])
     # check that nothing changed for address 2
     self.assertEqual(now_2 + 10, process.infos['10.0.0.2']['now'])
     self.assertEqual(0, process.infos['10.0.0.2']['uptime'])
示例#4
0
 def test_evaluate_conflict(self):
     """ Test the determination of a synthetic state in case of conflict. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # when there is only one STOPPED process info, there is no conflict
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.evaluate_conflict())
     self.assertEqual(ProcessStates.STOPPED, process.state)
     # the addition of one RUNNING process info does not raise any conflict
     process.infos['10.0.0.2'] = any_process_info_by_state(ProcessStates.RUNNING)
     process.addresses = {'10.0.0.2'}
     self.assertFalse(process.evaluate_conflict())
     # the addition of one STARTING process raises a conflict
     process.infos['10.0.0.3'] = any_process_info_by_state(ProcessStates.STARTING)
     process.addresses.add('10.0.0.3')
     self.assertTrue(process.evaluate_conflict())
     self.assertEqual(ProcessStates.RUNNING, process.state)
     # replace the RUNNING process info with a BACKOFF process info
     process.infos['10.0.0.2'] = any_process_info_by_state(ProcessStates.BACKOFF)
     self.assertTrue(process.evaluate_conflict())
     self.assertEqual(ProcessStates.BACKOFF, process.state)
     # replace the BACKOFF process info with a STARTING process info
     process.infos['10.0.0.2'] = any_process_info_by_state(ProcessStates.STARTING)
     self.assertTrue(process.evaluate_conflict())
     self.assertEqual(ProcessStates.STARTING, process.state)
     # replace the STARTING process info with an EXITED process info
     process.infos['10.0.0.2'] = any_process_info_by_state(ProcessStates.EXITED)
     process.addresses.remove('10.0.0.2')
     self.assertFalse(process.evaluate_conflict())
     self.assertEqual(ProcessStates.STARTING, process.state)
示例#5
0
 def test_times(self):
     """ Test the update_times method. """
     from supervisor.states import ProcessStates
     from supvisors.address import AddressStatus
     from supvisors.process import ProcessStatus
     status = AddressStatus('10.0.0.1', self.supvisors.logger)
     # add processes
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'], self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         status.add_process(process)
     # get current process times
     ref_data = {process.namespec(): (process.state, info['now'], info['local_time'], info.get('uptime', None))
         for process in status.processes.values() for info in [process.infos['10.0.0.1']]}
     # update times and check
     now = time.time()
     status.update_times(now + 10, now)
     self.assertEqual(now + 10, status.remote_time)
     self.assertEqual(now, status.local_time)
     # test process times: only RUNNING has an uptime
     new_data = {process.namespec(): (process.state, info['now'], info['local_time'], info.get('uptime', None))
         for process in status.processes.values() for info in [process.infos['10.0.0.1']]}
     for namespec, new_info in new_data.items():
         ref_info = ref_data[namespec]
         self.assertEqual(new_info[0], ref_info[0])
         self.assertGreater(new_info[1], ref_info[1])
         self.assertGreater(new_info[2], ref_info[2])
         if new_info[0] in [ProcessStates.RUNNING, ProcessStates.STOPPING]:
             self.assertGreater(new_info[3], ref_info[3])
         else:
             self.assertEqual(new_info[3], ref_info[3])
示例#6
0
 def test_invalidate_address(self):
     """ Test the invalidation of addresses. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # create conflict directly with 3 process info
     info = any_process_info_by_state(ProcessStates.BACKOFF)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     process.add_info('10.0.0.2',
                      any_process_info_by_state(ProcessStates.RUNNING))
     process.add_info('10.0.0.3',
                      any_process_info_by_state(ProcessStates.STARTING))
     # check the conflict
     self.assertTrue(process.conflicting())
     self.assertEqual(ProcessStates.RUNNING, process.state)
     # invalidate RUNNING one
     process.invalidate_address('10.0.0.2', False)
     # check state became UNKNOWN on invalidated address
     self.assertEqual(ProcessStates.UNKNOWN,
                      process.infos['10.0.0.2']['state'])
     # check the conflict
     self.assertTrue(process.conflicting())
     # check new synthetic state
     self.assertEqual(ProcessStates.BACKOFF, process.state)
     # invalidate BACKOFF one
     process.invalidate_address('10.0.0.1', False)
     # check state became UNKNOWN on invalidated address
     self.assertEqual(ProcessStates.UNKNOWN,
                      process.infos['10.0.0.1']['state'])
     # check 1 address: no conflict
     self.assertFalse(process.conflicting())
     # check synthetic state (running process)
     self.assertEqual(ProcessStates.STARTING, process.state)
     # invalidate STARTING one
     process.invalidate_address('10.0.0.3', True)
     # check state became UNKNOWN on invalidated address
     self.assertEqual(ProcessStates.UNKNOWN,
                      process.infos['10.0.0.3']['state'])
     # check 0 address: no conflict
     self.assertFalse(process.conflicting())
     # check that synthetic state became FATAL
     self.assertEqual(ProcessStates.FATAL, process.state)
     # check that failure_handler is notified
     self.assertEqual(
         [call(process)],
         self.supvisors.failure_handler.add_default_job.call_args_list)
     # add one STOPPING
     process.add_info('10.0.0.4',
                      any_process_info_by_state(ProcessStates.STOPPING))
     # check state STOPPING
     self.assertEqual(ProcessStates.STOPPING, process.state)
     # invalidate STOPPING one
     process.invalidate_address('10.0.0.4', False)
     # check state became UNKNOWN on invalidated address
     self.assertEqual(ProcessStates.UNKNOWN,
                      process.infos['10.0.0.4']['state'])
     # check that synthetic state became STOPPED
     self.assertEqual(ProcessStates.STOPPED, process.state)
示例#7
0
 def test_accept_extra_arguments(self):
     """ Test the possibility to add extra arguments when starting the process, iaw the process rules. """
     from supvisors.process import ProcessStatus
     info = any_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     self.supvisors.info_source.autorestart.return_value = False
     self.assertTrue(process.accept_extra_arguments())
     self.supvisors.info_source.autorestart.return_value = True
     self.assertFalse(process.accept_extra_arguments())
示例#8
0
 def test_stopped_running(self):
     """ Test the stopped / running status. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # test with STOPPED process
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertTrue(process.stopped())
     self.assertFalse(process.running())
     self.assertFalse(process.running_on('10.0.0.1'))
     self.assertFalse(process.pid_running_on('10.0.0.1'))
     # test with BACKOFF process
     info = any_process_info_by_state(ProcessStates.BACKOFF)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.stopped())
     self.assertTrue(process.running())
     self.assertTrue(process.running_on('10.0.0.1'))
     self.assertFalse(process.running_on('10.0.0.2'))
     self.assertFalse(process.pid_running_on('10.0.0.1'))
     self.assertFalse(process.pid_running_on('10.0.0.2'))
     # test with RUNNING process
     info = any_process_info_by_state(ProcessStates.RUNNING)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.stopped())
     self.assertTrue(process.running())
     self.assertTrue(process.running_on('10.0.0.1'))
     self.assertFalse(process.running_on('10.0.0.2'))
     self.assertTrue(process.pid_running_on('10.0.0.1'))
     self.assertFalse(process.pid_running_on('10.0.0.2'))
     # test with STOPPING process
     info = any_process_info_by_state(ProcessStates.STOPPING)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.stopped())
     self.assertFalse(process.running())
     self.assertFalse(process.running_on('10.0.0.1'))
     self.assertFalse(process.running_on('10.0.0.2'))
     self.assertFalse(process.pid_running_on('10.0.0.1'))
     self.assertFalse(process.pid_running_on('10.0.0.2'))
示例#9
0
 def test_add_process(self):
     """ Test the add_process method. """
     from supvisors.address import AddressStatus
     from supvisors.process import ProcessStatus
     status = AddressStatus('10.0.0.1', self.supvisors.logger)
     info = any_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     status.add_process(process)
     # check that process is stored
     self.assertIn(process.namespec(), status.processes.keys())
     self.assertIs(process, status.processes[process.namespec()])
示例#10
0
 def test_pid_process(self):
     """ Test the pid_process method. """
     from supvisors.address import AddressStatus
     from supvisors.process import ProcessStatus
     status = AddressStatus('10.0.0.1', self.supvisors.logger)
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'], self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         status.add_process(process)
     # check the namespec and pid of the running processes
     self.assertItemsEqual([('sample_test_1:xfontsel', 80879), ('sample_test_2:yeux_01', 80882)], status.pid_processes())
示例#11
0
 def test_stopped(self):
     """ Test the stopped method. """
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     application = ApplicationStatus('ApplicationTest', self.supvisors.logger)
     self.assertTrue(application.stopped())
     # add a stopped process
     info = any_stopped_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     application.add_process(process)
     application.update_status()
     self.assertTrue(application.stopped())
     # add a running process
     info = any_running_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     application.add_process(process)
     application.update_status()
     self.assertFalse(application.stopped())
示例#12
0
 def test_update_status(self):
     """ Test the update of state and running addresses. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # update_status is called in the construction
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.STOPPED, process.state)
     self.assertTrue(process.expected_exit)
     # replace with an EXITED process info
     process.infos['10.0.0.1'] = any_process_info_by_state(
         ProcessStates.EXITED)
     process.update_status('10.0.0.1', ProcessStates.EXITED, False)
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.EXITED, process.state)
     self.assertFalse(process.expected_exit)
     # add a STARTING process info
     process.infos['10.0.0.2'] = any_process_info_by_state(
         ProcessStates.STARTING)
     process.update_status('10.0.0.2', ProcessStates.STARTING, True)
     self.assertSetEqual({'10.0.0.2'}, process.addresses)
     self.assertEqual(ProcessStates.STARTING, process.state)
     self.assertTrue(process.expected_exit)
     # add a BACKOFF process info
     process.infos['10.0.0.3'] = any_process_info_by_state(
         ProcessStates.BACKOFF)
     process.update_status('10.0.0.3', ProcessStates.STARTING, True)
     self.assertSetEqual({'10.0.0.3', '10.0.0.2'}, process.addresses)
     self.assertEqual(ProcessStates.BACKOFF, process.state)
     self.assertTrue(process.expected_exit)
     # replace STARTING process info with RUNNING
     process.infos['10.0.0.2'] = any_process_info_by_state(
         ProcessStates.RUNNING)
     process.update_status('10.0.0.2', ProcessStates.RUNNING, True)
     self.assertSetEqual({'10.0.0.3', '10.0.0.2'}, process.addresses)
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertTrue(process.expected_exit)
     # replace BACKOFF process info with FATAL
     process.infos['10.0.0.3'] = any_process_info_by_state(
         ProcessStates.FATAL)
     process.update_status('10.0.0.3', ProcessStates.FATAL, False)
     self.assertSetEqual({'10.0.0.2'}, process.addresses)
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertTrue(process.expected_exit)
     # replace RUNNING process info with STOPPED
     process.infos['10.0.0.2'] = any_process_info_by_state(
         ProcessStates.STOPPED)
     process.update_status('10.0.0.2', ProcessStates.STOPPED, False)
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.STOPPED, process.state)
     self.assertFalse(process.expected_exit)
示例#13
0
 def test_running_process(self):
     """ Test the running_process method. """
     from supvisors.address import AddressStatus
     from supvisors.process import ProcessStatus
     status = AddressStatus('10.0.0.1', self.supvisors.logger)
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'], self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         status.add_process(process)
     # check the name of the running processes
     self.assertItemsEqual(['late_segv','segv', 'xfontsel', 'yeux_01'],
         [proc.process_name for proc in status.running_processes()])
示例#14
0
 def test_add_process(self):
     """ Test the add_process method. """
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     application = ApplicationStatus('ApplicationTest', self.supvisors.logger)
     # add a process to the application
     info = any_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     application.add_process(process)
     # check that process is stored
     self.assertIn(process.process_name, application.processes.keys())
     self.assertIs(process, application.processes[process.process_name])
示例#15
0
 def test_add_info(self):
     """ Test the addition of a process info into the ProcessStatus. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # ProcessStatus constructor uses add_info
     info = process_info_by_name('xclock')
     self.assertNotIn('uptime', info)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     # check contents
     self.assertEqual(1, len(process.infos))
     self.assertIs(info, process.infos['10.0.0.1'])
     self.assertGreater(process.last_event_time, 0)
     last_event_time = process.last_event_time
     self.assertIn('uptime', info)
     self.assertEqual(info['now'] - info['start'], info['uptime'])
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.STOPPING, process.state)
     self.assertTrue(process.expected_exit)
     # test that address is unchanged
     self.assertListEqual(['*'], process.rules.addresses)
     # update rules to test '#'
     process.rules.addresses = ['#']
     # replace with an EXITED process info
     info = any_process_info_by_state(ProcessStates.EXITED)
     process.add_info('10.0.0.1', info)
     # check contents
     self.assertEqual(1, len(process.infos))
     self.assertIs(info, process.infos['10.0.0.1'])
     self.assertGreaterEqual(process.last_event_time, last_event_time)
     last_event_time = process.last_event_time
     self.assertIn('uptime', info)
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.EXITED, process.state)
     self.assertTrue(process.expected_exit)
     # the firefox process has a procnumber of 0 and address '10.0.0.1' has an index of 1
     # address rule remains unchanged
     self.assertListEqual(['#'], process.rules.addresses)
     # add a RUNNING process info
     info = any_process_info_by_state(ProcessStates.RUNNING)
     process.add_info('10.0.0.2', info)
     # check contents
     self.assertEqual(2, len(process.infos))
     self.assertIs(info, process.infos['10.0.0.2'])
     self.assertGreaterEqual(process.last_event_time, last_event_time)
     self.assertEqual({'10.0.0.2'}, process.addresses)
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertTrue(process.expected_exit)
     # the xfontsel process has a procnumber of 2 and address '10.0.0.2' has an index of 2
     # address rule changes to '10.0.0.2'
     self.assertListEqual(['10.0.0.2'], process.rules.addresses)
示例#16
0
 def test_invalidate_address(self):
     """ Test the invalidation of addresses. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # create conflict directly with 3 process info
     info = any_process_info_by_state(ProcessStates.BACKOFF)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     process.add_info('10.0.0.2', any_process_info_by_state(ProcessStates.RUNNING))
     process.add_info('10.0.0.3', any_process_info_by_state(ProcessStates.STARTING))
     # check the conflict
     self.assertTrue(process.conflicting())
     self.assertEqual(ProcessStates.RUNNING, process.state)
     # invalidate RUNNING one
     process.invalidate_address('10.0.0.2')
     # check UNKNOWN
     self.assertEqual(ProcessStates.UNKNOWN, process.infos['10.0.0.2']['state'])
     # check the conflict
     self.assertTrue(process.conflicting())
     # check new synthetic state
     self.assertEqual(ProcessStates.BACKOFF, process.state)
     # invalidate BACKOFF one
     process.invalidate_address('10.0.0.1')
     # check UNKNOWN
     self.assertEqual(ProcessStates.UNKNOWN, process.infos['10.0.0.1']['state'])
     # check 1 address: no conflict
     self.assertFalse(process.conflicting())
     # check state (running process)
     self.assertEqual(ProcessStates.STARTING, process.state)
     # invalidate STARTING one
     process.invalidate_address('10.0.0.3')
     # check UNKNOWN
     self.assertEqual(ProcessStates.UNKNOWN, process.infos['10.0.0.3']['state'])
     # check 0 address: no conflict
     self.assertFalse(process.conflicting())
     # check state FATAL
     self.assertEqual(ProcessStates.FATAL, process.state)
     # check mark_for_restart
     self.assertFalse(process.mark_for_restart)
     # add one STOPPING
     process.add_info('10.0.0.4', any_process_info_by_state(ProcessStates.STOPPING))
     # check state STOPPING
     self.assertEqual(ProcessStates.STOPPING, process.state)
     # invalidate STOPPING one
     process.invalidate_address('10.0.0.4')
     # check UNKNOWN
     self.assertEqual(ProcessStates.UNKNOWN, process.infos['10.0.0.4']['state'])
     # check state STOPPED
     self.assertEqual(ProcessStates.STOPPED, process.state)
示例#17
0
 def test_serialization(self):
     """ Test the serialization of the ProcessStatus. """
     import pickle
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # test with a STOPPED process
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     serialized = process.serial()
     self.assertDictEqual(serialized, {'application_name': info['group'], 'process_name': info['name'],
         'statecode': 0, 'statename': 'STOPPED',
         'expected_exit': not info['spawnerr'], 'last_event_time': process.last_event_time, 'addresses': []})
     # test that returned structure is serializable using pickle
     dumped = pickle.dumps(serialized)
     loaded = pickle.loads(dumped)
     self.assertDictEqual(serialized, loaded)
示例#18
0
 def test_conflicting(self):
     """ Test the process conflicting rules. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # when there is only one STOPPED process info, there is no conflict
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertFalse(process.conflicting())
     # the addition of a running address, still no conflict
     process.addresses.add('10.0.0.2')
     self.assertFalse(process.conflicting())
     # the addition of a new running address raises a conflict
     process.addresses.add('10.0.0.4')
     self.assertTrue(process.conflicting())
     # remove the first running address to solve the conflict
     process.addresses.remove('10.0.0.2')
     self.assertFalse(process.conflicting())
示例#19
0
 def test_add_info(self):
     """ Test the addition of a process info into the ProcessStatus. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # ProcessStatus constructor uses add_info
     info = any_process_info_by_state(ProcessStates.STOPPING)
     self.assertNotIn('event_time', info)
     self.assertNotIn('local_time', info)
     self.assertNotIn('uptime', info)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     # check contents
     self.assertEqual(1, len(process.infos))
     self.assertIs(info, process.infos['10.0.0.1'])
     self.assertIsNotNone(process.last_event_time)
     last_event_time = process.last_event_time
     self.assertIn('event_time', info)
     self.assertIn('local_time', info)
     self.assertIn('uptime', info)
     self.assertEqual(last_event_time, info['event_time'])
     self.assertEqual(last_event_time, info['now'])
     self.assertEqual(info['now'] - info['start'], info['uptime'])
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.STOPPING, process.state)
     self.assertTrue(process.expected_exit)
     # replace with an EXITED process info
     info = any_process_info_by_state(ProcessStates.EXITED)
     process.add_info('10.0.0.1', info)
     # check contents
     self.assertEqual(1, len(process.infos))
     self.assertIs(info, process.infos['10.0.0.1'])
     self.assertIsNotNone(process.last_event_time)
     self.assertNotEqual(last_event_time, process.last_event_time)
     last_event_time = process.last_event_time
     self.assertIn('event_time', info)
     self.assertIn('local_time', info)
     self.assertIn('uptime', info)
     self.assertEqual(last_event_time, info['event_time'])
     self.assertEqual(last_event_time, info['now'])
     self.assertFalse(process.addresses)
     self.assertEqual(ProcessStates.EXITED, process.state)
     self.assertTrue(process.expected_exit)
     # add a RUNNING process info
     process.add_info('10.0.0.2', any_process_info_by_state(ProcessStates.RUNNING))
示例#20
0
 def test_loading(self):
     """ Test the loading method. """
     from supvisors.address import AddressStatus
     from supvisors.process import ProcessStatus
     status = AddressStatus('10.0.0.1', self.supvisors.logger)
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'], self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         status.add_process(process)
     # check the loading of the address: gives 5 (1 per running process) by default because no rule has been loaded
     self.assertEqual(4, status.loading())
     # change expected_loading of any stopped process
     process = random.choice([proc for proc in status.processes.values() if proc.stopped()])
     process.rules.expected_loading = 50
     self.assertEqual(4, status.loading())
     # change expected_loading of any running process
     process = random.choice([proc for proc in status.processes.values() if proc.running()])
     process.rules.expected_loading = 50
     self.assertEqual(53, status.loading())
示例#21
0
 def test_create(self):
     """ Test the values set at construction. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessRules, ProcessStatus
     info = any_stopped_process_info()
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     # check application default attributes
     self.assertIs(self.supvisors, process.supvisors)
     self.assertEqual(info['group'], process.application_name)
     self.assertEqual(info['name'], process.process_name)
     self.assertEqual(ProcessStates.UNKNOWN, process.state)
     self.assertTrue(process.expected_exit)
     self.assertEqual(0, process.last_event_time)
     self.assertEqual(set(), process.addresses)
     self.assertEqual({}, process.infos)
     self.assertEqual('', process.extra_args)
     self.assertFalse(process.ignore_wait_exit)
     # rules part
     self.assertDictEqual(
         ProcessRules(self.supvisors).__dict__, process.rules.__dict__)
示例#22
0
 def check_valid(self, parser):
     """ Test the parsing of a valid XML. """
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     from supvisors.ttypes import RunningFailureStrategies, StartingFailureStrategies
     # test models & patterns
     self.assertItemsEqual([
         'dummy_model_01', 'dummy_model_02', 'dummy_model_03',
         'dummy_model_04'
     ], parser.models.keys())
     self.assertItemsEqual(['dummies_', 'dummies_01_', 'dummies_02_'],
                           parser.patterns.keys())
     # check unknown application
     application = ApplicationStatus('dummy_application_X',
                                     self.supvisors.logger)
     parser.load_application_rules(application)
     self.assert_default_application_rules(application.rules)
     # check first application
     application = ApplicationStatus('dummy_application_A',
                                     self.supvisors.logger)
     parser.load_application_rules(application)
     self.assert_default_application_rules(application.rules)
     # check second application
     application = ApplicationStatus('dummy_application_B',
                                     self.supvisors.logger)
     parser.load_application_rules(application)
     self.assert_application_rules(application.rules, 1, 4,
                                   StartingFailureStrategies.STOP,
                                   RunningFailureStrategies.RESTART_PROCESS)
     # check third application
     application = ApplicationStatus('dummy_application_C',
                                     self.supvisors.logger)
     parser.load_application_rules(application)
     self.assert_application_rules(
         application.rules, 20, 0, StartingFailureStrategies.ABORT,
         RunningFailureStrategies.STOP_APPLICATION)
     # check fourth application
     application = ApplicationStatus('dummy_application_D',
                                     self.supvisors.logger)
     parser.load_application_rules(application)
     self.assert_application_rules(
         application.rules, 0, 100, StartingFailureStrategies.CONTINUE,
         RunningFailureStrategies.RESTART_APPLICATION)
     # check program from unknown application: all default
     process = ProcessStatus('dummy_application_X', 'dummy_program_X0',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check unknown program from known application: all default
     process = ProcessStatus('dummy_application_A', 'dummy_program_A0',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check known program from known but not related application: all default
     process = ProcessStatus('dummy_application_A', 'dummy_program_B1',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check known empty program
     process = ProcessStatus('dummy_application_B', 'dummy_program_B0',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check dash addresses and valid other values
     process = ProcessStatus('dummy_application_B', 'dummy_program_B1',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['#'], 3, 50, True, False, 5,
                               RunningFailureStrategies.CONTINUE)
     # check single address with required not applicable and out of range loading
     process = ProcessStatus('dummy_application_B', 'dummy_program_B2',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['10.0.0.3'], 0, 0, False,
                               False, 1,
                               RunningFailureStrategies.RESTART_PROCESS)
     # check wildcard address, optional and max loading
     process = ProcessStatus('dummy_application_B', 'dummy_program_B3',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['*'], 0, 0, False, False,
                               100,
                               RunningFailureStrategies.STOP_APPLICATION)
     # check multiple addresses, all other incorrect values
     process = ProcessStatus('dummy_application_B', 'dummy_program_B4',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules,
                               ['10.0.0.3', '10.0.0.1', '10.0.0.5'], 0, 0,
                               False, False, 1,
                               RunningFailureStrategies.RESTART_APPLICATION)
     # check empty reference
     process = ProcessStatus('dummy_application_C', 'dummy_program_C0',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check unknown reference
     process = ProcessStatus('dummy_application_C', 'dummy_program_C1',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
     # check known reference
     process = ProcessStatus('dummy_application_C', 'dummy_program_C2',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['*'], 0, 0, False, False, 25,
                               RunningFailureStrategies.STOP_APPLICATION)
     # check other known reference
     process = ProcessStatus('dummy_application_C', 'dummy_program_C3',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['#'], 1, 0, True, True, 1,
                               RunningFailureStrategies.CONTINUE)
     # check pattern with single matching and reference
     process = ProcessStatus('dummy_application_D', 'dummies_any',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['10.0.0.4', '10.0.0.2'], 0,
                               100, False, False, 10,
                               RunningFailureStrategies.CONTINUE)
     # check pattern with multiple matching and configuration
     process = ProcessStatus('dummy_application_D', 'dummies_01_any',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_process_rules(process.rules, ['#'], 1, 1, False, True, 75,
                               RunningFailureStrategies.CONTINUE)
     # check pattern with multiple matching and incorrect reference
     process = ProcessStatus('dummy_application_D', 'any_dummies_02_',
                             self.supvisors)
     parser.load_process_rules(process)
     self.assert_default_process_rules(process.rules)
示例#23
0
 def test_update_status(self):
     """ Test the rules to update the status of the application method. """
     from supervisor.states import ProcessStates
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     from supvisors.ttypes import ApplicationStates
     application = ApplicationStatus('ApplicationTest',
                                     self.supvisors.logger)
     # add processes to the application
     for info in ProcessInfoDatabase:
         process = ProcessStatus(info['group'], info['name'],
                                 self.supvisors)
         process.add_info('10.0.0.1', info.copy())
         application.add_process(process)
     # init status
     # there are lots of states but the 'strongest' is STARTING
     # STARTING is a 'running' state so major/minor failures are applicable
     application.update_status()
     self.assertEqual(ApplicationStates.STARTING, application.state)
     # there is a FATAL state in the process database
     # no rule is set for processes, so there are only minor failures
     self.assertFalse(application.major_failure)
     self.assertTrue(application.minor_failure)
     # set FATAL process to major
     fatal_process = next((process
                           for process in application.processes.values()
                           if process.state == ProcessStates.FATAL), None)
     fatal_process.rules.required = True
     # update status. major failure is now expected
     application.update_status()
     self.assertEqual(ApplicationStates.STARTING, application.state)
     self.assertTrue(application.major_failure)
     self.assertFalse(application.minor_failure)
     # set STARTING process to RUNNING
     starting_process = next(
         (process for process in application.processes.values()
          if process.state == ProcessStates.STARTING), None)
     starting_process.state = ProcessStates.RUNNING
     # update status. there is still one BACKOFF process leading to STARTING application
     application.update_status()
     self.assertEqual(ApplicationStates.STARTING, application.state)
     self.assertTrue(application.major_failure)
     self.assertFalse(application.minor_failure)
     # set BACKOFF process to EXITED
     backoff_process = next(
         (process for process in application.processes.values()
          if process.state == ProcessStates.BACKOFF), None)
     backoff_process.state = ProcessStates.EXITED
     # update status. the 'strongest' state is now STOPPING
     # as STOPPING is not a 'running' state, failures are not applicable
     application.update_status()
     self.assertEqual(ApplicationStates.STOPPING, application.state)
     self.assertFalse(application.major_failure)
     self.assertFalse(application.minor_failure)
     # set STOPPING process to STOPPED
     stopping_process = next(
         (process for process in application.processes.values()
          if process.state == ProcessStates.STOPPING), None)
     stopping_process.state = ProcessStates.STOPPED
     # update status. the 'strongest' state is now RUNNING
     # failures are applicable again
     application.update_status()
     self.assertEqual(ApplicationStates.RUNNING, application.state)
     self.assertTrue(application.major_failure)
     self.assertFalse(application.minor_failure)
     # set RUNNING processes to STOPPED
     for process in application.processes.values():
         if process.state == ProcessStates.RUNNING:
             process.state = ProcessStates.STOPPED
     # update status. the 'strongest' state is now RUNNING
     # failures are not applicable anymore
     application.update_status()
     self.assertEqual(ApplicationStates.STOPPED, application.state)
     self.assertFalse(application.major_failure)
     self.assertFalse(application.minor_failure)
示例#24
0
 def test_deployment_state(self):
     """ Test the Deployment state of the FSM. """
     from supvisors.application import ApplicationStatus
     from supvisors.process import ProcessStatus
     from supvisors.statemachine import AbstractState, DeploymentState
     from supvisors.ttypes import ApplicationStates, SupvisorsStates
     state = DeploymentState(self.supvisors)
     self.assertIsInstance(state, AbstractState)
     # test enter method
     # test that start_applications is  called only when local address is the master address
     with patch.object(self.supvisors.starter,
                       'start_applications') as mocked_starter:
         self.supvisors.context.master = False
         state.enter()
         self.assertEqual(0, mocked_starter.call_count)
         # now master address is local
         self.supvisors.context.master = True
         state.enter()
         self.assertEqual(1, mocked_starter.call_count)
     # create application context
     application = ApplicationStatus('sample_test_2', self.supvisors.logger)
     self.supvisors.context.applications['sample_test_2'] = application
     for info in database_copy():
         if info['group'] == 'sample_test_2':
             process = ProcessStatus(info['group'], info['name'],
                                     self.supvisors)
             process.rules.start_sequence = len(process.namespec()) % 3
             process.rules.stop_sequence = len(process.namespec()) % 3 + 1
             process.add_info('10.0.0.1', info)
             application.add_process(process)
     # test application updates
     self.supvisors.context.master = False
     self.assertEqual(ApplicationStates.STOPPED, application.state)
     self.assertFalse(application.minor_failure)
     self.assertFalse(application.major_failure)
     self.assertDictEqual({}, application.start_sequence)
     self.assertDictEqual({}, application.stop_sequence)
     state.enter()
     application = self.supvisors.context.applications['sample_test_2']
     self.assertEqual(ApplicationStates.RUNNING, application.state)
     self.assertTrue(application.minor_failure)
     self.assertFalse(application.major_failure)
     # list order may differ, so break down
     self.assertItemsEqual([0, 1], application.start_sequence.keys())
     self.assertItemsEqual([
         application.processes['yeux_01'], application.processes['yeux_00']
     ], application.start_sequence[0])
     self.assertItemsEqual([application.processes['sleep']],
                           application.start_sequence[1])
     self.assertItemsEqual([1, 2], application.stop_sequence.keys())
     self.assertItemsEqual([
         application.processes['yeux_01'], application.processes['yeux_00']
     ], application.stop_sequence[1])
     self.assertItemsEqual([application.processes['sleep']],
                           application.stop_sequence[2])
     # test next method
     # stay in DEPLOYMENT if local is master and a deployment is in progress, whatever the conflict status
     with patch.object(self.supvisors.starter,
                       'check_starting',
                       return_value=False):
         for conflict in [True, False]:
             with patch.object(self.supvisors.context,
                               'conflicting',
                               return_value=conflict):
                 self.supvisors.context.master = True
                 result = state.next()
                 self.assertEqual(SupvisorsStates.DEPLOYMENT, result)
     # return OPERATION if local is not master and no conflict, whatever the starting status
     self.supvisors.context.master = False
     with patch.object(self.supvisors.context,
                       'conflicting',
                       return_value=False):
         for starting in [True, False]:
             with patch.object(self.supvisors.starter,
                               'check_starting',
                               return_value=starting):
                 result = state.next()
                 self.assertEqual(SupvisorsStates.OPERATION, result)
     # return OPERATION if a deployment is in progress and no conflict, whatever the master status
     with patch.object(self.supvisors.starter,
                       'check_starting',
                       return_value=True):
         with patch.object(self.supvisors.context,
                           'conflicting',
                           return_value=False):
             for master in [True, False]:
                 self.supvisors.context.master = master
                 result = state.next()
                 self.assertEqual(SupvisorsStates.OPERATION, result)
     # return CONCILIATION if local is not master and conflict detected, whatever the starting status
     self.supvisors.context.master = False
     with patch.object(self.supvisors.context,
                       'conflicting',
                       return_value=True):
         for starting in [True, False]:
             with patch.object(self.supvisors.starter,
                               'check_starting',
                               return_value=starting):
                 result = state.next()
                 self.assertEqual(SupvisorsStates.CONCILIATION, result)
     # return CONCILIATION if a deployment is in progress and conflict detected, whatever the master status
     with patch.object(self.supvisors.starter,
                       'check_starting',
                       return_value=True):
         with patch.object(self.supvisors.context,
                           'conflicting',
                           return_value=True):
             for master in [True, False]:
                 self.supvisors.context.master = master
                 result = state.next()
                 self.assertEqual(SupvisorsStates.CONCILIATION, result)
     # no exit implementation. just call it without test
     state.exit()
示例#25
0
 def test_update_info(self):
     """ Test the update of the ProcessStatus upon reception of a process event. """
     from supervisor.states import ProcessStates
     from supvisors.process import ProcessStatus
     # add a STOPPED process infos into a process status
     info = any_process_info_by_state(ProcessStates.STOPPED)
     process = ProcessStatus(info['group'], info['name'], self.supvisors)
     process.add_info('10.0.0.1', info)
     self.assertEqual(ProcessStates.STOPPED,
                      process.infos['10.0.0.1']['state'])
     self.assertEqual(ProcessStates.STOPPED, process.state)
     self.assertFalse(process.addresses)
     local_time = process.infos['10.0.0.1']['local_time']
     # update with a STARTING event on an unknown address
     process.update_info('10.0.0.2', {
         'state': ProcessStates.STARTING,
         'now': 10
     })
     # check no change
     info = process.infos['10.0.0.1']
     self.assertEqual(ProcessStates.STOPPED,
                      process.infos['10.0.0.1']['state'])
     self.assertEqual(ProcessStates.STOPPED, process.state)
     self.assertFalse(process.addresses)
     # update with a STARTING event
     process.update_info('10.0.0.1', {
         'state': ProcessStates.STARTING,
         'now': 10
     })
     # check changes
     info = process.infos['10.0.0.1']
     self.assertEqual(ProcessStates.STARTING, info['state'])
     self.assertEqual(ProcessStates.STARTING, process.state)
     self.assertSetEqual({'10.0.0.1'}, process.addresses)
     self.assertEqual(10, process.last_event_time)
     self.assertEqual(10, info['event_time'])
     self.assertEqual(10, info['now'])
     self.assertGreaterEqual(info['local_time'], local_time)
     local_time = info['local_time']
     self.assertEqual(10, info['start'])
     self.assertEqual(0, info['stop'])
     self.assertEqual(0, info['uptime'])
     # update with a RUNNING event
     process.update_info('10.0.0.1', {
         'state': ProcessStates.RUNNING,
         'now': 15,
         'pid': 1234
     })
     # check changes
     self.assertEqual(ProcessStates.RUNNING, info['state'])
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertSetEqual({'10.0.0.1'}, process.addresses)
     self.assertEqual(15, process.last_event_time)
     self.assertEqual(1234, info['pid'])
     self.assertEqual(15, info['event_time'])
     self.assertEqual(15, info['now'])
     self.assertGreaterEqual(info['local_time'], local_time)
     local_time = info['local_time']
     self.assertEqual(10, info['start'])
     self.assertEqual(0, info['stop'])
     self.assertEqual(5, info['uptime'])
     # add a new STOPPED process info and update with STARTING / RUNNING events
     process.add_info('10.0.0.2',
                      any_process_info_by_state(ProcessStates.STOPPED))
     process.update_info('10.0.0.2', {
         'state': ProcessStates.STARTING,
         'now': 20
     })
     process.update_info('10.0.0.2', {
         'state': ProcessStates.RUNNING,
         'now': 25,
         'pid': 4321
     })
     # check state and addresses
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertSetEqual({'10.0.0.1', '10.0.0.2'}, process.addresses)
     self.assertEqual(25, process.last_event_time)
     # update with an EXITED event
     process.update_info('10.0.0.1', {
         'state': ProcessStates.EXITED,
         'now': 30,
         'expected': False
     })
     # check changes
     self.assertEqual(ProcessStates.EXITED, info['state'])
     self.assertEqual(ProcessStates.RUNNING, process.state)
     self.assertSetEqual({'10.0.0.2'}, process.addresses)
     self.assertEqual(30, process.last_event_time)
     self.assertEqual(0, info['pid'])
     self.assertEqual(30, info['event_time'])
     self.assertEqual(30, info['now'])
     self.assertGreaterEqual(info['local_time'], local_time)
     self.assertEqual(10, info['start'])
     self.assertEqual(30, info['stop'])
     self.assertEqual(0, info['uptime'])
     self.assertFalse(info['expected'])
     # update with an STOPPING event
     info = process.infos['10.0.0.2']
     local_time = info['local_time']
     process.update_info('10.0.0.2', {
         'state': ProcessStates.STOPPING,
         'now': 35
     })
     # check changes
     self.assertEqual(ProcessStates.STOPPING, info['state'])
     self.assertEqual(ProcessStates.STOPPING, process.state)
     self.assertSetEqual({'10.0.0.2'}, process.addresses)
     self.assertEqual(35, process.last_event_time)
     self.assertEqual(4321, info['pid'])
     self.assertEqual(35, info['event_time'])
     self.assertEqual(35, info['now'])
     self.assertGreaterEqual(info['local_time'], local_time)
     local_time = info['local_time']
     self.assertEqual(20, info['start'])
     self.assertEqual(0, info['stop'])
     self.assertEqual(15, info['uptime'])
     self.assertTrue(info['expected'])
     # update with an STOPPED event
     process.update_info('10.0.0.2', {
         'state': ProcessStates.STOPPED,
         'now': 40
     })
     # check changes
     self.assertEqual(ProcessStates.STOPPED, info['state'])
     self.assertEqual(ProcessStates.STOPPED, process.state)
     self.assertFalse(process.addresses)
     self.assertEqual(40, process.last_event_time)
     self.assertEqual(0, info['pid'])
     self.assertEqual(40, info['event_time'])
     self.assertEqual(40, info['now'])
     self.assertGreaterEqual(info['local_time'], local_time)
     self.assertEqual(20, info['start'])
     self.assertEqual(40, info['stop'])
     self.assertEqual(0, info['uptime'])
     self.assertTrue(info['expected'])